Built-in project · Raspberry Pi Pico

MicroPython stepper motor on a Pico, GP21 to GP18

MicroPython on a Raspberry Pi Pico: a 28BYJ-48 stepper on a ULN2003 board, driven from GP21 to GP18, turns once one way and once back. 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 30 minutes to build and run. Runs in your browser. Free, and no account needed.

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

The circuit runs here once the page has loaded.

What you'll learn

  • How a stepper motor moves by energizing coils in order
  • Driving a stepper through a ULN2003 board
  • Step count and gearing
  • A separate motor supply with a common ground
  • Negative steps to reverse direction
  • Difficulty: Intermediate
  • Time: About 30 minutes
  • Board: Raspberry Pi Pico
  • Parts: 4

How it works

A 28BYJ-48 stepper motor has four coils. A ULN2003 board switches them for you, so the Pico only sends four low power signals on GP21, GP20, GP19 and GP18. The motor runs from its own 5 V supply built from a battery and a breadboard power module.

To move one step, the program turns on one coil at a time in order. 2048 steps make one full turn of the geared shaft.

The main loop turns one full turn forward, waits a second, then one full turn back, then waits another second. Each step waits 2000 microseconds.

Parts list

4 parts, plus the jumper wires. They retail for about $11; 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
Stepper motor, 28BYJ-48 with ULN2003 pin IN1Raspberry Pi Pico pin GP21
Stepper motor, 28BYJ-48 with ULN2003 pin IN2Raspberry Pi Pico pin GP20
Stepper motor, 28BYJ-48 with ULN2003 pin IN3Raspberry Pi Pico pin GP19
Stepper motor, 28BYJ-48 with ULN2003 pin IN4Raspberry Pi Pico pin GP18
Breadboard power supply, MB102 pin VINBattery: AA, coin cell, LiPo pin V+
Battery: AA, coin cell, LiPo pin V-Ground
Breadboard power supply, MB102 pin GNDGround
Stepper motor, 28BYJ-48 with ULN2003 pin GNDGround
Stepper motor, 28BYJ-48 with ULN2003 pin VCCBreadboard power supply, MB102 pin 5V
Breadboard power supply, MB102 pin BOT+Breadboard power supply, MB102 pin TOP+
Breadboard power supply, MB102 pin BOT-Breadboard power supply, MB102 pin TOP-

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 stepper motor on its ULN2003 driver: IN1 to IN4 on GP21, GP20, GP19
# and GP18. Energizing the four coils in turn moves the shaft a step; 2048
# steps are a whole turn of the 28BYJ-48's geared shaft.
from machine import Pin
import time

coils = [Pin(n, Pin.OUT, value=0) for n in (21, 20, 19, 18)]

def step(n, delay_us=2000):
    """n steps, forward when n > 0."""
    for i in range(abs(n)):
        k = i % 4 if n > 0 else 3 - i % 4
        for c, coil in enumerate(coils):
            coil.value(c == k)
        time.sleep_us(delay_us)

while True:
    print("one turn forward")
    step(2048)
    time.sleep(1)
    print("one turn back")
    step(-2048)
    time.sleep(1)

Code walkthrough

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

step main.py

Moves the motor n steps. For each step it picks which of the four coils to turn on, counting forward from 0 to 3 for positive n and backward for negative. It sets that pin high and the others low, then waits delay_us microseconds.

def step(n, delay_us=2000):
    """n steps, forward when n > 0."""
    for i in range(abs(n)):
        k = i % 4 if n > 0 else 3 - i % 4
        for c, coil in enumerate(coils):
            coil.value(c == k)
        time.sleep_us(delay_us)

Troubleshooting

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

  • The motor hums but does not turn This project
    Try a longer delay_us. Steps that come too fast are missed.
  • It jerks or turns the wrong way This project
    Check the order GP21, GP20, GP19, GP18 goes to IN1 to IN4.
  • The battery is wired backwards, or the voltage is too low or too high for the circuit. A fresh AA is about 1.5 V, a LiPo is 3.7 V nominal and 4.2 V full. Battery: AA
    Match the plus and minus marks. Check the voltage your parts need. Two AAs make 3 V, four make 6 V. Never feed a LiPo to a 3.3 V chip directly at 4.2 V.
  • The circuit resets or browns out when a motor or servo starts. A battery has internal resistance, so the voltage sags under load. Battery: AA
    Use a fresh pack with enough current rating. Add a 100 uF or larger capacitor near the load. Power motors from their own pack and join the grounds.
  • The rails give the wrong voltage and the circuit misbehaves. Breadboard power supply
    Set the jumper on each rail pair to 5 V or 3.3 V before powering up. Check the 3.3 V parts do not sit on a 5 V rail. Measure the rail with a multimeter.
  • The board gets hot or shuts down. Breadboard power supply
    The regulators are small and power in from the 9 V jack. A 9 V battery cannot supply much current. Use a proper 7 V to 12 V adapter and keep the total load well under about 700 mA.
  • The motor buzzes or shakes and does not turn. The coil pins IN1 to IN4 are in the wrong order for the library. Stepper motor
    For Arduino's Stepper library on a 28BYJ-48, create it with pins 8, 10, 9, 11 (IN1, IN3, IN2, IN4). Or use AccelStepper with HALF4WIRE and the same pin order.
  • It stalls or skips when spun fast or powered from the Arduino 5 V pin. It also draws more than a USB port may give. Stepper motor
    Power the ULN2003 board from a separate 5 V supply and join the grounds. Run it slowly, about 10 to 15 RPM, and ramp up speed gradually.

Change it and keep it

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