Documentation

ShillehTek ULN2003 Stepper Motor for Arduino Raspberry Pi 5V | ShillehTek Product Manual
Documentation / ShillehTek ULN2003 Stepper Motor for Arduino Raspberry Pi 5V | ShillehTek Product Manual

ShillehTek ULN2003 Stepper Motor for Arduino Raspberry Pi 5V | ShillehTek Product Manual

Overview

The ULN2003 5V Stepper Motor Driver is a compact controller board paired with the popular 28BYJ-48 4-phase stepper motor. The board uses the ULN2003AN Darlington array to switch the motor's coils based on signals from a microcontroller, while four onboard LEDs (A, B, C, D) light up in sequence so you can visually confirm the motor is stepping.

This kit is the most affordable way to learn stepper motor control. It's perfect for slow, precise movement projects: clocks, smart curtains, robotic arms, model trains, automated dispensers, and CNC plotters. The 28BYJ-48 motor's 64:1 internal gearbox produces 4096 steps per full revolution in half-step mode, giving you very fine angular control without complex code.

The driver works with Arduino, ESP32, Raspberry Pi, and Pico — anything with four GPIO pins to spare. Inputs are 3.3V/5V tolerant and the included Stepper.h Arduino library makes basic motion a few lines of code. A jumper near the screw terminals enables or disables motor power without unplugging the board.

At a Glance

Driver IC
ULN2003AN
Motor Voltage
5V (DC 5-12V input)
Motor Type
28BYJ-48 4-phase
Steps / Revolution
4096 (half-step)
Logic Inputs
IN1-IN4 (3.3V/5V)
Indicators
4 LEDs (A, B, C, D)

Specifications

Parameter Value
Driver IC ULN2003AN (7-channel Darlington array)
Motor Power Input 5V DC (typical), 5-12V supported
Logic Input Voltage 3.3V / 5V compatible
Input Pins IN1, IN2, IN3, IN4
Motor Connector 5-pin JST (matches 28BYJ-48 cable)
Indicator LEDs 4 (one per coil channel)
Power Jumper On/Off, removes motor power
28BYJ-48 Step Angle 5.625° / 64 (geared output)
Steps per Revolution (full step) 2048 (with 64:1 gearbox)
Steps per Revolution (half step) 4096 (with 64:1 gearbox)
28BYJ-48 Coil Resistance ~50 ohms per phase
28BYJ-48 Pull-in Torque ~300 g·cm typical
Motor Cable 5-wire unipolar (red common, +4 phases)

Pinout Diagram

ULN2003 stepper motor driver board pinout diagram showing IN1, IN2, IN3, IN4 microcontroller signal inputs, four step indicator LEDs A, B, C, D, white 5-pin stepper motor connector, ULN2003AN Darlington array IC, on/off jumper, and DC power input terminals for 5-12 volts

Connect IN1 through IN4 to four GPIO pins on your microcontroller — these are the coil control signals. The white 5-pin connector at the top accepts the 28BYJ-48 motor's keyed cable in only one orientation. Power the motor through the screw terminals labeled + and - (5-12V DC), and use the on/off jumper to cut motor power without disconnecting wires. The four LEDs labeled A, B, C, D light up in sequence as IN1-IN4 are driven, giving you instant visual feedback that your stepping pattern is working.

Wiring Guide

Arduino Wiring

The Arduino's 5V output can power the ULN2003 driver and 28BYJ-48 motor for light-duty projects, but for reliable performance use a separate 5V supply on the board's screw terminals and share grounds.

