The ULN2003 stepper motor driver is a Darlington transistor array designed specifically for low-power unipolar stepper motors like the 5V 28BYJ-48. It handles up to 500mA per channel at a maximum of 50V, making it the default choice for light-duty prototyping, pan-tilt camera mounts, and simple automation. However, it is entirely unsuited for high-torque bipolar NEMA 17 or NEMA 23 applications found in CNC routers and 3D printers. If you are moving a load that requires precise high-speed positioning or more than a few ounce-inches of torque, you need to look past the ULN2003.
The ULN2003 Stepper Motor Driver: Capabilities and Limits
At its core, the ULN2003A IC contains seven NPN Darlington transistor pairs. Each pair features a high current gain and integrates a flyback diode across the collector-emitter path to safely dissipate inductive kickback when the motor coils are de-energized. On the standard red breakout board you find in most hobby kits, four of these channels are routed to a 5-pin JST connector, alongside status LEDs and a power jumper.
Priced between $1.50 and $3.00 for a fully populated breakout board, the ULN2003 is incredibly cheap. It accepts 5V logic directly from an Arduino Uno, ESP32, or Raspberry Pi without needing level shifters. But its limitations are hard physical boundaries: it can only sink current (it cannot push it), it only supports unipolar winding topologies, and it lacks the microstepping and active current decay features required for smooth, high-speed bipolar stepper control.
Motor Type Comparison: Where the ULN2003 Fits
Selecting the right driver requires matching the motor's winding topology and torque profile to the driver's switching capability. Steppers and servos are fundamentally different architectures and are not interchangeable in control logic or driver hardware. Below is a breakdown of common hobbyist motors and the drivers they actually demand.
| Motor Type | Torque Curve Profile | Control Needs | Typical Cost | Compatible Driver |
|---|---|---|---|---|
| Unipolar Stepper (e.g., 28BYJ-48) | Low holding torque, drops off sharply at speed. Best for slow, high-reduction gear loads. | Simple sequential DC sinking. No current chopping required. | $2 - $5 | ULN2003, ULN2803, discrete TIP120s |
| Bipolar Stepper (e.g., NEMA 17) | High holding torque, maintains torque at higher speeds when driven with chopper microstepping. | H-bridge switching, active current limiting, PWM decay modes. | $10 - $25 | A4988, DRV8825, TMC2209 |
| RC Servo (e.g., SG90, MG996R) | High stall torque at zero speed, drops to zero when moving. Position feedback via internal pot. | 50Hz PWM pulse width (1ms-2ms). No coil sequencing. | $3 - $15 | Direct MCU GPIO (for micro), PCA9685 (for many) |
| Brushless DC (BLDC Outrunner) | High continuous torque at high RPM. Zero holding torque without active commutation. | 3-phase AC commutation, back-EMF sensing or Hall sensors. | $20 - $60 | ESC (Electronic Speed Controller) |
The ULN2003 strictly belongs in the first row. If your load profile requires high-speed traversal or precise CNC positioning, a unipolar stepper driven by a ULN2003 will fail you; you must upgrade to a bipolar stepper and a chopper driver like the TMC2209.
Wiring, Terminal Identification, and Sizing Rules
The most common pairing for the ULN2003 is the 5V 28BYJ-48 unipolar stepper. This motor has five wires: Red (Center Tap / VCC), Pink (Coil 1), Yellow (Coil 2), Orange (Coil 3), and Blue (Coil 4). Note that the standard color sequence on the 5-pin JST connector is often Red-Blue-Pink-Yellow-Orange, which does not match the physical coil order. Always trust the pinout printed on the motor casing or measure continuity with a multimeter.
Terminal Identification and Pin Mapping
- IN1 to IN4: Connect to four digital output pins on your microcontroller (e.g., Arduino D8, D9, D10, D11).
- VCC (Board): Connect to the positive terminal of your power supply. For a 5V 28BYJ-48, use a 5V supply. Do not power the motor directly from the Arduino's 5V regulator; it will brownout the MCU.
- GND: Connect to the power supply ground AND the microcontroller ground. A common ground is mandatory for the logic signals to register.
- Motor Connector: Plug the 28BYJ-48 JST connector directly into the board. The red wire aligns with the 'VCC' or '+' marking on the board silk screen.
Sizing Rule of Thumb and Worked Load Example
When sizing a Darlington driver for a unipolar motor, use this rule of thumb: The driver's continuous current rating per channel must be at least 1.5 times the motor's rated phase current. This accounts for the thermal derating of the IC package when multiple channels are energized simultaneously (as in full-step or half-step waveforms).
Worked Example 1 (Passes): The standard 5V 28BYJ-48 draws approximately 160mA per phase.
160mA × 1.5 = 240mA required driver capacity.
The ULN2003 is rated for 500mA per channel. 500mA > 240mA. The driver is correctly sized and will run cool.
Worked Example 2 (Fails): You decide to use a larger 12V unipolar stepper motor rated at 400mA per phase for a heavier conveyor belt load.
400mA × 1.5 = 600mA required driver capacity.
The ULN2003 maxes out at 500mA. If you use it, the silicon junction will overheat, the Darlington pairs will enter thermal runaway, and the IC will eventually short out. For this 12V load, you must step up to a driver like the TI DRV8805 or build a discrete logic-level MOSFET array.
Failure Signatures: Hum, Overheat, and Stall
When a stepper system fails, it rarely does so silently. Recognizing the acoustic and thermal signatures will save you from chasing software bugs when the problem is purely electromechanical.
The Hum: If the motor emits a loud, continuous buzzing or humming sound without rotating, the step pulse frequency is too high for the rotor's inertia to catch (you are commanding a speed beyond the motor's pull-in torque curve), or the coil energization sequence is scrambled. Verify your code is using the correct half-step or full-step sequence (e.g., A-AB-B-BC-C-CD-D-DA) and lower the RPM in your Arduino Stepper library initialization.
Overheat: The ULN2003 IC should be warm, but if it is too hot to touch (exceeding 60°C), you are exceeding its thermal dissipation limits. As noted in the Texas Instruments ULN2003A datasheet, the high $V_{CE(sat)}$ means a 500mA load generates roughly 0.6W of heat per channel. With two channels active, that is 1.2W dissipated in a plastic DIP-16 package with no heatsink. If you are leaving the motor energized at a standstill for long periods, implement a software idle state to cut the coil power.
Stall: A stall occurs when the load inertia or friction exceeds the motor's pull-out torque. The 28BYJ-48 has an internal gear reduction (nominally 1:64) which multiplies its bare torque to roughly 34.3 mN·m. If your mechanical linkage binds, or if you try to accelerate the load too quickly, the rotor will slip magnetic poles. The motor will stop moving, but the driver will continue to sequence the coils, resulting in a stall and a subsequent hum.
Frequently Asked Questions
Can I use the ULN2003 stepper motor driver for a NEMA 17 bipolar motor?
No. NEMA 17 motors are almost exclusively bipolar, meaning they have four wires and no center taps. The current must be reversed through the coils to achieve rotation, which requires an H-bridge topology. The ULN2003 can only sink current to ground; it cannot reverse polarity. Attempting to wire a bipolar motor to a ULN2003 will result in a motor that twitches but never completes a full rotation. For NEMA 17 motors, use a chopper driver like the A4988, DRV8825, or the ultra-quiet TMC2209.
Why is my ULN2003 driver board getting extremely hot to the touch?
This is inherent to the Darlington transistor design. Unlike modern MOSFETs which have near-zero on-resistance, Darlingtons have a fixed voltage drop of about 1.0V to 1.5V when fully saturated. At the 500mA absolute maximum rating, each channel dissipates up to 0.75 watts of heat. The plastic IC package cannot shed this heat efficiently. To keep temperatures manageable, limit continuous duty currents to 300mA per channel, or add a small stick-on heatsink to the IC.
How do I stop the 28BYJ-48 motor from vibrating and drawing current when stopped?
By default, the Arduino Stepper library keeps the final coil state energized after a move is complete to maintain holding torque. This causes the motor to hum slightly and draws continuous current, draining batteries and heating the driver. To fix this, you must manually de-energize the coils in your code immediately after the movement finishes. If your motor is connected to pins 8, 9, 10, and 11, add the following lines after your stepper.step() command:
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
This turns off all transistors in the ULN2003, stopping the vibration and dropping the current draw to zero. Note that the motor will now have zero holding torque and can be turned by hand.
What is the maximum RPM speed for a 28BYJ-48 with the ULN2003 driver?
In practical applications using half-step sequencing, the reliable maximum speed for a 5V 28BYJ-48 is between 15 and 20 RPM (roughly 500 to 650 steps per second). If you push the step rate beyond this threshold, the rotor's physical inertia prevents it from catching the rotating magnetic field, and the motor will stall and hum. If your application requires higher speeds, you must either increase the supply voltage to a 12V variant of the motor (which requires a 12V power supply and careful thermal monitoring of the ULN2003) or switch to a bipolar NEMA 17 driven by a microstepping chopper driver, as detailed in resources like All About Circuits.






