2 stepper motors running at SAME TIME - Arduino uno

Hi there,
Im trying to get two stepper motors to rotate at the same time. Im using two Sn754410NE drivers and an Uno Arduino. pins 2-5 go to stepper 1 and pins 8-11 goes to stepper 2. when i run the program (shown below) both steppers rotate but NOT AT THE SAME TIME:(. the first one rotates and then the second one rotates. is there a way to mod this program so BOTH STEPPERS RUN AT THE SAME TIME:). ANY HELP would be appreciated. thanks in advance. this is the code that im using (its basically from the samples, just modifies a bit):
CHEERS!!

#include <Stepper.h>

const int step_360 = 200;// 360 number of steps per/rev
// initialize the stepper library on pins 2-5 n 8-11
Stepper myStepper1(step_360,2,3,4,5);
Stepper myStepper2(step_360,8,9,10,11);

void setup()
{
// set the speed at 60 rpm:
myStepper1.setSpeed(60);//left
myStepper2.setSpeed(60);//right
// initialize the serial port:
Serial.begin(9600);
}
void loop()
{
// step one revolution in one direction:
Serial.println("clockwise");
myStepper1.step(step_360);
myStepper2.step(step_360);
delay(500);
}

when i run the program (shown below) both steppers rotate but NOT AT THE SAME TIME

No need to shout. Of course they don't run at the same time. The step() method is a blocking function. It does not return until the motor has completed stepping the specified number of steps. The speed and number of steps defines how long that takes.

You can't really make them step at the same time. What you can do, though, is to make them step one at a time in much smaller steps, so that they appear to be moving at the same time.

for(int s=0; s<step_360; s++)
{
  myStepper1.step(1);
  myStepper2.step(1);
}

Depending on the driver and the stepper motor, you may be able to use half, quarter, or eighth step mode, and step in even smaller amounts, making the motors move more and more in sync,

You can in either of two ways: Firstly, you can connect one set of stepper control signals from the Arduino to both driver channels. This has the effect of running the steppers in lockstep. (I once built a CNC router with two steppers driving the x-axis, and this was how I ensured that the steppers stayed in sync.)

If that's not what you want, you can make sure that both sets of control signals are connected to pins on the same port, and then exercise control by doing 8-bit wide outputs to the port rather than to individual pins with digitalWrite().

Edit: clarification

PaulS:

when i run the program (shown below) both steppers rotate but NOT AT THE SAME TIME

No need to shout. Of course they don't run at the same time. The step() method is a blocking function. It does not return until the motor has completed stepping the specified number of steps. The speed and number of steps defines how long that takes.

You can't really make them step at the same time. What you can do, though, is to make them step one at a time in much smaller steps, so that they appear to be moving at the same time.

for(int s=0; s<step_360; s++)

{
 myStepper1.step(1);
 myStepper2.step(1);
}




Depending on the driver and the stepper motor, you may be able to use half, quarter, or eighth step mode, and step in even smaller amounts, making the motors move more and more in sync,

thanks sooo much!!! that for loop seems to do the trick. since u can tell my programing skills are next to nil, how would u modify the loop so one stepper does say 90 degrees and one does 360.? thanks again. greatly appreciated!:slight_smile:

how would u modify the loop so one stepper does say 90 degrees and one does 360.?

Determine which position change is larger (360). Then, define the amount each motor needs to step on each pass through loop.
float step1Inc = 90.0/360.0;
float step2Inc = 360.0/360.0;

Then, loop for 360 steps. On each pass through loop, set the new position.

float step1Pos = 0.0;
float step2Pos = 0.0;

for(int i=0; i<360; i++)
{
  step1Pos += step1Inc;
  step2Pos += step2Inc;

  // Move stepper 1 to step1Pos
  // Move stepper 2 to step2Pos
}

Since the stepper expects to move in whole steps, step1Pos = 0.25, 0.50, and 0.75 will cause nothing to happen for stepper 1, while stepper 2 steps 3 times. Then when step1Pos gets to 1.0, it will step once.

You could try something like this - Speed might be an issue -

Dir1 and Dir2 control the direction the motor will step +1 and -1. Dir1 or Dir2 = 0 will result in no motion for that motor.
How often you call them controls the motor speed. Each time you call motor 1 or Motor 2 you will get 1 step.
You could use half stepping but that would require 8 patterns (0-7) and the necesary changes to Motor1 and Motor2

int StepCt1 = 0;
int StepCt2 = 0;
int Dir1;
int Dir2;


