Simultaneously Controlling Stepper Motors with Arduino

Written by: Brandon Tsuge

|

|

Time to read min

In this post, I demonstrate how to simultaneously control two stepper motors, using the Arduino.

Parts Needed

What is a Stepper Motor?

A stepper motor is a type of brushless motor that moves in discrete steps. This is good when the application requires precise position or speed control. For this reason, they are commonly used in 3D printers and robot arms. Steppers also have the ability of creating a holding torque, meaning that they can maintain a position under a certain external load on the output shaft. However, they are not capable of a high output torque when they are spinning quickly. In addition, they consume relatively large amounts of current, which can potentially lead to the motor getting hot. Ultimately, they are easy and reliable to use, especially when you use it with an Arduino and the Sparkfun Easy Drivers.

Stepper Motor and Driver

Building the Circuit

Before building the circuit, solder male header pins to the Sparkfun Easy Drivers. Then solder female header pins to a prototyping circuit board. These header pins will connect directly to the male header pins on the stepper motor driver. Then solder screw terminal blocks to the circuit boards. The screw terminal blocks will need to be soldered to the female header pins. This process allows for more convenient wiring, but it's not necessary. Simply using a breadboard will also work fine.

Stepper Motor Driver Boards
Stepper Motor Driver Board with Screw Terminals

I also use a screw terminal adapter board for the Arduino Nano to make wiring easier as well.

Arduino Nano with Screw Terminal Board

A guide to connect the stepper motor drivers can be found on the motor driver product page.

  • Connect the 4 leads on each stepper motor to the "A" and "B" pins on the motor drivers.

  • For the first motor driver, connect "STEP" on the motor driver to digital pin 2 on the Arduino.

  • Connect "DIR" to digital pin 3.

  • Connect "MS1" to digital pin 4.

  • Connect "MS2" to digital pin 5.

  • Connect "ENABLE" to digital pin 6.

  • Wire a power source to "PWR IN" on both motor drivers.

  • For the second motor driver, connect the "STEP" pin to digital pin 7.

  • Connect "DIR" to digital pin 8.

  • Connect "MS1" to digital pin 9.

  • Connect "MS2" to digital pin 10.

  • Connect "ENABLE" to digital pin 11.

Dual Stepper Motor Wiring Diagram

Simple Arduino Code

Let's first start with getting one stepper motor to spin. This is relatively simple to do with Arduino. Begin the sketch by defining pins 2-6. Give them names so that it's clear how they are connected to the stepper motor driver.

#define Motor1_stp 2 
#define Motor1_dir 3 
#define Motor1_MS1 4 
#define Motor1_MS2 5 
#define Motor1_EN  6 

In the setup, set all of these pins to outputs. Write pin 3 (motor direction) to LOW. After you run the program, if the motor is moving in the wrong direction, set this pin to HIGH. Set pins 4 and 5 (MS1 and MS2) to LOW to initiate full steps. If MS1 is set to HIGH and MS2 is set to LOW, the motor will move in half steps. If MS1 is set to LOW and MS2 is set to HIGH, the stepper will move in quarter steps. If MS1 and MS2 are both set to HIGH, the motor will move in eighth steps. Lastly, set pin 6 to LOW enable the motor driver.

void setup() {
  //Set all motor pins to outputs
  pinMode(Motor1_stp, OUTPUT);
  pinMode(Motor1_dir, OUTPUT);
  pinMode(Motor1_MS1, OUTPUT);
  pinMode(Motor1_MS2, OUTPUT);
  pinMode(Motor1_EN, OUTPUT);

  
  //Write initial values to motor pins
  digitalWrite(Motor1_dir, LOW); 
  digitalWrite(Motor1_MS1, LOW); 
  digitalWrite(Motor1_MS2, LOW);
  digitalWrite(Motor1_EN, LOW); 
}

In the loop, first write pin 2 (STEP) to LOW, delay by 1ms and then write pin 2 to (HIGH). Add another delay of 1ms at the end of the sketch. The length of the delay determines the speed of the motor. A longer delay slows the motor. A delay of 1ms with MS1 and MS2 both set to LOW will cause the motor to move at its fastest speed.

void loop() {
  digitalWrite(Motor1_stp, LOW);
  delay(1);
  digitalWrite(Motor1_stp,HIGH);
  delay(1);
}
Single Spinning Stepper Motor

To get the second motor to spin, you could repeat this process with another set of variables and pin definitions for pins 7-11. However, writing the code in this way will make it impossible for the motors to rotate at different speeds. The maximum speeds of the motors will also be reduced because the sequential use of the delay commands.

#define Motor1_stp 2 
#define Motor1_dir 3 
#define Motor1_MS1 4
#define Motor1_MS2 5 
#define Motor1_EN  6 

