Accelstepper Multiplestepper - Arduino and multiple steppers issues

Hi everyone !

I am working on an art installation with motors. Before i always used Dc motors but i always had trouble with the lack of precision. So today, i am starting using stepper motors (nema 18, 17HS19-2004S1, 0,59Nm) with Tb6600 drivers, 12v 2A power supplies, and arduinos uno.

What i would like to do :
I’d like to set the four stepper motors on the ceiling of a room, equipped with reels of nylon wires. The wires are linked to the four corners of a sheet. I want to pre-program the motors so they move indepently and simultaneously in a choreagraphy that last 3 minutes and loops every nine minutes.

So step by step, it could look like :

-Pause of a long delay at the end or the beginning
-motors starts to run, together or one by one, at different speeds, different accelerations and during different times.

  • when a motors stops, it can pause for one or few seconde an then run again to another position.

For better understanding, this code is for one motor and i would like to run four (or at least two) motors with each its own choregraphy, independent of the others, in a single sketch (apart from the fact that runToPosition is a blocking function, obviously) :

#include <AccelStepper.h>
#define dirPin 2
#define stepPin 3
#define motorInterfaceType 1

AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void setup() {


}
void loop() {
  
  stepper.setMaxSpeed(800);
  stepper.setAcceleration(200);
  stepper.moveTo(8000);
  stepper.runToPosition();
  delay(1000);
  
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(500);
  stepper.moveTo(0);
  stepper.runToPosition();
  delay(3000);

  stepper.setMaxSpeed(1500);
  stepper.setAcceleration(800);
  stepper.moveTo(500);
  stepper.runToPosition();
  delay(1000);
}

So I looked to the Multiplesteppers example. And i’m having trouble.

I tried to modify it in many ways, but i always end up far from the result i am looking for.
exemple :

#include <AccelStepper.h>
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 8, 9);

void setup()
{  

}
void loop()
{
        stepper1.setMaxSpeed(200.0);
        stepper1.setAcceleration(100.0);
        stepper1.moveTo(800);
    if (stepper1.distanceToGo() == 0)
        stepper1.moveTo(400);
        stepper1.run();

        stepper2.setMaxSpeed(300.0);
        stepper2.setAcceleration(100.0);
        stepper2.moveTo(1200);
    if (stepper2.distanceToGo() == 0)
        stepper2.moveTo(400);
    stepper2.run();

}

With this code, for exemple, the first rotation is good on each motors and then they run extremely slow and note in the direction i told or at least want them to.
If i try to had a delay, the two motors run extremely slow from the beginning.

Do you have any advices ? infomations ? helpful references ?

I can feel i’m getting closer to the goal but this is the part where i’m lost

Thanks for reading

Noar

The MultiStepper library does not use acceleration. If you need acceleration you will have to write your own code - it's not very difficult. Have a look at this Simple acceleration code.

It's not clear from your project description whether it is necessary for the moves of the different motors to be coordinated. By that I mean that if motorA move 267 steps and motorB moves 33steps they must both start and finish at the same time. For example, that is normally how a 3D printer works.

If that coordinated movement is not a requirement then you can use the ordinary AccelStepper library for all 4 motors.

The functions delay() and delayMicroseconds() block the Arduino until they complete so they are very likely to prevent the regular production of step pulses for the motors. Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

Hi Robin2! Thanks for your reply.

First (correct me if i’m wrong) i’m not using the Multistepper Library in the Multiplesteppers exemple (link). It seems like can use the acceleration. I’ll check the simple accelaration code.

You’re right, i didn’t precise this : no the motors don’t need to be coordinated. In fact, i prefer if they’re not.
Do yo have an exemple of code reference in mind when you say “the ordinary Accelstepper library for 4 motors” ?

Okay, didn’t knew delay() was blocking. I’m gonna check on millis()

noarno2:
First (correct me if i'm wrong) i'm not using the Multistepper Library

Silly me for thinking the Thread title was relevant :slight_smile:

Do yo have an exemple of code reference in mind when you say "the ordinary Accelstepper library for 4 motors" ?

You can have something as simple as

stepperA.moveTo(NNN);
stepperB.moveTo(MMM);
stepperC.moveTo(KKK);
stepperD,moveTo(LLL);

and

stepperA.run();
stepperB.run()
// etc

...R

The thread title is “Accelstepper Multiplestepper…”. I’m not sure to understand what you mean.

Yes, i tried this code but when I try to chain the first movement with a second, it doesn’t work : when the first movement is complete, the motors doesn’t stop and rewind but continue to turn really slow.

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 8, 9);

void setup()
{  
    stepper1.setMaxSpeed(800.0);
    stepper1.setAcceleration(400.0);
    stepper2.setMaxSpeed(800.0);
    stepper2.setAcceleration(400.0);

}
void loop() {
  
stepper1.moveTo(400);
stepper2.moveTo(400);

stepper1.run();
stepper2.run();
  

stepper1.moveTo(200);
stepper2.moveTo(200);

stepper1.run();
stepper2.run();
 
}

I also tried that, more or less same result:

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 8, 9);

void setup()
{  
    stepper1.setMaxSpeed(800.0);
    stepper1.setAcceleration(400.0);
    stepper2.setMaxSpeed(800.0);
    stepper2.setAcceleration(400.0);

}
void loop() {
  
stepper1.moveTo(400);
stepper2.moveTo(400);

if (stepper1.distanceToGo() == 0)
if (stepper2.distanceToGo() == 0)

stepper1.moveTo(200);
stepper2.moveTo(200);

if (stepper1.distanceToGo() == 0)
if (stepper2.distanceToGo() == 0)

stepper1.moveTo(600);
stepper2.moveTo(600);

stepper1.run();
stepper2.run();
}

You should not be setting the destination in every iteration of loop like this

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

Just set the destination for a new move after the stepper has reached its destination. You can use if (stepper1.distanceToGo == 0) to check for the completion of a move.

And don't duplicate the lines

stepper1.run();
stepper2.run();

just include them in loop() once as the last thing in loop()

Keep in mind that a single call to stepper.run() will only move the motor at most by one step. Stepper.run() needs to be called at a higher frequency than the step rate perhaps 3 times as often (or more). That means that many times when stepper.run() is called there will be no move. The library will only make a step happen when it is time for the next step.

...R

Here is how I move independent steppers to positions in a sequence. Sequences in arrays.

#include <AccelStepper.h>

const int posA[] = {400, 800, 1000, 500, 0};
const int posB[] = { -300, 600, 2000, -500, 0};

const byte enablePin = 8; // needed for the CNC shield

AccelStepper stepperA(AccelStepper::DRIVER, 2, 5);
AccelStepper stepperB(AccelStepper::DRIVER, 3, 6);

void setup()
{
   pinMode(enablePin, OUTPUT); // needed for the CNC shield
   digitalWrite(enablePin, LOW); // needed for the CNC shield

   stepperA.setMaxSpeed(300.0);
   stepperA.setAcceleration(100.0);

   stepperB.setMaxSpeed(300.0);
   stepperB.setAcceleration(100.0);
}

void loop()
{
   static unsigned int indexA = 0;
   static unsigned int indexB = 0;

   if (stepperA.run() == 0) // run() returns 1 while moving 0 when finished
   {
      stepperA.moveTo(posA[indexA]);
      indexA++;
      if (indexA > sizeof(posA) / sizeof(posA[0]))
      {
         indexA = 0;
      }
   }
   if (stepperB.run() == 0)
   {
      stepperB.moveTo(posB[indexB]);
      indexB++;
      if (indexB > sizeof(posB) / sizeof(posB[0]))
      {
         indexB = 0;
      }
   }
}

Hi ! Sorry, i had to take a christmas break. Btw hope you had a nice one and i wish you an happy new year.

Thanks a lot for your replies.

@groundFungus : thanks for that, it’s a really nice code. It helps me understanding better the array. But I think I might be struggling to add the speed accelaration and stop time for each motor at each movement. i’m gonna work on it

@ robin2 :
I think i understand what you mean but when i tried to modify the code i’m not sure of what i’m doing. It must certainly be very easy and i just miss it.
I’ve been working on this code which i find more or less satisfying since it let me :

  • Move each motor independenty and simultaneously
  • Change speed and accélération on each mouvement for each motor
  • Tell motor who are done rotating to wait for other to do so, so they can begin a new movement
  • End the loop with a long delay

i also add a chronometer to it that tels me, the time the loop lasts :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 8, 9);

unsigned long MS;
unsigned long start;


void setup()
{
  Serial.begin (9600);                  // Serial.begin (115200);
  start=millis();
}

void loop() {
//chrono

{
  MS = millis()-start;

  Serial.print ((MS / 1000) / 60);      // minutes
  Serial.print ("' ");
  Serial.print ((MS / 1000) % 60);      // secondes
  Serial.print ("'' ");
  Serial.println (MS % 1000);           // millièmes
}  

//chorégraphy


stepper1.setMaxSpeed(300.0);
stepper1.setAcceleration(500.0);
stepper2.setMaxSpeed(300.0);
stepper2.setAcceleration(500.0);

stepper1.moveTo(1*turn);
stepper2.moveTo(2*turn);

while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))
{
  stepper1.run();
  stepper2.run();
 }
 
while (stepper2.distanceToGo() != 0)
{stepper1.stop();
stepper2.run();}
if (stepper2.distanceToGo() == 0)


//mouv2


stepper1.setMaxSpeed(600.0);
stepper1.setAcceleration(500.0);
stepper2.setMaxSpeed(600.0);
stepper2.setAcceleration(100.0);
stepper1.moveTo(3 *tours);
stepper2.moveTo(2000);

while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))
{
  stepper1.run();
  stepper2.run();
 }

//mouv3
  
stepper1.moveTo(4000);
stepper2.moveTo(5000);
while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))
{
  stepper1.run();
  stepper2.run();

 }
while (stepper2.distanceToGo() != 0)
{stepper1.stop();
stepper2.run();}
if (stepper2.distanceToGo() == 0)
{stepper1.stop();
stepper2.stop();}
delay (5000);
}

please feel free to comment :slight_smile:

noarno2:
I've been working on this code which i find more or less satisfying since it let me :

Good to hear you have a solution.

...R