Built-in project · Arduino Uno R3

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.

The circuit runs here once the page has loaded.

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.

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 EN12Arduino Uno R3 pin 11
Motor driver, L293D pin IN1Arduino Uno R3 pin 10
Motor driver, L293D pin IN2Arduino Uno R3 pin 9
Motor driver, L293D pin VSArduino Uno R3 pin 5V
Motor driver, L293D pin VSSArduino Uno R3 pin 5V
Potentiometer pin 1Arduino Uno R3 pin 5V
Motor driver, L293D pin GND1Arduino Uno R3 pin GND
Potentiometer pin 3Arduino Uno R3 pin GND
Potentiometer pin 2Arduino Uno R3 pin A0
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 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.