Can I loop through multiple stepper names using AccelStepper?

Hi All,

I'm looking to simplify my code while working with a large number (10+) of stepper motors (28BYJ48) and the AccelStepper library.

For every function I want to call (.move, .moveTo, .run, .disableOutputs, ...) it will end up in what seems like a unnecessary amount of copy/paste coding:

The "basic" method (multiplied times the numbers of steppers):

  stepper1.move(100); 
  stepper2.move(100); 
  stepper3.move(100);   
  stepper4.move(100);  
 ...

or

  stepper1.run();
  stepper2.run();
  stepper3.run();
  stepper4.run();
...

I'm admittedly rusty when it comes to C++, but I was hoping I could do something like below.

Unfortunately, I get an Error: 'stepper' was not declared in this scope. Either my syntax/method is just wrong, or for whatever reason I can't take this approach when working with the AccelStepper library. I'm guessing it is just my method...

All my attempts to Google this problem away have failed...there is probably some terminology for this type of nested(?) variables that I'm just missing... appreciate any guidance you can provide!

 while(x=1, x<4, x++)
 {
  stepper(x).move(100); 
 }

or

while(x=1, x<4, x++)
 {
  stepper(x).run(); 
 }

You can't do that, but you can do something similar (and better):
Put the Stepper objects in an array:

Stepper steppers[] = {stepper1, stepper2, stepper3, stepper4};

Then you can do things like this:

for(x=0, x<4, x++)
{
  steppers[x].move(100);
}

Note that it's a for loop you want with this syntax, not a while loop.

pert:
You can't do that, but you can do something similar (and better):
Put the Stepper objects in an array:

Stepper steppers[] = {stepper1, stepper2, stepper3, stepper4};

Then you can do things like this:

for(x=0, x<4, x++)

{
  steppers[x].move(100);
}



Note that it's a for loop you want with this syntax, not a while loop.

Thanks Pert,

I think I'm getting close to making this work. It seems like the AccelStepper functions are working with the array format, but when I go to run the motors the system goes a bit haywire. The driver board LEDs light up, and they are pulling current (more than normal), but the motors do not step. So it seems like something is not going back to the AccelStepper library correctly?

Below showing how I defined the array in the initialization section:

// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48
AccelStepper stepper1(HALFSTEP, motor1_Pin1, motor1_Pin3, motor1_Pin2, motor1_Pin4);
AccelStepper stepper2(HALFSTEP, motor2_Pin1, motor2_Pin3, motor2_Pin2, motor2_Pin4);
AccelStepper stepper3(HALFSTEP, motor3_Pin1, motor3_Pin3, motor3_Pin2, motor3_Pin4);
AccelStepper stepper4(HALFSTEP, motor4_Pin1, motor4_Pin3, motor4_Pin2, motor4_Pin4);
AccelStepper stepper5(HALFSTEP, motor5_Pin1, motor5_Pin3, motor5_Pin2, motor5_Pin4);
AccelStepper stepper6(HALFSTEP, motor6_Pin1, motor6_Pin3, motor6_Pin2, motor6_Pin4);
AccelStepper stepper7(HALFSTEP, motor7_Pin1, motor7_Pin3, motor7_Pin2, motor7_Pin4);
AccelStepper stepper8(HALFSTEP, motor8_Pin1, motor8_Pin3, motor8_Pin2, motor8_Pin4);
AccelStepper stepper9(HALFSTEP, motor9_Pin1, motor9_Pin3, motor9_Pin2, motor9_Pin4);
AccelStepper stepper10(HALFSTEP, motor10_Pin1, motor10_Pin3, motor10_Pin2, motor10_Pin4);
AccelStepper stepper11(HALFSTEP, motor11_Pin1, motor11_Pin3, motor11_Pin2, motor11_Pin4);
AccelStepper stepper12(HALFSTEP, motor12_Pin1, motor12_Pin3, motor12_Pin2, motor12_Pin4);

AccelStepper stepArray[]={stepper1,stepper2,stepper3,stepper4,stepper5,
stepper6,stepper7,stepper8,stepper9,stepper10,stepper11,stepper12};