void Motor1(int Direction){
   StepCt1=Stepct1+Direction;
   StepCt1=StepCt1 && 3;       / StpepCt1 ranges from 0 to 3,  -1 = B11111111 so B11111111 && B00000011 = B00000011
   switch (StepCt1)
      case 0:
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
          digitalWrite(4, LOW);
          digitalWrite(5, LOW); 
          break;
      case 1:
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
          digitalWrite(4, LOW);
          digitalWrite(5, LOW); 
          break;
      case 2:
          digitalWrite(2, LOW);
          digitalWrite(3, LOW);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW); 
          break;
      case 3:
          digitalWrite(2, LOW);
          digitalWrite(3, LOW);
          digitalWrite(4, LOW);
          digitalWrite(5, HIGH); 
          break;
    }
}
void Motor2(int Direction){
   StepCt2=Stepct2+Direction;
   StepCt2=StepCt2 && 3;       / StpepCt1 ranges from 0 to 3,  -1 = B11111111 so B11111111 && B00000011 = B00000011
   switch (StepCt2)
      case 0:
          digitalWrite(8, HIGH);
          digitalWrite(9, LOW);
          digitalWrite(10, LOW);
          digitalWrite(11, LOW); 
          break;
      case 1:
          digitalWrite(8, LOW);
          digitalWrite(9, HIGH);
          digitalWrite(10, LOW);
          digitalWrite(11, LOW); 
          break;
      case 2:
          digitalWrite(8, LOW);
          digitalWrite(9, LOW);
          digitalWrite(10, HIGH);
          digitalWrite(11, LOW); 
          break;
      case 3:
          digitalWrite(8, LOW);
          digitalWrite(9, LOW);
          digitalWrite(10, LOW);
          digitalWrite(11, HIGH); 
          break;
    }
}

I think following logic should do the trick

Say you have 2 Steppers A & B and you want it to rotate 90 & 270 deg at the same time and for the same time say Motor are of 60 PPR (PWM output rather than Digital will be good for this method). (this logic has nothing to do with the example provided with IDE) My simple logic is as you have individual driver for your motors you will only need "Clock Pulses" to run the motor. if your driver consist of any inbuilt clock then you can easily replace the inbuilt clock pulses with the Arduino generated pulses. this is applicable to Direction pulses as well.