Driver Pin Arduino Pin
IN1 Digital Pin 8
IN2 Digital Pin 9
IN3 Digital Pin 10
IN4 Digital Pin 11
+ (motor power) 5V (or external 5V supply)
- (motor ground) GND
Tip: The 28BYJ-48 plug is keyed and only fits one way into the board's 5-pin connector. If the motor vibrates but doesn't rotate, your IN1-IN4 sequence is probably wrong — try the half-step pattern (Arduino's Stepper.h library uses a different pin order, often IN1, IN3, IN2, IN4).
Info: Drawing motor current through the Arduino's 5V regulator can reset the board on long runs. For anything beyond a quick demo, power the driver from an external 5V wall adapter and connect only IN1-IN4 plus a common ground.

ESP32 Wiring

The ULN2003 inputs are 3.3V tolerant, so the ESP32 drives them directly. Power the motor side from a separate 5V source — the ESP32's onboard regulator can't supply enough current for the stepper coils.

Driver Pin ESP32 Pin Details
IN1 GPIO 14
IN2 GPIO 27
IN3 GPIO 26
IN4 GPIO 25
+ (motor power) External 5V Wall adapter or USB power bank
- (motor ground) GND Tie ESP32 GND and supply GND together
Warning: Always share grounds between the ESP32 and the motor power supply. Floating grounds cause unreliable stepping and can damage the GPIO pins.
Tip: Avoid using strapping pins (GPIO 0, 2, 5, 12, 15) for IN1-IN4 — high or low states on those pins at boot can prevent the ESP32 from starting. Pins 14, 25, 26, 27 are safe choices.

Raspberry Pi Wiring

The Pi's 3.3V GPIO drives the ULN2003 inputs without level shifting. Don't try to power the motor from the Pi's 5V rail; use an external supply on the driver's screw terminals and share grounds.

Driver Pin Raspberry Pi Pin Details
IN1 Pin 11 (GPIO 17)
IN2 Pin 13 (GPIO 27)
IN3 Pin 15 (GPIO 22)
IN4 Pin 16 (GPIO 23)
+ (motor power) External 5V supply Do NOT use Pi 5V
- (motor ground) Pin 6 (GND) Common ground with supply GND
Warning: The Pi's 5V rail is meant for the Pi itself. Connecting a stepper motor to it can crash the Pi or damage the SD card during high-current pulses. Always use a separate 5V supply for the motor.
Tip: Use BCM pin numbering (the GPIO numbers, not physical pin positions) when writing your Python code with RPi.GPIO. The numbering is more portable across Pi models.

Raspberry Pi Pico Wiring

The Pico's 3.3V GPIO is fully compatible with the ULN2003 inputs. The Pico's VBUS (USB 5V) can power small steppers in short bursts, but a separate 5V supply is more reliable for continuous motion.

Driver Pin Pico Pin Details
IN1 GP2
IN2 GP3
IN3 GP4
IN4 GP5
+ (motor power) VBUS or external 5V VBUS = 5V from USB cable
- (motor ground) GND Common ground required
Info: If your Pico is connected to a computer via USB, VBUS provides 5V at up to ~500 mA. The 28BYJ-48 typically draws under 240 mA per phase, so a single motor works fine on VBUS for casual use. Add an external supply if you're driving multiple motors or running for long periods.

Code Examples

Arduino (Stepper.h library)

uln2003_arduino.ino
// 28BYJ-48 + ULN2003 - Arduino full revolution example
// IN1->D8, IN2->D9, IN3->D10, IN4->D11
// NOTE: Stepper.h pin order is (IN1, IN3, IN2, IN4) — not 1,2,3,4!

#include 

// Steps per revolution for the 28BYJ-48 (full step with 64:1 gearbox)
const int STEPS_PER_REV = 2048;

// Stepper(steps, pin1, pin3, pin2, pin4) — note the swapped order
Stepper motor(STEPS_PER_REV, 8, 10, 9, 11);

void setup() {
  Serial.begin(9600);
  motor.setSpeed(10);  // RPM (max ~15 RPM for 28BYJ-48)
}

void loop() {
  Serial.println("One revolution clockwise");
  motor.step(STEPS_PER_REV);
  delay(1000);

  Serial.println("One revolution counter-clockwise");
  motor.step(-STEPS_PER_REV);
  delay(1000);
}

Raspberry Pi (Python)

uln2003_rpi.py
#!/usr/bin/env python3
# 28BYJ-48 + ULN2003 - Raspberry Pi half-step example
# IN1->GPIO 17, IN2->GPIO 27, IN3->GPIO 22, IN4->GPIO 23

import RPi.GPIO as GPIO
import time

PINS = [17, 27, 22, 23]  # IN1, IN2, IN3, IN4

# 8-step half-stepping sequence for smoother motion
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],
]

GPIO.setmode(GPIO.BCM)
for pin in PINS:
    GPIO.setup(pin, GPIO.OUT)
    GPIO.output(pin, 0)

def step(direction=1, steps=4096, delay_s=0.001):
    seq = HALF_STEP if direction > 0 else list(reversed(HALF_STEP))
    for i in range(steps):
        for pin, val in zip(PINS, seq[i % 8]):
            GPIO.output(pin, val)
        time.sleep(delay_s)

try:
    print("Rotating one full revolution clockwise...")
    step(direction=1, steps=4096)  # 4096 = one revolution in half-step mode
    time.sleep(1)
    print("Rotating one full revolution counter-clockwise...")
    step(direction=-1, steps=4096)
finally:
    for pin in PINS:
        GPIO.output(pin, 0)
    GPIO.cleanup()

Raspberry Pi Pico (MicroPython)

uln2003_pico.py
# 28BYJ-48 + ULN2003 - Pico MicroPython half-step example
# IN1->GP2, IN2->GP3, IN3->GP4, IN4->GP5

