Built-in project · Raspberry Pi Pico

MicroPython L293D motor on a Pico: a knob sets speed

MicroPython on a Raspberry Pi Pico: a knob on GP26 drives a DC motor both ways on an L293D, IN1 and IN2 on GP15 and GP16 and PWM enable on GP17. The whole build, a Raspberry Pi Pico 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 25 minutes to build and run. Runs in your browser. Free, and no account needed.

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

The circuit runs here once the page has loaded.

What you'll learn

  • Reversing a DC motor with an H-bridge driver
  • Direction from two pins, speed from PWM on enable
  • Reading a knob with an ADC in MicroPython
  • Printing only when something changes
  • Difficulty: Intermediate
  • Time: About 25 minutes
  • Board: Raspberry Pi Pico
  • Parts: 7

How it works

A knob on GP26 is read as a number, and the program subtracts 32768 so the middle of the knob is 0. In the middle the motor stops. Turn either way and it runs that way.

The sign sets the direction. GP15 goes high for forward and GP16 goes high for back, and they feed the L293D inputs. The distance from the middle is doubled and sent as PWM on GP17, the enable pin, at 1000 Hz. Farther means faster.

The program prints "forward", "back" or "stop" only when the state changes. A speed of 2 percent or less counts as stop.

Parts list

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

Kits that can build it

This starter kit has 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 pinConnects to
Motor driver, L293D pin IN1Raspberry Pi Pico pin GP15
Potentiometer pin 2Raspberry Pi Pico pin GP26
Motor driver, L293D pin EN12Raspberry Pi Pico pin GP17
Motor driver, L293D pin IN2Raspberry Pi Pico pin GP16
Potentiometer pin 1Ground
Potentiometer pin 33.3 V
DC motor pin 1Motor driver, L293D pin OUT1
Motor driver, L293D pin GND1Ground
Motor driver, L293D pin GND2Ground
DC motor pin 2Motor driver, L293D pin OUT2
Motor driver, L293D pin VS5 V
Motor driver, L293D pin EN34Ground
Motor driver, L293D pin IN4Motor driver, L293D pin IN3
Motor driver, L293D pin OUT4Motor driver, L293D pin OUT3
Motor driver, L293D pin GND3Ground
Motor driver, L293D pin GND4Ground
Motor driver, L293D pin VSS5 V

The code

The MicroPython code exactly as the editor opens it. Change a line there and press Run: the board runs it on the official MicroPython firmware, with nothing to compile.

main.py · Raspberry Pi Pico
# A motor both ways on an L293D, from the knob on GP26. The middle of the
# knob is stop; turned either way, GP15 and GP16 set the direction and the
# PWM on GP17 (the chip's enable) sets how fast.
from machine import ADC, Pin, PWM
import time

knob = ADC(26)
in1 = Pin(15, Pin.OUT)
in2 = Pin(16, Pin.OUT)
enable = PWM(Pin(17))
enable.freq(1000)
last = None

while True:
    offset = knob.read_u16() - 32768             # -32768 to 32767
    in1.value(offset > 0)
    in2.value(offset < 0)
    enable.duty_u16(min(65535, abs(offset) * 2))
    speed = abs(offset) * 100 // 32768
    state = ("forward" if offset > 0 else "back") if speed > 2 else "stop"
    if state != last:
        print(state)
        last = state
    time.sleep_ms(50)

Troubleshooting

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

  • The motor does not run. This project
    Check GP17 goes to EN12 and that the L293D has 5 V on both VS and VSS.
  • The motor only turns one way. This project
    Check GP15 goes to IN1 and GP16 goes to IN2. Both are needed to reverse.
  • 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.
  • Turning the knob does nothing, or the value is stuck at 0 or 1023. Potentiometer
    Check that the wiper goes to an analog input (A0 to A5 on an Uno), not a digital pin. Make sure both ends are connected, since a floating end gives noise.
  • 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.

Change it and keep it

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