ESP32 with Stepper Motor (28BYJ-48 and ULN2003 Motor Driver)

In this guide, you’ll learn how to control a stepper motor with the ESP32. We’ll use the 28BYJ-48 unipolar stepper motor with the ULN2003 motor driver. The ESP32 board will be programmed using Arduino IDE.

ESP32 with Stepper Motor 28BYJ-48 and ULN2003 Motor Driver

We have a similar tutorial for the ESP8266 board: ESP8266 NodeMCU with Stepper Motor (28BYJ-48 and ULN2003 Motor Driver)

We have tutorials for other motors with the ESP32:

Parts Required

To follow this tutorial, you need the following parts:

You can use the preceding links or go directly to to find all the parts for your projects at the best price!

Introducing Stepper Motors

A stepper motor is a brushless DC electric motor that divides a full rotation into a number of steps. It moves one step at a time, and each step is the same size. This allows us to rotate the motor by a precise angle to a precise position. The stepper motor can rotate clockwise or counterclockwise.

The following picture shows two 28BYJ-48 stepper motors.

28BYJ-48 Stepper Motors

Stepper motors are made of internal coils that make the motor shaft move in steps in one direction or the other when current is applied to the coils in a specific way.

There are two types of stepper motors: unipolar and bipolar stepper motors.

In this article, we won’t detail how the stepper motors are made and how they work internally. To learn in more detail how they work and the differences between each type of stepper motor, we recommend reading this article by the DroneBotWorkshop blog.

28BYJ-48 Stepper Motor

There are several stepper motors with different specifications. This tutorial will cover the widely used 28BYJ-48 unipolar stepper motor with the ULN2003 motor driver.

28BYJ-48 connected to ULN2003 Motor Driver 01 module

28BYJ-48 Stepper Motor Features

Features of the stepper motor (for more details, consult the datasheet):

  • Rated voltage: 5V DC
  • Number of phases: 4
  • Speed variation ratio: 1/64
  • Stride angle: 5.625º/64
  • Frequency: 100Hz

The 28BYJ-48 stepper motor has a total of four coils. One end of the coils is connected to 5V, which corresponds to the motor’s red wire. The other end of the coils corresponds to the wires with blue, pink, yellow, and orange color. Energizing the coils in a logical sequence makes the motor move one step in one direction or the other.

28BYJ-48 stepper motor coils

The 28BYJ-48 Stepper Motor has a stride angle of 5.625°/64 in half-step mode. This means that the motor has a step angle of 5.625º—so it needs 360º/5.625º = 64 steps in half-step mode. In full-step mode: 64/2 = 32 steps to complete one rotation.

However, the output shaft is driven via a 64:1 gear ratio. This means that the shaft (visible outside the motor) will complete a rotation if the motor inside rotates 64 times. This means that the motor will have to move 32×64 = 2048 steps for the shaft to complete one full rotation. This means that you’ll have a precision of 360º/2048 steps = 0.18º/step.

So, in summary:

  • Total steps per revolution = 2048 steps
  • Step angle = 0.18º/step

If you’re using a different stepper motor, please consult the datasheet.

ULN2003 Motor Driver

To interface the stepper motor with the ESP32, we’ll use the ULN2003 motor driver, as shown in the figure below. The 28BYJ-48 stepper motor is many times sold together with the ULN2003 motor driver.

ULN2003 Motor Driver 01 module board

The module comes with a connector that makes it easy and simple to connect the motor to the module. It has four input pins to control the coils that make the stepper motor move. The four LEDs provide a visual interface of the coils’ state.

ULN2003 IC Motor Driver Labels

There are pins to connect VCC and GND, and a jumper cap that acts as an ON/OFF switch to power the stepper motor—if you remove the jumper, there is no power reaching the motor. You can use those pins to wire a physical switch.

ULN2003 Motor Driver Pinout

The following table shows the module pinout:

IN1Control the motor: connect to a microcontroller digital pin
IN2Control the motor: connect to a microcontroller digital pin
IN3Control the motor: connect to a microcontroller digital pin
IN4Control the motor: connect to a microcontroller digital pin
VCCPowers the motor
Motor connectorConnect the motor connector

Wire Stepper Motor to the ESP32

In this section, we’ll connect the stepper motor to the ESP32 via the ULN2003 motor driver.

We’ll connect IN1, IN2, IN3, and IN4 to GPIOs 19, 18, 5, and 17. You can use any other suitable digital pins (check our ESP32 pinout reference guide).

You can follow the next schematic diagram.

ESP32 with Stepper Motor 28BYJ-48 and ULN2003A Schematic Diagram Wiring

Note: you should power the motor driver using an external 5V power supply.

Motor DriverESP32

Control Stepper Motor with the ESP32 – Code

There are different ways to control stepper motors with a microcontroller. We’ll use the Arduino built-in Stepper.h library. This library provides an easy way to move the motor by a defined number of steps.

Copy the following code to your Arduino IDE.

  Rui Santos
  Complete project details at
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
  Based on Stepper Motor Control - one revolution by Tom Igoe

#include <Stepper.h>

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution

// ULN2003 Motor Driver Pins
#define IN1 19
#define IN2 18
#define IN3 5
#define IN4 17

// initialize the stepper library
Stepper myStepper(stepsPerRevolution, IN1, IN3, IN2, IN4);

