Built-in project · Arduino Uno R3

Summer fan: four buttons and an L293D (pins 9 and 10), on an Arduino Uno

A DC motor on an L293D with 1A on pin 10 and 2A on pin 9, and four buttons on pins 4 to 7: three speeds and off, chosen with analogWrite. The whole build, an Arduino Uno and 6 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 20 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $35. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Driving a motor through an H-bridge chip
  • PWM speed control with analogWrite
  • Reading buttons with INPUT_PULLUP
  • Looping over arrays of pins and values
  • Difficulty: Intermediate
  • Time: About 20 minutes
  • Board: Arduino Uno R3
  • Parts: 8

How it works

Four pushbuttons choose how fast a small motor spins. A pin on the Uno cannot run a motor by itself, so an L293D driver does it. Each output of the chip copies its input, with the motor's current behind it.

Pin 9 is held LOW and pin 10 gets PWM from analogWrite. With one input LOW and the other pulsed, the motor turns, and the duty sets the speed.

The buttons are on pins 4, 5, 6 and 7. Each connects its pin to ground when pressed, and the sketch uses the internal pull-ups. Pin 4 is off, 5 is slow, 6 is medium and 7 is fast.

Parts list

8 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Motor driver, L293D pin IN1Arduino Uno R3 pin 10
Motor driver, L293D pin IN2Arduino Uno R3 pin 9
Pushbutton (1) pin 1aArduino Uno R3 pin 7
Pushbutton (2) pin 1aArduino Uno R3 pin 6
Pushbutton (3) pin 1aArduino Uno R3 pin 5
Pushbutton (4) pin 1aArduino Uno R3 pin 4
Motor driver, L293D pin EN12Arduino Uno R3 pin 5V
Motor driver, L293D pin VSArduino Uno R3 pin 5V
Motor driver, L293D pin VSSArduino Uno R3 pin 5V
Motor driver, L293D pin GND1Arduino Uno R3 pin GND
Pushbutton (1) pin 2aArduino Uno R3 pin GND
Pushbutton (2) pin 2aArduino Uno R3 pin GND
Pushbutton (3) pin 2aArduino Uno R3 pin GND
Pushbutton (4) pin 2aArduino Uno R3 pin GND
DC motor pin 1Motor driver, L293D pin OUT1
DC motor pin 2Motor driver, L293D pin OUT2

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// A summer fan: four buttons pick the speed of a motor on an L293D.
//
//   L293D 1,2EN -> 5V   VCC1 (16) and VCC2 (8) -> 5V   GND -> GND
//   L293D 1A -> pin 10   2A -> pin 9   1Y and 2Y -> the motor's two leads
//   buttons on pins 4, 5, 6 and 7, each to GND (internal pull-ups)
//
// A board pin cannot run a motor, so the L293D does it: each Y output copies
// its A input, with the motor's own current behind it. One input HIGH and the
// other LOW turns the motor; both LOW stops it. analogWrite on 1A, with 2A
// held LOW, chooses how fast.
//
// Press a button: pin 4 is off, 5 slow, 6 medium and 7 fast.

const int MOTOR_1A = 10;
const int MOTOR_2A = 9;
const int BUTTONS[4] = {4, 5, 6, 7};
const int SPEEDS[4] = {0, 120, 180, 255};
const char *NAMES[4] = {"off", "slow", "medium", "fast"};

void setup() {
  pinMode(MOTOR_1A, OUTPUT);
  pinMode(MOTOR_2A, OUTPUT);
  digitalWrite(MOTOR_2A, LOW);
  for (int i = 0; i < 4; i++) pinMode(BUTTONS[i], INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Mokxi Uno: fan buttons on 4 (off), 5, 6 and 7 (fast)");
}

void loop() {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(BUTTONS[i]) == LOW) {
      analogWrite(MOTOR_1A, SPEEDS[i]);
      Serial.print("fan: ");
      Serial.println(NAMES[i]);
      delay(200);
    }
  }
}

Code walkthrough

The key functions of the sketch, and what each one does.

setup sketch.ino

Makes the two motor pins outputs and holds MOTOR_2A LOW so the motor can only run one way. It turns each pin in BUTTONS into an INPUT_PULLUP input, which reads HIGH until pressed. Then it opens serial at 9600 baud.

void setup() {
  pinMode(MOTOR_1A, OUTPUT);
  pinMode(MOTOR_2A, OUTPUT);
  digitalWrite(MOTOR_2A, LOW);
  for (int i = 0; i < 4; i++) pinMode(BUTTONS[i], INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Mokxi Uno: fan buttons on 4 (off), 5, 6 and 7 (fast)");
}

loop sketch.ino

Checks each button. A LOW reading means pressed, so it calls analogWrite on MOTOR_1A with the matching value from SPEEDS: 0, 120, 180 or 255. It prints the name and waits 200 ms. The motor keeps its speed until another button is pressed.

void loop() {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(BUTTONS[i]) == LOW) {
      analogWrite(MOTOR_1A, SPEEDS[i]);
      Serial.print("fan: ");
      Serial.println(NAMES[i]);
      delay(200);
    }
  }
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • Nothing happens when I press a button This project
    Each button's other leg must go to GND. With the internal pull-up, pressing joins the pin to ground.
  • The motor does not turn This project
    Check that the L293D enable pin (1,2EN) and both supply pins are on 5 V, and that its ground is joined to the Uno's.
  • The motor is weak or does not turn, and the chip gets hot. Motor driver
    The L293D gives about 600 mA per channel and drops about 1.4 V per side. Use a motor that fits, and for bigger motors pick another driver.
  • Nothing moves even though the inputs are right. Motor driver
    Power both supply pins: VCC1 (pin 16) at 5 V for logic and VCC2 (pin 8) for the motor. Tie the enable pin high, and join all grounds.
  • The motor does not spin, or the pin gets hot or the board resets when it is wired straight to a GPIO pin. DC motor
    A pin gives about 20 mA and a motor needs far more. Drive it through a transistor or motor driver, with its own supply and a shared ground.
  • The transistor or pin is damaged by spikes when the motor stops. DC motor
    Put a flyback diode across the motor, cathode to the positive side. A motor is a coil and kicks back voltage when switched off. Add a 0.1 uF capacitor across the motor terminals to cut noise.
  • The input reads random HIGH and LOW when the button is not pressed. Pushbutton
    A floating pin picks up noise. Add a 10 k pull-down or pull-up resistor, or use INPUT_PULLUP and wire the button between the pin and GND. Then pressed reads LOW.
  • The button seems always pressed, or never changes. Pushbutton
    A 4-leg tactile switch has legs joined in pairs. Place it across the breadboard center gap so the pairs sit on different rows. Wired along one side, the legs are already connected.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.