Motor both ways on an Arduino Uno
An L293D H bridge turns a DC motor forward and back from three Uno pins, and shows what braking does that coasting does not. The whole build, an Arduino Uno and 2 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.
Step by step, with the wiring and the common mistakes: Arduino L293D Motor Driver: Forward and Reverse
What you'll learn
- How an H bridge reverses a motor
- Braking compared with coasting
- Speed control with PWM on an enable pin
- Voltage lost inside a driver chip
- Built-in clamp diodes on the L293D
- Difficulty: Intermediate
- Time: About 20 minutes
- Board: Arduino Uno R3
- Parts: 4
How it works
An L293D H bridge lets the Uno spin a DC motor either way. Pin 7 and pin 8 pick the direction, and pin 9 drives the enable pin with PWM for speed. The sketch loops through forward, brake, reverse, coast, half throttle forward and brake.
Braking and coasting look different. With both inputs equal, the chip shorts the motor and it stops fast. With enable at 0, it lets go and winds down slowly. The L293D also loses about 1.2 V in each of two output stages, so the motor sees much less than 5 V.
Parts list
4 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × Motor driver, L293DIn Claw Machine Kit.
- 1 × DC motorIn Robot Car Kit.
Kits that can build it
These 8 starter kits have every part in the circuit. Each kit's page lists what else it can build.
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 pin | Connects to |
|---|---|
| Motor driver, L293D pin EN12 | Arduino Uno R3 pin 9 |
| Motor driver, L293D pin IN2 | Arduino Uno R3 pin 8 |
| Motor driver, L293D pin IN1 | Arduino Uno R3 pin 7 |
| Motor driver, L293D pin VS | Arduino Uno R3 pin 5V |
| Motor driver, L293D pin VSS | Arduino Uno R3 pin 5V |
| Motor driver, L293D pin GND1 | Arduino Uno R3 pin GND |
| DC motor pin 1 | Motor driver, L293D pin OUT1 |
| DC motor pin 2 | Motor 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.
// H bridge: a motor that goes both ways, on an L293D.
//
// pin 9 EN12, the PWM that sets the speed
// pin 7 IN1
// pin 8 IN2
// L293D VSS (pin 16) to 5 V, VS (pin 8) to 5 V, any GND pin to GND
// OUT1 and OUT2 to the motor's two terminals
//
// The transistor in the `motor` example can switch a motor on and off. It
// cannot make it turn the other way, because a transistor only knows how to
// pull one end down. Turning a motor round means being able to put either end
// at the supply and the other at ground, and four switches in an H around the
// motor is the only way to do that. That is what this chip has: four half
// bridges, two of them per motor.
//
// IN1 IN2 what happens
// 1 0 OUT1 high, OUT2 low: forward
// 0 1 the other way around: reverse
// 0 0 both ends at ground: brake
// 1 1 both ends at 5 V -- brake
//
// and EN12 low lifts both ends off the motor entirely, which is coasting. The
// difference between braking and coasting is worth watching on the canvas: a
// braked motor stops in a fraction of a second because its own back EMF is
// shorted through the chip, and a coasting one winds down for seconds.
//
// # Where the volts go
//
// The output stages are Darlingtons, and a Darlington keeps about 1.2 V for
// itself. There is one in the high side and another in the low side, so a
// motor across a 5 V supply here sees about 2.6 V and turns at about half the
// speed you were expecting. That is not the model being coy: it is the number
// on the datasheet, and it is why the grown-up answer for anything that
// matters is a MOSFET bridge.
//
// The D on the end of the name is the eight clamp diodes inside, which is why
// this circuit needs none of the flyback diodes the transistor one does.
//
// # The PWM on the enable, and why half throttle is not half speed
//
// Chopping EN with analogWrite is how this chip is usually throttled, and it
// does not brake between pulses; the outputs go high impedance, so the motor
// coasts. With nothing on the shaft there is nothing to slow it down while it
// coasts, so an unloaded motor winds up to the same top speed at any duty,
// just more slowly. Put a load on it and the duty is the throttle it looks
// like. Mokxi's motor has no mechanical load, which is why the last leg of
// this loop reaches the same rpm as the first.
const int ENABLE = 9;
const int IN1 = 7;
const int IN2 = 8;
const int SPEED = 255;
const unsigned long RUN_MS = 2500;
const unsigned long STOP_MS = 800;
void drive(const char *what, int a, int b, int duty) {
digitalWrite(IN1, a);
digitalWrite(IN2, b);
analogWrite(ENABLE, duty);
Serial.print("motor: ");
Serial.println(what);
}
void setup() {
pinMode(ENABLE, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
analogWrite(ENABLE, 0);
Serial.begin(115200);
Serial.println("Mokxi Uno: L293D H bridge on pins 7, 8 and 9");
}
void loop() {
drive("forward", HIGH, LOW, SPEED);
delay(RUN_MS);
// Both inputs the same shorts the motor through the chip. Watch it stop.
drive("brake", LOW, LOW, SPEED);
delay(STOP_MS);
drive("reverse", LOW, HIGH, SPEED);
delay(RUN_MS);
// Enable low lets go of both terminals. Watch it wind down instead.
drive("coast", LOW, HIGH, 0);
delay(STOP_MS * 2);
// And once round at half throttle, to show the PWM working through it.
drive("forward, half throttle", HIGH, LOW, SPEED / 2);
delay(RUN_MS);
drive("brake", HIGH, HIGH, SPEED);
delay(STOP_MS);
}
Code walkthrough
The key functions of the sketch, and what each one does.
drive sketch.ino
Sets IN1 and IN2, writes the duty to ENABLE with analogWrite, and prints the name of the action. Every move in the loop is one call with a different mix of inputs and duty.
void drive(const char *what, int a, int b, int duty) {
digitalWrite(IN1, a);
digitalWrite(IN2, b);
analogWrite(ENABLE, duty);
Serial.print("motor: ");
Serial.println(what);
}loop sketch.ino
Runs the whole demo. Forward for RUN_MS, brake, reverse, coast with duty 0, then forward at half duty, then brake with both inputs HIGH. Each stop lasts STOP_MS, and coast waits twice as long.
void loop() {
drive("forward", HIGH, LOW, SPEED);
delay(RUN_MS);
// Both inputs the same shorts the motor through the chip. Watch it stop.
drive("brake", LOW, LOW, SPEED);
delay(STOP_MS);
drive("reverse", LOW, HIGH, SPEED);
delay(RUN_MS);
// Enable low lets go of both terminals. Watch it wind down instead.
drive("coast", LOW, HIGH, 0);
delay(STOP_MS * 2);
// And once round at half throttle, to show the PWM working through it.
drive("forward, half throttle", HIGH, LOW, SPEED / 2);
delay(RUN_MS);
drive("brake", HIGH, HIGH, SPEED);
delay(STOP_MS);
}setup sketch.ino
Makes pins 9, 7 and 8 outputs, starts with the enable at 0 so the motor is idle, and opens the serial port at 115200.
void setup() {
pinMode(ENABLE, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
analogWrite(ENABLE, 0);
Serial.begin(115200);
Serial.println("Mokxi Uno: L293D H bridge on pins 7, 8 and 9");
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The motor spins the wrong way. This project
Swap the motor's two wires on OUT1 and OUT2, or swap theHIGHandLOWvalues. - It never runs. This project
Both VS and VSS need 5 V, and GND1 needs ground. Check pin 9 goes to EN12. - It is slower than I expected. This project
That is normal here. The chip drops about 2.4 V in total, so the motor gets about 2.6 V from a 5 V supply. - 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. - Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.