void setup() {
  // set the speed at 5 rpm
  // initialize the serial port

void loop() {
  // step one revolution in one direction:

  // step one revolution in the other direction:

View raw code

We adapted this code from the examples provided by the Stepper library (File > Examples > Stepper > stepper_oneRevolution).

How the Code Works

First, include the Stepper.h library.

#include <Stepper.h>

Define the steps per revolution of your stepper motor—in our case, it’s 2048:

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution

Define the motor input pins. In this example, we’re connecting to GPIOs 19, 18, 5, and 17, but you can use any other suitable GPIOs.

#define IN1 19
#define IN2 18
#define IN3 5
#define IN4 17

Initialize an instance of the stepper library called myStepper. Pass as arguments the steps per revolution and the input pins. In the case of the 28BYJ-48 stepper motor, the order of the pins is IN1, IN3, IN2, IN4—it might be different for your motor.

Stepper myStepper(stepsPerRevolution, IN1, IN3, IN2, IN4);

In the setup(), set the stepper speed using the setSpeed method. The stepper speed is in rpm.


Initialize the Serial Monitor at a baud rate of 115200.


In the loop(), we’ll rotate the stepper motor clockwise and counterclockwise. You can use the step() method on the myStepper object. Pass as an argument the number of steps you want to take. For a full rotation (revolution), you need 2048 steps (stepsPerRevolution variable).


To rotate the motor counterclockwise, you need to pass the number of steps with the minus “” sign.



Upload the code to your board. After uploading, the motor will make one clockwise rotation and a counterclockwise rotation over and over again.

You can watch a quick video demonstration:

Other Libraries

Using the Stepper.h library is one of the easiest ways to control a stepper motor. However, if you want more control over your stepper motor, there are libraries with more functions like the AccelStepper library. This library is well documented, with all the methods described in great detail.

It provides several examples that are compatible with the ESP32. Just make sure you initialize a stepper object with the right pins:

AccelStepper stepper (AccelStepper::FULL4WIRE, 19, 5, 18, 17);

This library allows you to control the motors in a non-blocking way and allows you to control more than one motor at a time. But this is a subject for another tutorial.

Wrapping Up

This tutorial was a getting started guide for stepper motors with the ESP32. Stepper motors move one step at a time and allow you to position the motor shaft at a specific angle.

One of the easiest ways to control the stepper motor is to use the built-in Arduino Stepper library. This library provides an easy way to rotate the motor clockwise or counterclockwise a determined number of steps. If you want more control over your stepper motor, we recommend the AccelStepper library.

We hope you find this tutorial useful.

Learn more with the ESP32 with our resources:

Thanks for reading.

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

20 thoughts on “ESP32 with Stepper Motor (28BYJ-48 and ULN2003 Motor Driver)”

  1. While this first program is good enough to test out connections to a motor,
    I think it would be advisable to show beginners how to avoid using the delay() function which blocks. Help beginners become free of delay() as soon as possible.

    For example, refer users to this Adafruit tutorial:

    Or elaborate on the Adafruit example perhaps with end switches to limit travel.

    Hope thie helps.

  2. Hello, yours tutorials are really good. I am a newbie and I would like you to clarify some questions:
    – Do the motors maintain the state even when there is a power cut?
    – How to include limits switches? (It would be good idea a tutorial to open and close (for example a door) adding limits switches).

    Thanks a lot.

    • Hi.

      Yes, they maintain their position.

      You can detect if limit switches are pressed by reading the value on the GPIO it is connected to.
      Depending on your circuit and limit switch it will read a HIGH or LOW signal when it is pressed/not pressed.
      You can add an if statement that does something depending on the limit switch state: stop the stepper motor, or move the stepper motor.

      At the moment, we don’t have any tutorials about limit switches.

      I hope this helps.


  3. Good day,

    Can you please make a tutorial on using a NEMA 17 stepper motor with an ESP32 and DRV8825 stepper driver and controlling it with BLE or a web server?

  4. I try to follow your tutorial and use exact same codes (INT #, etc.), but the motor only runs clockwise, no counterclockwise turns. Any possible reasons or solutions?


  5. So glad you covered stepper motors! I had asked for this a while back. (maybe a year?) I’ve been away for a while so checking out all the latest projects here.

    You guys really explain things very well. I never have a problem understanding your guides.


  6. As always love the tutorials … can I suggest you update the pinout diag to include powering the esp32. I know it’s a small thing but showing how to power the esp32 with shared ground<?> would be helpful.


  7. Hello, it was a useful video for me, thank you. However, I could not understand what advantage using ESP32 in this application gives us compared to using arduino. We could do the same with arduino. Am I thinking wrong?

  8. Thank you for the tutorial. I am using the exact same stepper and controller, but I am trying to add a second. For some reason only the first one, attached to (In1=19, In2=18, In3=5, and In4=17) works. I’ve tried a bunch of different combination of GPIO pins for the second one. I am just declaring a second Stepper myStepperB(…) with In1b, In2b, etc… and connecting those to other GPIO Pins. (Right now 23,22,21 and 16). The second one never works. I’ve switched the motors and boards and the behavior is the same, so I don’t think it is that. My guess is that there is some constant in the library that just happens to work for the first set but doesn’t allow a second. Ideas? Thanks!

    • AHA!!! Found it. Thought I would leave it here for the next person. If you do NOT set the SPEED, it won’t work!


Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.