Go Down

Topic: 2 stepper motors running at SAME TIME - Arduino uno (Read 12 times) previous topic - next topic

prowler_sn

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);    
}

PaulS

Quote
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.

Code: [Select]
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,

Morris Dovey

#2
Feb 25, 2012, 02:27 pm Last Edit: Feb 25, 2012, 02:39 pm by Morris Dovey Reason: 1
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
There's always a better way!

prowler_sn


Quote
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.

Code: [Select]
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!:)

PaulS

Quote
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.
Code: [Select]
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.

kf2qd

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


Code: [Select]

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;
    }
}

aadityadengle

#6
Feb 22, 2014, 09:31 pm Last Edit: Feb 22, 2014, 09:35 pm by aadityadengle Reason: 1
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.

Robin2

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

aadityadengle

according to my last reply it may possible that you could ran out of memory  :P  :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
:)


Go Up