ESP8266 NodeMCU – Controling Stepper Motor with ULN2003 Driver

In this tutorial, you will learn how to use the UNL2003 driver to control a simple stepper motor. To make precise movements with control distance, such as 3D printers, then you should totally follow this tutorial.

Parts Required

The Stepper Motor and ULN2003 Driver

Figure 1

A stepper motor converts electronic signals into mechanical movement each time an incoming pulse is applied to the motor. Each pulse moves the shaft in fixed increments. If the stepper motor has a 1.8° step resolution, then in order for the shaft to rotate one complete revolution, in full step operation, the stepper motor would need to receive 200 pulses, 360° ÷ 1.8 = 200.

For that to happen, we need to use stepper drives, which control how a stepper motor operates. There are three commonly used excitation modes for stepper motors: full step, half step and micro-stepping. These excitation modes have an effect on both the running properties and torque the motor delivers. In our case, is half step excitation mode and it is a 28BYJ-48 – 5V Stepper Motor.

So, half step excitation mode is a combination of one phase and two-phase. This results in half the basic step angle. This smaller step angle provides smoother operation due to the increased resolution of the angle. We can see an example in figure 2.

Figure 2

It is not recommended to directly power the stepper motor from the output of the NodeMCU board. When the stepper motor draws too much current you can damage the Board.

In order to be able to deliver all the current to the stepper motor, we will use the ULN2003 driver board. The ULN2003 is a high-voltage, high-current Darlington drivers comprised of seven NPN Darlington pairs. This board only uses 4. All units feature integral clamp diodes for switching inductive loads.

In figure 3 you can observe the internal transistor of one channel.

Figue 3

Circuit

Figure 4

Since the voltage output of the ESP8266 NodeMCU board is 3.3V, and hence insufficient to power our stepper motor, a 9V battery was used, along with an LM7805 voltage regulator in order to feed the ULN2003 driver with the desired 5V. Connect the IN pins on the ULN2003A driver to pins on NodeMCU board:

  • IN1 pin on the ULN2003A driver to pin D1 on NodeMCU board
  • IN2 pin on the ULN2003A driver to pin D2 on NodeMCU board
  • IN3 pin on the ULN2003A driver to pin D3 on NodeMCU board
  • IN4 pin on the ULN2003A driver to pin D4 on NodeMCU board

Instaling Libraries For VS1838B

To get our stepper motor up and running, we first need to install a library to control its driver, which is the AccelStepper library. Although the Arduino IDE already includes a library for stepper motors (http://arduino.cc/en/Reference/Stepper), this library introduces some significant improvements, such as acceleration and deceleration support, capability to control multiple simultaneous stepper motors and many more.

To install it, go to Sketch > Include Library > Manage Libraries… and then type in the research box “accelstepper”. Look for AccelStepper by Mike McCauley, click on that entry and then select Install, as shown in figure 1. This way, we are ready to start coding!

Figure 5

Coding

In this tutorial, we simply want to make the stepper motor to go back and forward in 90 and 180-degree angles and then go back to the original position (0 degrees), over and over again.

We think that, with this code, you are able to understand how to control the stepper motor, so now you just need to apply this knowledge to your future applications. Enjoy!

#include <AccelStepper.h>           // Load the AccelStepper library

#define motorPin1  5                // IN1 pin on the ULN2003A driver to pin D1 on NodeMCU board
#define motorPin2  4                // IN2 pin on the ULN2003A driver to pin D2 on NodeMCU board
#define motorPin3  0                // IN3 pin on the ULN2003A driver to pin D3 on NodeMCU board
#define motorPin4  2                // IN4 pin on the ULN2003A driver to pin D4 on NodeMCU board

int stepsPerRevolution = 64;        // steps per revolution
int degreePerRevolution = 5.625;    // degree per revolution

/*
 * AccelStepper::FULL2WIRE (2) means: 2 wire stepper (2 pins needed). 
 * AccelStepper::FULL3WIRE (3) means: 3 wire stepper, like a harddisk motor (3 pins needed). 
 * AccelStepper::FULL4WIRE (4) means: 4 wire stepper (4 pins needed). 
 * AccelStepper::HALF3WIRE (6) means: 3 wire half stepper, like a harddisk motor (3 pins needed) 
 * AccelStepper::HALF4WIRE (8) means: 4 wire half stepper (4 pins needed) 
 *
 * AccelStepper uses AccelStepper::FULL4WIRE (4 pins needed) by default.
 */
AccelStepper stepper(AccelStepper::HALF4WIRE, motorPin1, motorPin3, motorPin2, motorPin4);

void setup() {
  Serial.begin(9600);               // initialise the serial monitor

  stepper.setMaxSpeed(1000.0);      // set the max motor speed
  stepper.setAcceleration(100.0);   // set the acceleration
  stepper.setSpeed(200);            // set the current speed

}

// Degrees of the momevement. So first to 90 degrees, then to -90 graden then to 180 degrees etc.
int steps[] = { 90, -90, 180, -180, 0 };

// The total entries in steps[]
int stepsCount = 5;

// Keeps track of the position in steps[] we are about to run
int stepsIndex = 0;

void loop() {

  // If the stepper isn't moving and doesn't have to go any distance
  if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    // Move the stepper to the degrees on the position of stepIndex in steps[]
    stepper.moveTo(degToSteps(steps[stepsIndex]));

    // Increase the index when each movement has finished
    stepsIndex++;

    // If we have executed all positions of steps[]
    if (stepsIndex > stepsCount) {

      // Set the index to 0 to restart the process
      stepsIndex = 0;
    }
  }

  stepper.run();

}

