Control a stepper motor with a DRV8825 and an ESP32

Many guides focus on connecting a Pololu DRV8825 to an Arduino, however, I wanted to use an ESP32 Dev Kit because it is cheaper and has WiFi connectivity. This guide will break down how to code stepper motor control on an ESP32 Dev Kit via a DRV8825 Stepper Motor Controller.

We start off by mapping the General Purpose Input Ouput (GPIO) pins on the ESP32 to inputs on the DRV87825:

#define dirPin 13
#define stepPin 14
#define stepsPerRevolution 6400
#define M0 27
#define M1 26
#define M2 25
#define ENABLE 33

Most standard ESP32 Dev Kits will have enough GPIO pins for this project. To find out the function of each pin, search for the specification of your ESP32 Dev Kit model. For example, if a pin is labelled GPIO13 on the diagram, enter this as 13 on the C++ file. In code this will be #define dirPin 13. Please note that on some boards, the GPIO pins may be locked to input only.

Here is a pinout diagram of a DRV8825 for reference in this guide:

DRV8825-pinout diagram


Next we set each of these GPIO pins to be outputs:

void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(M0, OUTPUT);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(ENABLE, OUTPUT);
}

Before we start writing code to trigger steps, we need to set the Microstep resolution.

The DRV8825 supports microstepping up to a resolution of 1/32. Microstepping creates smoother motion as each step is broken up. Microstepping also greatly reduces the vibration of the motor resulting in quieter motion so I recommend setting it to the maximum resolution.

Here is a table of each pin combination:

M0 M1 M2 Microstep resolution
Low Low Low Full step
High Low Low 1/2 step
Low High Low 1/4 step
High High Low 1/8 step
Low Low High 1/16 step
High Low High 1/32 step
Low High High 1/32 step

This table and other information I am using in this guide can be found in the Pololu DRV8825 website here.

For this example, we are going to set the Microstep resolution to 1/32 (max Microstep resolution).

void loop(){
digitalWrite(M0, HIGH);
digitalWrite(M2, LOW);
digitalWrite(ENABLE, HIGH);

You may have noticed this the variable #define stepsPerRevolution 6400 created earlier. The 6400 is calculated by multiplying the full step resolution by the Microstep resolution.

To calculate the full step resolution, use the following equation:

`"Full step resolution" = 360/("step angle")`

In this case, I am using a common NEMA17 stepper motor with a step angle of 1.8° so to calculate the stepsPerRevolution:

`"stepsPerRevolution" = 360/(1.8) * 32 =` 6400

Next, we move onto moving the stepper motor:

digitalWrite(dirPin, LOW);
digitalWrite(ENABLE, LOW);
for (int i = 0; i < 48000; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(100);
digitalWrite(stepPin, LOW);
delayMicroseconds(100);
}
digitalWrite(ENABLE, HIGH);

This line: digitalWrite(ENABLE, LOW); turns the ENABLE input on and off. When HIGH, the current to the motor is turned off, and vice versa.

In this example, the motor will turn in one direction (depending on coil wiring), turn off, turn on, turn in the opposite direction, turn off, turn on and repeat...

Every microstep is induced by turning the step pin on and off. The faster we do this, the faster the motor will turn. In this case, there is a 100µs delay between pulses so it will take `100*10^-6 * 6400 = 0.64s` to complete one turn of the motor.

To do a certain number of turns in a given direction, we set a for loop to send step pulses for `"stepsPerRevolution"*"number of turns."` In this case, a value of 48000 means that the motor will turn `48000/6400 = 7.5` revolutions before turning in the opposite direction.

To turn the motor in the oppostite direction we simply set the dirPin to be high:

digitalWrite(dirPin, HIGH);
digitalWrite(ENABLE, LOW);
for (int i = 0; i < 48000; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(100);
digitalWrite(stepPin, LOW);
delayMicroseconds(100);
}
digitalWrite(ENABLE, HIGH);

If we put all of this code together, we get a program that turns a stepper motor 7.5 revolutions in one direction, and then 7.5 times in the opposite direction:

#define dirPin 13
#define stepPin 14
#define stepsPerRevolution 6400
#define M0 27
#define M1 26
#define M2 25
#define ENABLE 33

void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(M0, OUTPUT);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(ENABLE, OUTPUT);
}

void loop(){
digitalWrite(M0, HIGH);
digitalWrite(M2, LOW);
digitalWrite(ENABLE, HIGH);


digitalWrite(dirPin, LOW);
digitalWrite(ENABLE, LOW);
for (int i = 0; i < 48000; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(100);
digitalWrite(stepPin, LOW);
delayMicroseconds(100);
}
digitalWrite(ENABLE, HIGH);

digitalWrite(dirPin, HIGH);
digitalWrite(ENABLE, LOW);
for (int i = 0; i < 48000; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(100);
digitalWrite(stepPin, LOW);
delayMicroseconds(100);
}
digitalWrite(ENABLE, HIGH);
}

Using the completed code above, you can edit the variables and incorporate it into your own projects.

I hope you found this guide useful, in the future I plan on making a similar guide on how to program motor control on an ESP32 with a webserver interface.

Find me elsewhere


© 2022 Richard Geoghegan