Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

28BYJ-48 stepper and ULN2003 with Raspberry Pi Pico W — MicroPython

Turn a 28BYJ-48 stepper through a ULN2003 board from a Pico W on GP10–GP13 in MicroPython: half-step sequence, angles, and coils off when idle.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The 28BYJ-48 is the ₹150 geared stepper in most starter kits, sold with a ULN2003 driver board. The Pico W drives the board’s four inputs from GP10–GP13 and the motor runs from VBUS (5 V).

No library is needed: the script steps through the eight-entry half-step table, turns a full revolution, then a quarter-turn back, and switches the coils off between moves.

Wiring

Raspberry Pi Pico WOnly the pins used are shown · 3.3 V logic28BYJ-48 stepper motor + ULN2003 driverGNDGP10GP11GP12GP13VBUSIN1IN2IN3IN4+-
Every connection
Raspberry Pi Pico W28BYJ-48 stepper motor + ULN2003 driverWireNotes
GP10IN1blueGP10 is physical pin 14.
GP11IN2purpleGP11 is physical pin 15.
GP12IN3yellowGP12 is physical pin 16.
GP13IN4orangeGP13 is physical pin 17.
VBUS+redVBUS (pin 40) is USB 5 V for the 5 V motor (about 200–250 mA while stepping). Never 3V3.
GND-black

5 V for the 5 V version of the motor (about 200–250 mA while stepping) part, 3.3 V board. The ULN2003 inputs accept 3.3 V or 5 V logic, so ESP32 and Pico drive IN1–IN4 directly. Power the motor from 5 V — not from a 3.3 V pin — and share GND with the board.

Board quirks

  • The ULN2003 accepts 3.3 V inputs, so GP10–GP13 drive it directly — four neighbouring pins on the left header.
  • 4096 half-steps is one turn of the output shaft (the real gear ratio makes it about 4076, so expect a small drift over many turns).
  • Below about 1 ms per half-step the motor stalls and just buzzes. It is a slow motor: roughly 15 s per turn here.
  • release() switches all coils off after each move so the motor and the driver don’t heat up. Leave them on only if something must be held in place.

Code

main.pyMicroPython
# 28BYJ-48 stepper + ULN2003 driver board on a Raspberry Pi Pico W (MicroPython, no library).
# Wiring: IN1 -> GP10 (pin 14), IN2 -> GP11 (pin 15), IN3 -> GP12 (pin 16), IN4 -> GP13 (pin 17),
# + -> VBUS (pin 40, USB 5 V), - -> GND. The motor plugs into the white 5-pin socket.
from machine import Pin
import time

STEPS_PER_REV = 4096  # half-steps per output-shaft turn (64 x 64:1 gearbox, about 4076 really)
STEP_MS = 1           # 1 ms per half-step = about 15 s per turn; go lower and it stalls

coils = [Pin(n, Pin.OUT, value=0) for n in (10, 11, 12, 13)]
HALF_STEP = (
    (1, 0, 0, 0), (1, 1, 0, 0), (0, 1, 0, 0), (0, 1, 1, 0),
    (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 0, 1), (1, 0, 0, 1),
)
pos = 0


def step(n):
    """Move n half-steps; negative = the other way."""
    global pos
    d = 1 if n > 0 else -1
    for _ in range(abs(n)):
        pos += d
        for pin, v in zip(coils, HALF_STEP[pos % 8]):
            pin.value(v)
        time.sleep_ms(STEP_MS)


def release():
    for pin in coils:
        pin.value(0)  # coils off: no holding torque, but no heat or wasted current either


def turn_degrees(deg):
    step(int(deg * STEPS_PER_REV / 360))


print("28BYJ-48 on GP10-GP13")
while True:
    print("One turn clockwise")
    turn_degrees(360)
    release()
    time.sleep(1)
    print("Quarter turn back")
    turn_degrees(-90)
    release()
    time.sleep(1)

Expected serial output

REPL / Thonny shellOutput
28BYJ-48 on GP10-GP13
One turn clockwise
Quarter turn back

Common errors

Motor vibrates but doesn’t turn

IN wires out of order or the step delay is too short. Check IN1–IN4 go to GP10–GP13 in order, and keep STEP_MS at 1 or more.

Pico resets when the motor starts

The motor is pulling too much from USB. Power the ULN2003 + pin from a separate 5 V supply and join the grounds.

↑↓ to move · Enter to open