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.
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:
- ESP32 with DC Motor and L298N Motor Driver – Control Speed and Direction
- ESP32 Servo Motor Web Server with Arduino IDE
Parts Required
To follow this tutorial, you need the following parts:
- 28BYJ-48 Stepper Motor
- ULN2003 Motor Driver
- ESP32 (read Best ESP32 Development Boards)
- Jumper Wires
- 5V Power Supply
You can use the preceding links or go directly to MakerAdvisor.com/tools 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.
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 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.
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.
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.
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:
IN1 | Control the motor: connect to a microcontroller digital pin |
IN2 | Control the motor: connect to a microcontroller digital pin |
IN3 | Control the motor: connect to a microcontroller digital pin |
IN4 | Control the motor: connect to a microcontroller digital pin |
VCC | Powers the motor |
GND | Common GND |
Motor connector | Connect 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.
Note: you should power the motor driver using an external 5V power supply.
Motor Driver | ESP32 |
IN1 | GPIO 19 |
IN2 | GPIO 18 |
IN3 | GPIO 5 |
IN4 | GPIO 17 |
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 & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-stepper-motor-28byj-48-uln2003/
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
myStepper.setSpeed(5);
// initialize the serial port
Serial.begin(115200);
}
void loop() {
// step one revolution in one direction:
Serial.println("clockwise");
myStepper.step(stepsPerRevolution);
delay(1000);
// step one revolution in the other direction:
Serial.println("counterclockwise");
myStepper.step(-stepsPerRevolution);
delay(1000);
}
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.
myStepper.setSpeed(5);
Initialize the Serial Monitor at a baud rate of 115200.
Serial.begin(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).
myStepper.step(stepsPerRevolution);
To rotate the motor counterclockwise, you need to pass the number of steps with the minus “–” sign.
myStepper.step(-stepsPerRevolution);
Demonstration
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.
Controlling a Stepper Motor Remotely
Learn how to control a stepper motor remotely with the ESP32 using a web server. Take a look at the following tutorials:
- ESP32 Web Server: Control Stepper Motor (HTML Form)
- ESP32 Web Server: Control Stepper Motor (WebSocket)
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 about the ESP32 with our resources:
- Learn ESP32 with Arduino IDE (eBook + video course)
- Build Web Servers with ESP32 and ESP8266 eBook (2nd Edition)
- More ESP32 Projects and Tutorials …
Thanks for reading.
Very good project well laid out, but would have liked more help with the software
Hi.
What would you like to see covered here?
Regards,
Sara
Thanks love you’re work regards pete.
Hi making a cnc THANKS AGAIN REGARDS PETE
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:
learn.adafruit.com/multi-tasking-the-arduino-part-1/a-classy-solution
Or elaborate on the Adafruit example perhaps with end switches to limit travel.
Hope thie helps.
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.
Regards,
Sara
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?
Hi.
Thanks for the suggestion.
I’ll add that to my to-do list.
Regards,
Sara
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?
Thanks.
Never mind. I found where the problem is. Thanks.
Great!
Regards,
Sara
Hi.
Check the wiring.
If you’re using a different driver, the order of the pins might be different.
Regards,
Sara
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.
Bob
That’s great!
Thank you.
Regards,
Sara
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.
Thanks!!
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?
Hi.
In this particular case, bo.
But this is just a getting started guide.
The idea is to control the stepper motor remotely via a web server. But, for that, first, you need to be familiar with the basics.
https://randomnerdtutorials.com/stepper-motor-esp32-websocket/
Regards,
Sara
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!
gostaria de ver algo utilizando o MCPWM que vem no hardware no ESP32. é possÃvel explorar muitas desse módulo interno do ESP.
Excellent tutorial! Great job. If you have time please make a tutorial on how to control more than one stepper motor using the AccelStepper library.
Do you have code for HomeAssitant?
Unfortuantely, no.
Regards,
Sar
Unfortunately, no.
Regards,
Sara
Since the library stepper.h block the microcontroller while the stepmotor is moving, I decide to create a nonblocking stepmotor library based on timer/interrupts so that the microcontroller is free even when the stepmotor is moving. It is able to manage both types of stepmotor: Nema17 and 28byj-48, The NewStepper.h is available at https://github.com/AntonioFromBrazil/NewStepper
I used this tutorial and part of the code to write a ESP32 program to control the same stepper and driver used this by webhooks (final project is to control the blades of the “veneziane” blinds at home).
I did the same already using ESPhome and Home Assistant but I need to remove Home Assistant and control the steppers (physically connected to my blinds) using webhooks.
The point is : both solutions works fine but while the ESPhome solution has no issue, this solution (that I need) makes the stepper motor so hot, even if the motor is still long time (without any moves).
In the ESPhome yaml file there a directive that ask the driver/motor to sleep when not in use (sleep_when_done : true). Maybe that’s the magic ? is there any similar method to perform “sleeping” and cold down the stepper temp ?
thanks so much for your tutorial, Grazie ! 🙂
I reply to myself 🙂 because (maybe) I found the way.
To cool down the temp of the stepper is possible to use the AccelStepper library and the method disableOutputs() allows to turn off the motor (by setting all pin to LOW) and there’s no current flowing in the stepper, until next “move” command will be requested.
Thanks for providing that info.
Regards,
Sara
Hi,
I’m not sure if the ULN2003 works well with 3.3V logic – wouldn’t it be better to use the ULN2001?
Hi.
This worked well with the ULN2003, but if you prefer, you can also use a ULN2001 (but I haven’t tried this one).
Regards,
Sara