Here is where I call the move and run functions. I'm choosing to only run the first 4 motors in this loop.

  for (x = 0; x < 12; x++)
  {
    stepArray[x].setCurrentPosition(0);
    stepArray[x].move(100);
  }

  while (abs(stepArray[0].distanceToGo()) > 0)
  {
    stepArray[0].run();
    stepArray[1].run();
    stepArray[2].run();
    stepArray[3].run();
  }

Using the below, w/o arrays, the motors work as expected.

 stepper1.move(100);  // 1 revolution
 stepper2.move(100);  // 1 revolution
 stepper3.move(100);  // 1 revolution
 stepper4.move(100);  // 1 revolution
  while (abs(stepper1.distanceToGo()) > 0)
  {
    stepper1.run();
    stepper2.run();
    stepper3.run();
    stepper4.run();
  }

The two codes are not equivalent. This would be the equivalent to the second using the array:

  for (x = 0; x < 4; x++)
  {
    stepArray[x].move(100);
  }

  while (abs(stepArray[0].distanceToGo()) > 0)
  {
    stepArray[0].run();
    stepArray[1].run();
    stepArray[2].run();
    stepArray[3].run();
  }

pert:
Put the Stepper objects in an array:

Stepper steppers[] = {stepper1, stepper2, stepper3, stepper4};

This is not actually "putting the Stepper objects in an array" It creating an array of 4 NEW stepper objects that are copy-constructed from the original 'stepper1' through 'stepper4'.

So, now you actually have 8 Stepper objects, 4 of which are never used by the program. Since they're not used, they very well could be optimized out by the compiler. But, technically, you have not put the original 4 into an array.

Two alternatives that don't create 4 new objects are:

An array of pointers:

AccelStepper stepper1(HALFSTEP, motor1_Pin1, motor1_Pin3, motor1_Pin2, motor1_Pin4);
AccelStepper stepper2(HALFSTEP, motor2_Pin1, motor2_Pin3, motor2_Pin2, motor2_Pin4);
AccelStepper stepper3(HALFSTEP, motor3_Pin1, motor3_Pin3, motor3_Pin2, motor3_Pin4);
AccelStepper stepper4(HALFSTEP, motor4_Pin1, motor4_Pin3, motor4_Pin2, motor4_Pin4);

AccelStepper *stepperPtrArray[] = {&stepper1, &stepper2, &stepper3, &stepper4};

Create the array directly:

AccelStepper stepperArray[] = {
  {HALFSTEP, motor1_Pin1, motor1_Pin3, motor1_Pin2, motor1_Pin4},
  {HALFSTEP, motor2_Pin1, motor2_Pin3, motor2_Pin2, motor2_Pin4},
  {HALFSTEP, motor3_Pin1, motor3_Pin3, motor3_Pin2, motor3_Pin4},
  {HALFSTEP, motor4_Pin1, motor4_Pin3, motor4_Pin2, motor4_Pin4}
};
1 Like

Thanks for the correction gfvalvo! I like the second option.

Yes, thanks to both of you for the advice!

I went down the pointer array path, and was able to find some other threads that cover this same solution for working with AccelStepper. I've implemented and it seems like it will do exactly what I need.

Linking it here for future readers: [Solved]Accelstepper library and Multiple stepper motors - Motors, Mechanics, Power and CNC - Arduino Forum

gfvalvo:
This is not actually "putting the Stepper objects in an array" It creating an array of 4 NEW stepper objects that are copy-constructed from the original 'stepper1' through 'stepper4'.

So, now you actually have 8 Stepper objects, 4 of which are never used by the program. Since they're not used, they very well could be optimized out by the compiler. But, technically, you have not put the original 4 into an array.
...

This subtlety is a bit less subtle after I looked into "copy construct object c++". It will work, but as you say there will be eight objects, it behooves one to refer to four of them in just one way, that is there are not two names (one direct and one in the array) for one object.

Worse is the fact that this will be a default copy. Unless the object provides its own copy function, all you get is a shallow copy. Which would mightn't work.

Your pointer array soln. makes sense and just works.

Learn something every day.

a7