/*
 * Converts degrees to steps
 * 
 * 28BYJ-48 motor has 5.625 degrees per step
 * 360 degrees / 5.625 = 64 steps per revolution
 * 
 * Example with degToSteps(45):
 * (64 / 5.625) * 45 = 512 steps
 */
float degToSteps(float deg) {
  return (stepsPerRevolution / degreePerRevolution) * deg;
}

References:

  • https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html
  • https://www.makerguides.com/28byj-48-stepper-motor-arduino-tutorial/
  • https://www.makerguides.com/wp-content/uploads/2019/04/ULN2003-Datasheet.pdf
  • https://www.makerguides.com/wp-content/uploads/2019/04/ULN2003-Stepper-Motor-Driver-PCB.pdf
  • https://www.makerguides.com/wp-content/uploads/2019/04/28byj48-Stepper-Motor-Datasheet.pdf

7 thoughts on “ESP8266 NodeMCU – Controling Stepper Motor with ULN2003 Driver

  1. Hi, I do think this is a great blog. I stumbledupon it 😉
    I am going to come back yet again since I saved as
    a favorite it. Money and freedom is the greatest way to change, may you be rich and
    continue to help others.

  2. sketch_mar09a:33:11: error: stray ‘#’ in program

    int steps[] = { 90, -90, 180, -180, 0 };

    ^

    sketch_mar09a:47:37: error: stray ‘#’ in program

    stepper.moveTo(degToSteps(steps[stepsIndex]));

    ^

    sketch_mar09a:33:10: error: expected initializer before ‘&’ token

    int steps[] = { 90, -90, 180, -180, 0 };

    ^

    sketch_mar09a:33:15: error: expected unqualified-id before ‘]’ token

    int steps[] = { 90, -90, 180, -180, 0 };

    ^

    C:\Users\oskar\OneDrive\Dokumenty\Arduino\sketch_mar09a\sketch_mar09a.ino: In function ‘void loop()’:

    sketch_mar09a:44:29: error: ‘amp’ was not declared in this scope

    if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    ^

    sketch_mar09a:44:32: error: expected ‘)’ before ‘;’ token

    if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    ^

    sketch_mar09a:44:34: error: ‘amp’ was not declared in this scope

    if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    ^

    sketch_mar09a:44:66: error: expected ‘;’ before ‘)’ token

    if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    ^

    sketch_mar09a:75:1: error: expected ‘}’ at end of input

    }

    ^

    exit status 1
    stray ‘#’ in program

  3. #include // Load the AccelStepper library

    #define motorPin1 5 // IN1 pin on the ULN2003A driver to pin D1 on NodeMCU board
    #define motorPin2 4 // IN2 pin on the ULN2003A driver to pin D2 on NodeMCU board
    #define motorPin3 0 // IN3 pin on the ULN2003A driver to pin D3 on NodeMCU board
    #define motorPin4 2 // IN4 pin on the ULN2003A driver to pin D4 on NodeMCU board

    int stepsPerRevolution = 64; // steps per revolution
    int degreePerRevolution = 5.625; // degree per revolution

    /*
    * AccelStepper::FULL2WIRE (2) means: 2 wire stepper (2 pins needed).
    * AccelStepper::FULL3WIRE (3) means: 3 wire stepper, like a harddisk motor (3 pins needed).
    * AccelStepper::FULL4WIRE (4) means: 4 wire stepper (4 pins needed).
    * AccelStepper::HALF3WIRE (6) means: 3 wire half stepper, like a harddisk motor (3 pins needed)
    * AccelStepper::HALF4WIRE (8) means: 4 wire half stepper (4 pins needed)
    *
    * AccelStepper uses AccelStepper::FULL4WIRE (4 pins needed) by default.
    */
    AccelStepper stepper(AccelStepper::HALF4WIRE, motorPin1, motorPin3, motorPin2, motorPin4);

    void setup() {
    Serial.begin(9600); // initialise the serial monitor

    stepper.setMaxSpeed(1000.0); // set the max motor speed
    stepper.setAcceleration(100.0); // set the acceleration
    stepper.setSpeed(200); // set the current speed

    }

    // Degrees of the momevement. So first to 90 degrees, then to -90 graden then to 180 degrees etc.
    int steps[] = { 90, -90, 180, -180, 0 };

    // The total entries in steps[]
    int stepsCount = 5;

    // Keeps track of the position in steps[] we are about to run
    int stepsIndex = 0;

    void loop() {

    // If the stepper isn’t moving and doesn’t have to go any distance
    if (!stepper.isRunning() && stepper.distanceToGo() == 0) {

    // Move the stepper to the degrees on the position of stepIndex in steps[]
    stepper.moveTo(degToSteps(steps[stepsIndex]));

    // Increase the index when each movement has finished
    stepsIndex++;

    // If we have executed all positions of steps[]
    if (stepsIndex > stepsCount) {

    // Set the index to 0 to restart the process
    stepsIndex = 0;
    }
    }

    stepper.run();

    }

    /*
    * Converts degrees to steps
    *
    * 28BYJ-48 motor has 5.625 degrees per step
    * 360 degrees / 5.625 = 64 steps per revolution
    *
    * Example with degToSteps(45):
    * (64 / 5.625) * 45 = 512 steps
    */
    float degToSteps(float deg) {
    return (stepsPerRevolution / degreePerRevolution) * deg;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *