Making 2 NEMA-17 turn together using TB6600 driver with AccelStepper Library

Hello, I have 2 NEMA-17 Stepper motor connected each to a TB6600 stepper driver, and i am using the code below using AccelStepper library. Here is the code:

#include <AccelStepper.h>

#define dirPin1 2
#define stepPin1 3
#define dirPin2 4
#define stepPin2 5
#define motorInterfaceType 1

AccelStepper stepper1 = AccelStepper(motorInterfaceType, stepPin1, dirPin1);
AccelStepper stepper2 = AccelStepper(motorInterfaceType, stepPin2, dirPin2);

void setup() {
stepper1.setMaxSpeed(1000);
stepper2.setMaxSpeed(1000);
stepper1.setAcceleration(500);
stepper2.setAcceleration(500);
}

void loop() {
stepper1.moveTo(8000);
stepper2.moveTo(8000);

stepper1.runToPosition();
stepper2.runToPosition();

delay(1000);

stepper1.moveTo(0);
stepper2.moveTo(0);
stepper1.runToPosition();
stepper2.runToPosition();
delay(1000);
}

What i want is that i need both the motors to turn simultaneously but with this code, they are turning one by one.
Stepper 1 does the rotation, stops then Stepper 2 repeats the same process.

In the AccelStepper examples, there is one sample code that demonstrates an array[ ] of steppers.

I have built test code from that example - that runs as many steppers as you can find up to the capabilities of the cpu at hand (typ 4000 steps/second on 8-bit AVRs)

It works well, and flawlessly.
Give it a shot, then post your code, and if you’re still stuck, we can push you forward.

1 Like

Add your two AccelStepper's into a MultiStepper. See the AccelStepper and MultiStepper documentation:

https://www.airspayce.com/mikem/arduino/AccelStepper/annotated.html

Multistepper doesn't use acceleration and deceleration. I don't know if @yanishrao really wants them to move synchronized or only wants them to move at the same time.

@yanishrao : You could use my MobaTools library to move them at the same time. That is fairly easy with the MoToStepper class. The lib can be installed by means of the library manager.

#include <MobaTools.h>

#define dirPin1 2
#define stepPin1 3
#define dirPin2 4
#define stepPin2 5
#define stepsPerRev 200

MoToStepper stepper1 (stepsPerRev, STEPDIR );
MoToStepper stepper2 (stepsPerRev, STEPDIR );

void setup() {
    stepper1.attach( stepPin1, dirPin1 );
    stepper2.attach( stepPin2, dirPin2 );
    stepper1.setSpeedSteps(10000); //=Steps/sec * 10
    stepper2.setSpeedSteps(10000);
    stepper1.setRampLen( 200 );       // steps until full speed
    stepper2.setRampLen( 200 );
}

void loop() {
    stepper1.writeSteps(8000);    // go to position 8000 steps from zeropoint
    stepper2.writeSteps(8000);

    while ( stepper1.moving() || stepper2.moving() ); // wait until both steppers reach target position
    delay(1000);

    stepper1.writeSteps(0);
    stepper2.writeSteps(0);
    while ( stepper1.moving() || stepper2.moving() ); // wait until both steppers reach target position
    delay(1000);
}
1 Like

Thank you, i'll look into it

It will be a differential type steering robot with obstacle detection, 2 NEMA, one on each back side and 1 caster free wheel in front.
Im experimenting and testing on the rotation of the motors. I'll need 4 conditions i suppose and assuming the speed of the motor is X i'll need to create some conditions:

  1. Forward motion, Left Motor clockwise speed X = Right Motor clockwise speed X
  2. Backward motion, Left Motor speed X anticlockwise = Right Motor anticlockwise speed X
    3.Right turn: Left Motor clockwise speed X and Right Motor clockwise speed Half X
    4.Left turn: Left Motor clockwise speed Half X and Right Motor clockwise speed X

Also i'll need to start the motor with a small speed then increase to a constant max speed, because the motor does not turn when you try to start it with a direct max speed.
And im also having issues on the clockwise and anticlockwise rotation of the motor

Which board are you using? If it is a supported processor, that should be easily done with MoToStepper. If you don't want the motor to stop automatically at a distinct target position, you can use the rotate method:

stepper.rotate(1); // start rotating CW ( with acceleration )
stepper.rotate(-1); // start rotating CCW ( with acceleration )
stepper.rotate(0); // stop with decelerateion

The steps are created in the background by interrupts, so you don't have to bother about it in the sketch.
With AccelStepper you must use the run() method to create the steps with acceleration/deceleration. Maybe a little bit more complicated ( depending what else your sketch should do while the steppers are running ). But it shurely is possible too.

1 Like

I am using an Arduino Mega 2560.
The code below is running both motor together without it stopping, but the issue im having is that one is turning clockwise and the other one anticlockwise. How can i solve this?

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::DRIVER, 3,2); // 2 = direction and 3 = step
AccelStepper stepper2(AccelStepper::DRIVER, 5,4); // 2 = direction and 3 = step

void setup()
{  
   stepper1.setMaxSpeed(1000);
   stepper1.setSpeed(250);  
   stepper2.setMaxSpeed(1000);
   stepper2.setSpeed(250);  
}

void loop()
{  
   stepper1.runSpeed();
   stepper2.runSpeed();
}

I think the wiring of your two steppers is different. But you can simply set the speed to a negative value. But be aware that runspeed() does not use acceleration when starting the stepper.

Both motors are identical as well as the wiring. The negative value solved the issue though.
As for the acceleration for a max speed of 1000 and speed of 250, it appears to be able to start and run well, so then no need for the acceleration
@MicroBahner So now for backward and forward motion i can use this piece of code whereby both motors are turning in the same direction indefinitely as well as along with the obstacle detection sensor etc to control it, but how can i modify this code such that i can have my right and left turn conditions? For this one the motors will need to turn at different speed which i know how to do, but how to make it turn for a number of steps?

#include <AccelStepper.h>
int trigPin=6;
int echoPin=7;
int pingTravelTime;
float inch = 2.54;
float pingTravelDistance;
float distanceToTarget;

AccelStepper stepperL(AccelStepper::DRIVER, 3,2); // 2 = direction and 3 = step ; StepperR = Right motor
AccelStepper stepperR(AccelStepper::DRIVER, 5,4); // 4 = direction and 5 = step ; StepperL = Left motor

void setup()
{  
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
   stepperR.setMaxSpeed(-1000); //Negative since 1 motor was turning clwk and the other anticlkw
stepperL.setMaxSpeed(1000);
   stepperR.setSpeed(-250);  
 stepperL.setSpeed(250);  
}

void loop()
{  
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
digitalWrite(trigPin,LOW);
delayMicroseconds(10);
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,LOW);
pingTravelTime=pulseIn(echoPin,HIGH);
delay(25);
pingTravelDistance=(pingTravelTime*765.*5280.*12)/(3600.*1000000); //distance in inches (Go and return)
distanceToTarget=(pingTravelDistance*inch)/2; //distance in cm
Serial.println(distanceToTarget);
if (distanceToTarget>10)
{
   stepperL.runSpeed();
   stepperR.runSpeed();
}

}

@MicroBahner Look at this code, uploading it gives one issue, the motors does drive but not at the speed set, it is more slower, though it stops when the ultrasonic detects an object.
What i want to know is that how to put an else condition so that when it does detect an object a series of conditions is done:
For e.g it stops the motor first, then turn right or left etc

The code below is how i can achieve the right or left turn by playing with the values that is for e.g if i want to turn right, stepperL should be of higher speed than stepperR. But the issue is that i am not being able to merge those two codes, it appears to be different formats, is it because of the public member functions?

#include <AccelStepper.h>

AccelStepper stepperL(AccelStepper::DRIVER, 3,2); // 2 = direction and 3 = step ; StepperL = Left motor
AccelStepper stepperR(AccelStepper::DRIVER, 5,4); // 4 = direction and 5 = step ; StepperR = Right motor

void setup()
{  
    stepperL.setMaxSpeed(0);
    stepperL.setAcceleration(0);
    stepperL.moveTo(0);
    
    stepperR.setMaxSpeed(-1000.0);
    stepperR.setAcceleration(500.0);
    stepperR.moveTo(-500);
    

}

void loop()
{
    stepperL.run();
    stepperR.run();
}

Well that's the problem I already addressed in #7: The run-methods of Accelstepper do create at max one step per call. To reach the set speed, you must call them very frequently ( more often than your step frequency ). But your loop doesn't cycle fast enough: pulseIn() blocks, and you have a delay of 25ms. That slows the speed of the stepper significantly.

1 Like

Any solution that you can propose?
I think maybe what i want is easier with DC motors and a L298N driver, but i already had 2 NEMA 17 at home with the respective TB6600 drivers, that's why i wanted to give it a try

At least you should get rid of your delay(). Depending on your set speed and the measured distance, the blocking time of pulseIn may be short enough to not slow down the speed.

1 Like
#include <AccelStepper.h>
int trigPin=6;
int echoPin=7;
int pingTravelTime;
float inch = 2.54;
float pingTravelDistance;
float distanceToTarget;

AccelStepper stepperL(AccelStepper::DRIVER, 3,2); // 2 = direction and 3 = step ; StepperR = Right motor
AccelStepper stepperR(AccelStepper::DRIVER, 5,4); // 4 = direction and 5 = step ; StepperL = Left motor

void setup()
{  
Serial.begin(9600);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
   stepperR.setMaxSpeed(-1000); //Negative since 1 motor was turning clwk and the other anticlkw
stepperL.setMaxSpeed(1000);
   stepperR.setSpeed(-250);  
 stepperL.setSpeed(250);  
}

void loop()
{  
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
digitalWrite(trigPin,LOW);
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,LOW);
pingTravelTime=pulseIn(echoPin,HIGH);
pingTravelDistance=(pingTravelTime*765.*5280.*12)/(3600.*1000000); //distance in inches (Go and return)
distanceToTarget=(pingTravelDistance*inch)/2; //distance in cm
Serial.println(distanceToTarget);
if (distanceToTarget>10)
{
   stepperL.runSpeed();
   stepperR.runSpeed();
}

}

Removed some delays, speed looks ok.
Now how can we control the motors speed individually so that i can implement the left or right turn conditions?
The 2nd code in post #8 show how i can do it, but how to merge it with the full code?
Once you set a speed in the voice setup(), can you change it again in the loop?

Do you really need to measure distance between each step?

Or would it be OK to step (or not) every 100us and measure distance every 20ms?

The best way to do add functionality is to rewrite your code to break the distance measuring, motion planning, and motion execution tasks into different Blink Without Delay or Several Things at the Same Time-like functional chunks.

What i need is simply to make a 2 wheel obstacle detection robot but instead of using DC motors, to use Stepper motors (NEMA 17 with TB6600 driver).
@DaveX Can you help me modify the code and use millis() instead of delay() ?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.