#define Motor2_stp 7 
#define Motor2_dir 8 
#define Motor2_MS1 9 
#define Motor2_MS2 10 
#define Motor2_EN  11


void setup() {
  pinMode(Motor1_stp, OUTPUT);
  pinMode(Motor1_dir, OUTPUT);
  pinMode(Motor1_MS1, OUTPUT);
  pinMode(Motor1_MS2, OUTPUT);
  pinMode(Motor1_EN, OUTPUT);
  
  pinMode(Motor2_stp, OUTPUT);
  pinMode(Motor2_dir, OUTPUT);
  pinMode(Motor2_MS1, OUTPUT);
  pinMode(Motor2_MS2, OUTPUT);
  pinMode(Motor2_EN, OUTPUT);
  

  digitalWrite(Motor1_dir, LOW); 
  digitalWrite(Motor1_MS1, LOW); 
  digitalWrite(Motor1_MS2, LOW);
  digitalWrite(Motor1_EN, LOW); 
  
  digitalWrite(Motor2_dir, LOW); 
  digitalWrite(Motor2_MS1, LOW); 
  digitalWrite(Motor2_MS2, LOW);
  digitalWrite(Motor2_EN, LOW); 
}

void loop() {
  digitalWrite(Motor1_stp, LOW);
  delay(1);
  digitalWrite(Motor1_stp,HIGH);
  delay(1);
  digitalWrite(Motor2_stp, LOW);
  delay(1);
  digitalWrite(Motor2_stp,HIGH);
  delay(1);
}
Two Stepper Motors

Arduino Code for Variable Motor Speed

To get the motors to spin at different speeds, the millis() command would need to be used. This command outputs the time that has passed since the Arduino began running the current sketch. Similar to the simple example above, I define pins 2-11 with the same variable names. I then use millis(), for both motors, to establish an initial time that will later be compared to in an "if" statement. I also define time intervals for each motor step.

//Define Pins for Motor 1
#define Motor1_stp 2 
#define Motor1_dir 3 
#define Motor1_MS1 4 
#define Motor1_MS2 5 
#define Motor1_EN  6 

//Define Pins for Motor 2
#define Motor2_stp 7 
#define Motor2_dir 8 
#define Motor2_MS1 9 
#define Motor2_MS2 10 
#define Motor2_EN  11

//Set up timing
unsigned long previousMotor1Time = millis();
unsigned long previousMotor2Time = millis();
long Motor1Interval = 1;
long Motor2Interval = 10;

In the setup, I set all of the pins to outputs, and the DIR, MS1, MS2, and Enable pins to LOW.

void setup() {
  pinMode(Motor1_stp, OUTPUT);
  pinMode(Motor1_dir, OUTPUT);
  pinMode(Motor1_MS1, OUTPUT);
  pinMode(Motor1_MS2, OUTPUT);
  pinMode(Motor1_EN, OUTPUT);
  pinMode(Motor2_stp, OUTPUT);
  pinMode(Motor2_dir, OUTPUT);
  pinMode(Motor2_MS1, OUTPUT);
  pinMode(Motor2_MS2, OUTPUT);
  pinMode(Motor2_EN, OUTPUT);

  digitalWrite(Motor1_dir, LOW);
  digitalWrite(Motor1_MS1, LOW); 
  digitalWrite(Motor1_MS2, LOW);
  digitalWrite(Motor1_EN, LOW); 

  digitalWrite(Motor2_dir, LOW); 
  digitalWrite(Motor2_MS1, LOW); 
  digitalWrite(Motor2_MS2, LOW);
  digitalWrite(Motor2_EN, LOW); 
}

In the loop, use the millis() command again for both motors, and save it to a new variable. This will be used to determine how much time has passed. Write the STEP pins to LOW. For each motor, if the current time subtracted by the time previous time is greater than the defined time interval for that motor, then write the STEP pin to HIGH to move the motor one step. Then reset the start time to the current time. This is explained in the code snippet below.

void loop() {
  unsigned long currentMotor1Time = millis();
  unsigned long currentMotor2Time = millis();
  digitalWrite(Motor1_stp, LOW);
  digitalWrite(Motor2_stp, LOW);

  if(currentMotor1Time - previousMotor1Time > Motor1Interval){
    digitalWrite(Motor1_stp, HIGH);
    previousMotor1Time = currentMotor1Time;
  }

  if(currentMotor2Time - previousMotor2Time > Motor2Interval){
    digitalWrite(Motor2_stp, HIGH);
    previousMotor2Time = currentMotor2Time;
  }
}
Dual Stepper Motors Spinning at different speeds

For this example, the values are set up so that one motor steps every 1ms and the other motor steps every 10ms. Using this methodology ultimately gives you more versatility than if you were to have used the delay() command. The code for this example can be found here.

The Bored Robot LLC is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com