from machine import Pin
import time

pins = [Pin(2, Pin.OUT), Pin(3, Pin.OUT), Pin(4, Pin.OUT), Pin(5, Pin.OUT)]

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),
]

def step(direction=1, steps=4096, delay_ms=2):
    seq = HALF_STEP if direction > 0 else tuple(reversed(HALF_STEP))
    for i in range(steps):
        pattern = seq[i % 8]
        for pin, val in zip(pins, pattern):
            pin.value(val)
        time.sleep_ms(delay_ms)

try:
    print("One full revolution clockwise")
    step(direction=1, steps=4096)
    time.sleep(1)
    print("One full revolution counter-clockwise")
    step(direction=-1, steps=4096)
finally:
    for p in pins:
        p.value(0)

ESP32 (MicroPython)

uln2003_esp32.py
# 28BYJ-48 + ULN2003 - ESP32 MicroPython example
# IN1->GPIO 14, IN2->GPIO 27, IN3->GPIO 26, IN4->GPIO 25

from machine import Pin
import time

pins = [Pin(14, Pin.OUT), Pin(27, Pin.OUT), Pin(26, Pin.OUT), Pin(25, Pin.OUT)]

# Full-step sequence (faster, slightly less smooth than half-step)
FULL_STEP = [
    (1, 1, 0, 0),
    (0, 1, 1, 0),
    (0, 0, 1, 1),
    (1, 0, 0, 1),
]

def step(direction=1, steps=2048, delay_ms=3):
    seq = FULL_STEP if direction > 0 else tuple(reversed(FULL_STEP))
    for i in range(steps):
        pattern = seq[i % 4]
        for pin, val in zip(pins, pattern):
            pin.value(val)
        time.sleep_ms(delay_ms)

try:
    while True:
        print("CW one revolution")
        step(direction=1, steps=2048)  # 2048 = one revolution in full-step mode
        time.sleep(1)
        print("CCW one revolution")
        step(direction=-1, steps=2048)
        time.sleep(1)
except KeyboardInterrupt:
    for p in pins:
        p.value(0)

Frequently Asked Questions

How do I wire the ULN2003 driver to an Arduino?
Connect IN1, IN2, IN3, and IN4 to any four Arduino digital pins (commonly D8-D11). Plug the 28BYJ-48 motor's 5-pin cable into the white connector — it's keyed and only fits one way. Power the board's + and - terminals from the Arduino 5V/GND for testing, or from an external 5V supply for reliability.
How many steps does it take to make one full revolution?
The 28BYJ-48 motor has a 64:1 internal gearbox. In full-step mode you need 2048 steps per output revolution; in half-step mode it's 4096 steps. Half-stepping gives smoother motion and finer angular resolution at the cost of half the speed.
Why does my motor vibrate but not rotate?
The pin order in your code doesn't match the wiring. The Arduino Stepper.h library expects the order (IN1, IN3, IN2, IN4) when constructing the Stepper object — not (IN1, IN2, IN3, IN4). Try swapping IN2 and IN3 in your code, or swap the wires between the second and third LED-side pins. The four LEDs should light up in a clean A→B→C→D sweep when stepping correctly.
Can I run this from my Arduino's 5V pin?
For short tests, yes — a single 28BYJ-48 draws under 240 mA per phase. For continuous operation, dedicate an external 5V supply (USB wall adapter, 4xAA battery pack, or 5V regulated source) on the driver's screw terminals. Tie that supply's ground to the Arduino ground so the IN1-IN4 signals share a common reference.
What's the maximum speed of the 28BYJ-48?
Practical maximum is around 15 RPM. Pushing higher causes missed steps or stalling because the motor's gearbox limits responsiveness. If you set Stepper.setSpeed(20) or faster and the motor judders or stops, drop the speed back to 10-15 RPM. For high-speed applications, choose a NEMA 17 stepper with an A4988 or DRV8825 driver instead.
What does the on/off jumper do?
The jumper between the screw terminals and the chip cuts motor power without unplugging anything. With the jumper removed, the IN1-IN4 inputs are still connected, but the motor can't move. This is a handy "safety lock" while you upload code or rewire — the LEDs and logic still work, but the motor stays still.
Can I drive a NEMA 17 or other bipolar stepper with this board?
No. The ULN2003 board is designed for unipolar 4-phase steppers like the 28BYJ-48 (5-wire). NEMA 17 and most CNC steppers are bipolar 4-wire and need an H-bridge driver such as the A4988, DRV8825, or TMC2209. Trying to drive a bipolar stepper from this board won't work.