The logic:
initial setup
set any 2 pins to output mode ( here consider pin 6 & 7 for Motor A & B respectively)
Determine which will take more steps to get to desire position (in this case B)
Declare an Array of String for the max number of steps
now find the proportionate motion speed like here it is 1:3 so you should have to fire 1 A pulse for each third B pulse.
use following loop to fill the array
for (i = 0; i < StpB; i++){
if ( i % 3 ==0) {
AryTxt = "11" } else {
AryTxt = "01"
}
}
Now you have a set of pulses that to be fire on same interval ( at the same delay(time) )
you can differentiate the pulses individually using charAt() String function (see http://arduino.cc/en/Tutorial/StringCharacters )
you only have to do this
separate the pulse data before you call delay
it will be some thing like this
for (i = 0; i < StpB; i++){
_ char M = AryTxt*.charAt(1);_
_char N = AryTxt.charAt(2);
if (M == 1) {
digitalWrite(6, LOW);}*

else {
digitalWrite(6, HIGH);}_

if (N == 1) {
* digitalWrite(7, LOW);}*
else {
digitalWrite(7, HIGH);}
delay(10)
}
you should have sync motor.

The technique proposed by @PaulS is very simple and easily extended to any number of motors. I have tried it successfully. The only extra I would suggest is to use long integers rather than floating point. For example if you want one to step 23 times and the other 360 times make the loop = 360 * 23 = 8280 and then one motor steps once every 23 iterations and the other (slower) motor steps once every 360 iterations.

...R

according to my last reply it may possible that you could ran out of memory :stuck_out_tongue: :0
the solution is to avoid that array adding part and club the motor execution with pulse counting

for (i = 0; i < StpB; i++){
if ( i % 3 ==0) {
digitalWrite(6, HIGH);
digitalWrite(7,HIGH);
}
else {
digitalWrite(6, LOW);
digitalWrite(7,HIGH);
}
delay(10)
}

Short and Simple
:slight_smile:

1 Like

hi,I m new in arduino programming and I m trying to get two stepper motors to rotate at the same time. I m using two UCN5860 drivers IC'S and an Arduino Mega 2560.to arduino pins dir=8,Step=6 for the stepper 1 and pins pins dir=9,Step=7 for the stepper 2. when i run the program (shown below) no one steppers rotate :frowning:

i want to control the position of both steppers in such a way that when entering command through serial monitor of arduino then compares input char if it is "a" then move both steppers at the same time to 90 degree then after some delay reverse to its initial position i.e: 0 degree....in the same manner if it is "b" then move both steppers at the same time to 180 degree then after some delay reverse to its initial position i.e: 0 degree..

please give me some advise so that i can run the following code:
please help :frowning:

#define STP 6
#define DIR 8
#define STP1 7
#define DIR1 9

void applyBrakes()
{
digitalWrite(DIR, LOW);
digitalWrite(STP, LOW);
digitalWrite(DIR1, LOW);
digitalWrite(STP1, LOW);
delayMicroseconds(50);
}

void stepper1Forward()
{
digitalWrite(DIR, HIGH);
digitalWrite(STP, HIGH);
delayMicroseconds(2); //
digitalWrite(STP, LOW);
delayMicroseconds(100);
}

void stepper1Reverse()
{
digitalWrite(DIR, LOW);
digitalWrite(STP, HIGH);
delayMicroseconds(2);
digitalWrite(STP, LOW);
delayMicroseconds(100);
}

/**

  • Rotate stepper 1 forward by 1 step
    */
    void stepper2Forward()
    {
    digitalWrite(DIR1, HIGH);
    digitalWrite(STP1, HIGH);
    delayMicroseconds(2); //
    digitalWrite(STP1, LOW);
    delayMicroseconds(100);
    }

void stepper2Reverse()
{
digitalWrite(DIR1, LOW);
digitalWrite(STP1, HIGH);
delayMicroseconds(2);
digitalWrite(STP1, LOW);
delayMicroseconds(100);
}

void setup()
{

pinMode(DIR, OUTPUT);
pinMode(STP, OUTPUT);
pinMode(DIR1, OUTPUT);
pinMode(STP1, OUTPUT);

}
void loop()
{

if(Serial.available() > 0)
{

char character = (char) Serial.read();
if(character == 'a') //90
{
for(int i = 0; i <50 ; i++)
{
stepper1Forward();
}delay( 10 );

for(int i = 0; i <50 ; i++)
{
stepper2Forward();
}delay( 10 );

for(int i = 0; i <50 ; i++)
{
stepper1Reverse();
}delay( 10 );
for(int i = 0; i <50 ; i++)
{
stepper2Reverse();
}delay( 10 );
void applyBrakes();

}

else if(character == 'b') //180

{ for(int i = 0; i <100 ; i++)
{
stepper1Forward();
}delay( 10 );

for(int i = 0; i <100 ; i++)
{
stepper2Forward();
}delay( 10 );

for(int i = 0; i <100 ; i++)
{
stepper1Reverse();
}delay( 10 );
for(int i = 0; i <100 ; i++)
{
stepper2Reverse();
}delay( 10 );

void applyBrakes();

}
}

PaulS:
Determine which position change is larger (360). Then, define the amount each motor needs to step on each pass through loop.
float step1Inc = 90.0/360.0;
float step2Inc = 360.0/360.0;

Then, loop for 360 steps. On each pass through loop, set the new position.

float step1Pos = 0.0;

float step2Pos = 0.0;

for(int i=0; i<360; i++)
{
  step1Pos += step1Inc;
  step2Pos += step2Inc;

// Move stepper 1 to step1Pos
  // Move stepper 2 to step2Pos
}



Since the stepper expects to move in whole steps, step1Pos = 0.25, 0.50, and 0.75 will cause nothing to happen for stepper 1, while stepper 2 steps 3 times. Then when step1Pos gets to 1.0, it will step once.

aadityadengle:
according to my last reply it may possible that you could ran out of memory :stuck_out_tongue: :0
the solution is to avoid that array adding part and club the motor execution with pulse counting

for (i = 0; i < StpB; i++){
if ( i % 3 ==0) {
digitalWrite(6, HIGH);
digitalWrite(7,HIGH);
}
else {
digitalWrite(6, LOW);
digitalWrite(7,HIGH);
}
delay(10)
}

Short and Simple
:slight_smile:

This really saved my months of hardwork. After being stuck on the topic of operating multiple steppers simultaneously your reply in this thread helped me to get a better perspective of the problem and it is mostly solved. Thank you Aaditya

Here is my code that I used to drive two steppers at the same time. I can choose independent steps for each motor. It is used on a desktop plotter with two bipolar steppers and L293D H-bridge drivers. Nobody posted this solution before, why? Where is the mistake? :o

void drive(int xgo, int ygo) {

//make two dir variables, allows driving backward
int xdir = 1, ydir = 1;
if (xgo < 0) {
xdir = -1;
xgo*=-1;
}
if (ygo < 0) {
ydir = -1;
ygo *=-1;
}

int counter = 0;
if(xgo>ygo){ //xgo is bigger
for (int i = 0; i < xgo; i++) { //loop with xgo
x.step(xdir);
counter += ygo;
if (counter >= xgo) {
counter -= xgo;
y.step(ydir);
}
}
}
else{ //ygo is bigger or equal, loop with ygo , same as above, but x <-> y;
for (int i = 0; i < ygo; i++) {
y.step(ydir);
counter += xgo;
if (counter >= ygo) {
counter -= ygo;
x.step(xdir);
}
}
}
}

Hopefully I haven't made a mistake; :confused:

you can control 2 stepper or more with a common pins. just connect the N1(of 1st motor) and N1(2nd motor) in series like wise the others too and connect them to your arduino and write the code as if you were writing for just one motor.

PaulS:

for(int s=0; s<step_360; s++)

{
  myStepper1.step(1);
  myStepper2.step(1);
}




Depending on the driver and the stepper motor, you may be able to use half, quarter, or eighth step mode, and step in even smaller amounts, making the motors move more and more in sync,

Yes, it does, work, thank you very much. Now I just have to figure out how to tie into my code and we will be off and running.
simple but effective.