A knob drives a motor both ways through an L293D on an Arduino Uno
A potentiometer on A0 runs a DC motor on an L293D (inputs on pins 10 and 9, enable on 11): turn it left of the middle to go one way, right to go the other, faster the further you turn. The whole build, an Arduino Uno and 3 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.
What you'll learn
- Reversing a motor with an H-bridge driver
- Direction from two pins, speed from PWM
- Reading a knob with analogRead
- Mapping a centered range to a speed
- Difficulty: Intermediate
- Time: About 20 minutes
- Board: Arduino Uno R3
- Parts: 5
How it works
A knob on A0 controls a DC motor through an L293D motor driver. The middle of the knob, a reading of 512, is stop. Turning one way runs the motor one way, and turning the other way reverses it.
The side of 512 picks the direction, using pins 10 and 9 as the driver inputs. The distance from 512 is mapped to 0 to 255 and sent as PWM on the enable pin, 11. A farther turn means a faster motor.
The loop repeats every 50 ms. The driver's logic and motor supply are both wired to the Uno's 5V here.
Parts list
5 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 motor
- 1 × PotentiometerIn Halloween Prop Kit, Starter Projects Kit.
Kits that can build it
These 7 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 11 |
| Motor driver, L293D pin IN1 | Arduino Uno R3 pin 10 |
| Motor driver, L293D pin IN2 | Arduino Uno R3 pin 9 |
| Motor driver, L293D pin VS | Arduino Uno R3 pin 5V |
| Motor driver, L293D pin VSS | Arduino Uno R3 pin 5V |
| Potentiometer pin 1 | Arduino Uno R3 pin 5V |
| Motor driver, L293D pin GND1 | Arduino Uno R3 pin GND |
| Potentiometer pin 3 | Arduino Uno R3 pin GND |
| Potentiometer pin 2 | Arduino Uno R3 pin A0 |
| 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.
// A knob drives a motor both ways through an L293D.
//
// L293D 1A -> pin 10 2A -> pin 9 1,2EN -> pin 11
// L293D VCC1 -> 5V VCC2 -> the motor supply GND -> GND
// 1Y and 2Y -> the motor the knob's wiper -> A0
//
// The middle of the knob, 512, is stop. Further from it is faster: the
// distance becomes the PWM on the enable pin. Which side of the middle sets
// the direction: 1A HIGH and 2A LOW one way, the other way round the other.
const int IN1 = 10;
const int IN2 = 9;
const int ENABLE = 11;
void drive(bool forward, int speed) {
digitalWrite(IN1, forward ? HIGH : LOW);
digitalWrite(IN2, forward ? LOW : HIGH);
analogWrite(ENABLE, constrain(speed, 0, 255));
}
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENABLE, OUTPUT);
Serial.begin(9600);
Serial.println("Mokxi Uno: turn the knob away from the middle");
}
void loop() {
int knob = analogRead(A0);
bool forward = knob > 512;
int speed = map(abs(knob - 512), 0, 512, 0, 255);
drive(forward, speed);
delay(50);
}
Code walkthrough
The key functions of the sketch, and what each one does.
drive sketch.ino
It takes a direction and a speed. It sets IN1 and IN2 to opposite levels, which picks the direction. Then it writes the speed to ENABLE with analogWrite, limited to 0 to 255 by constrain.
void drive(bool forward, int speed) {
digitalWrite(IN1, forward ? HIGH : LOW);
digitalWrite(IN2, forward ? LOW : HIGH);
analogWrite(ENABLE, constrain(speed, 0, 255));
}setup sketch.ino
It sets the three driver pins as outputs and starts the serial port at 9600. It also prints a message asking you to turn the knob away from the middle.
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENABLE, OUTPUT);
Serial.begin(9600);
Serial.println("Mokxi Uno: turn the knob away from the middle");
}loop sketch.ino
It reads the knob on A0. A reading above 512 means forward. The speed is the distance from 512, mapped to 0 to 255. It calls drive with those two values, then waits 50 ms.
void loop() {
int knob = analogRead(A0);
bool forward = knob > 512;
int speed = map(abs(knob - 512), 0, 512, 0, 255);
drive(forward, speed);
delay(50);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The motor never moves. This project
Check pin 11 reaches EN12 and that VS and VSS are on 5V. - The motor only runs one way. This project
Check pin 10 goes to IN1 and pin 9 goes to IN2. Both are needed to reverse. - The motor creeps near the middle of the knob. This project
The stop point is exactly 512. Real knobs wobble, so a tiny speed near the middle is normal. - 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 reading jumps around or only covers part of the range. Potentiometer
Wire the two outer legs to 5 V and ground and the middle leg (the wiper) to an analog pin. Using the wrong two legs gives a dead or partial range.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.