6 AccelSteppers as an array of struct/array of class/array of object

This simulation uses an array of AccelStepper classes to drive six steppers on a simulated RAMPS/RUMBA/Mega shield.

While the steppers bounce back and forth between extremes, the inputs are monitored for pushbutton/limitSwitch activation (which sets the chosen stepper target to the value of the Position slide potentiometer) and also monitors for changes in the Speed and Acceleration slide, which affects all of the steppers immediately.

image
https://wokwi.com/projects/411859783629453313

/*  AccelStepper6AxisRampsMega.ino

This simulation demonstrates bouncing 6 stepper motors between different
limits while simultaneously reading potentiomters to adust speed 
acceleration, and target positions during moves.

It also demonstrates use of an array of classes in order to manage them
together as a set.

https://wokwi.com/projects/411859783629453313

  // built from :
  // https://wokwi.com/projects/390741120778917889

*/
// For RAMPS 1.4, Copied from https://wokwi.com/projects/390741120778917889
#define X_DIR_PIN          55
#define X_STEP_PIN         54
#define X_ENABLE_PIN       38

#define Y_DIR_PIN          61
#define Y_STEP_PIN         60
#define Y_ENABLE_PIN       56

#define Z_DIR_PIN          48
#define Z_STEP_PIN         46
#define Z_ENABLE_PIN       62

#define A_DIR_PIN          28
#define A_STEP_PIN         26
#define A_ENABLE_PIN       24

#define B_DIR_PIN          34
#define B_STEP_PIN         36
#define B_ENABLE_PIN       30
// 
#define C_DIR_PIN          32
#define C_STEP_PIN         47
#define C_ENABLE_PIN       45

#import <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/
// and https://github.com/waspinator/AccelStepper

// An array of classes, 
AccelStepper steppers[] = {
  {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN},
  {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN},
  {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN},
  {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN},
  {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN},
  {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN},
};
// parallel array for enable pins
const int StepperEnablePins[] = {X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, A_ENABLE_PIN, B_ENABLE_PIN, C_ENABLE_PIN };
// parallel array for limit buttons
const int ButtonPins[] = {3, 14, 18, 27, 29, 25};

const int NUM_STEPPERS = sizeof(steppers) / sizeof(steppers[0]);

void usage() {
  Serial.print(__FILE__ " on " __DATE__);
  Serial.print(F(R"(AccelStepper6AxisRAMPSMega.ino )"));
}
const int PositionPin = A13, SpeedPin = A14, AccelPin = A15;
uint16_t position, speed, acceleration, lastPosition, lastSpeed, lastAccel; // pot-read

void readAllInputs() {
  uint32_t now = millis();
  const auto interval = 200;
  static auto last = - interval;
  if (now - last >= interval) {
    now += interval;
    speed = map(analogRead(SpeedPin), 0, 1023, 0, 2000);
    acceleration = map(analogRead(AccelPin), 0, 1023, 0, 2000);
    position = map(analogRead(PositionPin), 0, 1023, 0, 2000);
    int ii = 0;
    for (auto pin : ButtonPins) {
      if (digitalRead(pin) == LOW) {
        steppers[ii].moveTo(position);
      }
      ++ii;
    }
  }
}

void process() {
  if (acceleration != lastAccel || speed != lastSpeed) {
    for ( auto & stepper : steppers) {
      stepper.setAcceleration(acceleration);
      stepper.setMaxSpeed(speed);
      lastSpeed = speed;
      lastAccel = acceleration;
    }
  }
}

void enableAllSteppers() {
  int ii = 0;
  for (auto &stepper : steppers) {
    stepper.setEnablePin(StepperEnablePins[ii]);
    stepper.setPinsInverted(false, false, true);
    stepper.enableOutputs();
    stepper.setMaxSpeed(1000);
    stepper.setAcceleration(100);
    stepper.moveTo(random(2000));
    pinMode(ButtonPins[ii], INPUT_PULLUP);
    ++ii;
  }
}

void runAllSteppers() {
  int ii = 0 ;
  for (auto &stepper : steppers) {
    if (stepper.distanceToGo() == 0) {
      stepper.moveTo(-stepper.currentPosition());
      Serial.print(ii);
      Serial.print("@");
      Serial.print(stepper.currentPosition());
      Serial.print(" ");
    }
    ++ii;
    stepper.run();
  }
}

// Arduino required #####################################

void setup() {
  srandom( 20241015 + analogRead(SpeedPin) + analogRead(AccelPin));
  Serial.begin(115200);
  enableAllSteppers();
  usage();
}

void loop() {
  readAllInputs();
  process();
  runAllSteppers();
}

This applies some of the techniques in:

And from:

However, this example creates an array for AccelStepper objects and assigns it with brace-delimited array of constructor parameters.

Array of struct containing classes

This example defines an array of struct, with one of the struct members being an accelStepper class. This is it's data definition:

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN}, X_ENABLE_PIN,3},
  {"Y", {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN}, Y_ENABLE_PIN,14},
  {"Z", {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN}, Z_ENABLE_PIN,18},
  {"A", {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN}, A_ENABLE_PIN,27},
  {"B", {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN}, B_ENABLE_PIN,29},
  {"C", {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN}, C_ENABLE_PIN,25},
};

(It is in the Wokwi simulation example above as the V4_array_structs.ino.txt tab. See the notes on renaming tabs)

/*  AccelStepper6AxisRampsMega.ino

This simulation demonstrates bouncing 6 stepper motors between different
limits while simultaneously reading potentiomters to adust speed 
acceleration, and target positions during moves.

It also demonstrates use of an array of structs containing classes in order to manage them
together as a set.

https://wokwi.com/projects/411859783629453313

  // built from :
  // https://wokwi.com/projects/390741120778917889

*/
// For RAMPS 1.4, Copied from https://wokwi.com/projects/390741120778917889
#define X_DIR_PIN          55
#define X_STEP_PIN         54
#define X_ENABLE_PIN       38

#define Y_DIR_PIN          61
#define Y_STEP_PIN         60
#define Y_ENABLE_PIN       56

#define Z_DIR_PIN          48
#define Z_STEP_PIN         46
#define Z_ENABLE_PIN       62

#define A_DIR_PIN          28
#define A_STEP_PIN         26
#define A_ENABLE_PIN       24

#define B_DIR_PIN          34
#define B_STEP_PIN         36
#define B_ENABLE_PIN       30
// 
#define C_DIR_PIN          32
#define C_STEP_PIN         47
#define C_ENABLE_PIN       45

#import <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/
// and https://github.com/waspinator/AccelStepper

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN}, X_ENABLE_PIN,3},
  {"Y", {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN}, Y_ENABLE_PIN,14},
  {"Z", {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN}, Z_ENABLE_PIN,18},
  {"A", {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN}, A_ENABLE_PIN,27},
  {"B", {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN}, B_ENABLE_PIN,29},
  {"C", {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN}, C_ENABLE_PIN,25},
};

const int NUM_STEPPERS = sizeof(stepperAssemblies) / sizeof(stepperAssemblies[0]);

void usage() {
  Serial.print(__FILE__ " on " __DATE__);
  Serial.print(F(R"(AccelStepper6AxisRAMPSMega.ino )"));
}
const int PositionPin = A13, SpeedPin = A14, AccelPin = A15;
uint16_t position, speed, acceleration, lastPosition, lastSpeed, lastAccel; // pot-read

void readAllInputs() {
  uint32_t now = millis();
  const auto interval = 200;
  static auto last = - interval;
  if (now - last >= interval) {
    now += interval;
    speed = map(analogRead(SpeedPin), 0, 1023, 0, 2000);
    acceleration = map(analogRead(AccelPin), 0, 1023, 0, 2000);
    position = map(analogRead(PositionPin), 0, 1023, 0, 2000);
    // // Parallel array form
    // int ii = 0;
    // for (auto pin : ButtonPins) {
    //   if (digitalRead(pin) == LOW) {
    //     steppers[ii].moveTo(position);
    //   }
    //   ++ii;
    // }
    // array of struct form:
    for (auto &obj : stepperAssemblies) {
      if (digitalRead(obj.button) == LOW) {
        obj.stepper.moveTo(position);
      }
    }
  }
}

void process() {
  if (acceleration != lastAccel || speed != lastSpeed) {
    for ( auto & assy : stepperAssemblies) {
      assy.stepper.setAcceleration(acceleration);
      assy.stepper.setMaxSpeed(speed);
      lastSpeed = speed;
      lastAccel = acceleration;
    }
    Serial.print("Speed:");
    Serial.print(speed);
    Serial.print(" Acceleration:");
    Serial.println(acceleration);
  }
}

void enableAllSteppersParallel() {
  int ii = 0;
  for (auto &assy : stepperAssemblies) {
    assy.stepper.setEnablePin(assy.enablePin);
    assy.stepper.setPinsInverted(false, false, true);
    assy.stepper.enableOutputs();
    assy.stepper.setMaxSpeed(1000);
    assy.stepper.setAcceleration(100);
    assy.stepper.moveTo(random(2000));
    pinMode(assy.button, INPUT_PULLUP);
    ++ii;
  }
}

void enableAllSteppers() {
  int ii = 0;
  for (auto &obj : stepperAssemblies) {
    obj.stepper.setEnablePin(obj.enablePin);
    obj.stepper.setPinsInverted(false, false, true);
    obj.stepper.enableOutputs();
    obj.stepper.setMaxSpeed(1000);
    obj.stepper.setAcceleration(100);
    obj.stepper.moveTo(random(2000));
    pinMode(obj.button, INPUT_PULLUP);
    Serial.print("Initialized ");
    Serial.print(obj.name);
    Serial.print(" Stepper, enabe Button Pin:");
    Serial.println(obj.button);
    ++ii;
  }
}


void runAllSteppers() {
  int ii = 0 ;
  for (auto &obj : stepperAssemblies) {
    if (obj.stepper.distanceToGo() == 0) {
      obj.stepper.moveTo(-obj.stepper.currentPosition());
      Serial.print(ii);
      Serial.print("@");
      Serial.print(obj.stepper.currentPosition());
      Serial.print(" ");
    }
    ++ii;
    obj.stepper.run();
  }
}

// Arduino required #####################################

void setup() {
  srandom( 20241015 + analogRead(SpeedPin) + analogRead(AccelPin));
  Serial.begin(115200);
  //enableAllSteppers();
  enableAllSteppers();
  usage();
}

void loop() {
  readAllInputs();
  process();
  runAllSteppers();
}
1 Like

Ooh, you can avoid the parallel arrays of enable pins and button pins and assemble an array of structures by using references to the steppers[..] array of classes:

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper &stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", steppers[0], X_ENABLE_PIN,3},
  {"Y", steppers[1], Y_ENABLE_PIN,14},
  {"Z", steppers[2], Z_ENABLE_PIN,18},
  {"A", steppers[3], A_ENABLE_PIN,27},
  {"B", steppers[4], B_ENABLE_PIN,29},
  {"C", steppers[5], C_ENABLE_PIN,25},
};

I'm sure you could go one step further and put the AccelStepper initializer parameters into that declaration and avoid this parallel array of classes of AccelSteppers:

// An array of classes, 
AccelStepper steppers[] = {
  {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN},
  {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN},
  {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN},
  {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN},
  {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN},
  {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN},
};

The whole code will drop into the Wokwi linked above:

whole code
/*  AccelStepper6AxisRampsMega.ino

This simulation demonstrates bouncing 6 stepper motors between different
limits while simultaneously reading potentiomters to adust speed 
acceleration, and target positions during moves.

It also demonstrates use of an array of classes in order to manage them
together as a set.

https://wokwi.com/projects/411859783629453313

  // built from :
  // https://wokwi.com/projects/390741120778917889

*/
// For RAMPS 1.4, Copied from https://wokwi.com/projects/390741120778917889
#define X_DIR_PIN          55
#define X_STEP_PIN         54
#define X_ENABLE_PIN       38

#define Y_DIR_PIN          61
#define Y_STEP_PIN         60
#define Y_ENABLE_PIN       56

#define Z_DIR_PIN          48
#define Z_STEP_PIN         46
#define Z_ENABLE_PIN       62

#define A_DIR_PIN          28
#define A_STEP_PIN         26
#define A_ENABLE_PIN       24

#define B_DIR_PIN          34
#define B_STEP_PIN         36
#define B_ENABLE_PIN       30
// 
#define C_DIR_PIN          32
#define C_STEP_PIN         47
#define C_ENABLE_PIN       45

#import <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/
// and https://github.com/waspinator/AccelStepper

// An array of classes, 
AccelStepper steppers[] = {
  {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN},
  {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN},
  {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN},
  {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN},
  {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN},
  {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN},
};
// parallel array for enable pins
const int StepperEnablePins[] = {X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, A_ENABLE_PIN, B_ENABLE_PIN, C_ENABLE_PIN };
// parallel array for limit buttons
const int ButtonPins[] = {3, 14, 18, 27, 29, 25};

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper &stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", steppers[0], X_ENABLE_PIN,3},
  {"Y", steppers[1], Y_ENABLE_PIN,14},
  {"Z", steppers[2], Z_ENABLE_PIN,18},
  {"A", steppers[3], A_ENABLE_PIN,27},
  {"B", steppers[4], B_ENABLE_PIN,29},
  {"C", steppers[5], C_ENABLE_PIN,25},
};

const int NUM_STEPPERS = sizeof(steppers) / sizeof(steppers[0]);

void usage() {
  Serial.print(__FILE__ " on " __DATE__);
  Serial.print(F(R"(AccelStepper6AxisRAMPSMega.ino )"));
}
const int PositionPin = A13, SpeedPin = A14, AccelPin = A15;
uint16_t position, speed, acceleration, lastPosition, lastSpeed, lastAccel; // pot-read

void readAllInputs() {
  uint32_t now = millis();
  const auto interval = 200;
  static auto last = - interval;
  if (now - last >= interval) {
    now += interval;
    speed = map(analogRead(SpeedPin), 0, 1023, 0, 2000);
    acceleration = map(analogRead(AccelPin), 0, 1023, 0, 2000);
    position = map(analogRead(PositionPin), 0, 1023, 0, 2000);
    // // Parallel array form
    // int ii = 0;
    // for (auto pin : ButtonPins) {
    //   if (digitalRead(pin) == LOW) {
    //     steppers[ii].moveTo(position);
    //   }
    //   ++ii;
    // }
    // array of struct form:
    for (auto &obj : stepperAssemblies) {
      if (digitalRead(obj.button) == LOW) {
        obj.stepper.moveTo(position);
      }
    }
  }
}

void process() {
  if (acceleration != lastAccel || speed != lastSpeed) {
    for ( auto & stepper : steppers) {
      stepper.setAcceleration(acceleration);
      stepper.setMaxSpeed(speed);
      lastSpeed = speed;
      lastAccel = acceleration;
    }
    Serial.print("Speed:");
    Serial.print(speed);
    Serial.print(" Acceleration:");
    Serial.println(acceleration);
  }
}

void enableAllSteppersParallel() {
  int ii = 0;
  for (auto &stepper : steppers) {
    stepper.setEnablePin(StepperEnablePins[ii]);
    stepper.setPinsInverted(false, false, true);
    stepper.enableOutputs();
    stepper.setMaxSpeed(1000);
    stepper.setAcceleration(100);
    stepper.moveTo(random(2000));
    pinMode(ButtonPins[ii], INPUT_PULLUP);
    ++ii;
  }
}

void enableAllSteppers() {
  int ii = 0;
  for (auto &obj : stepperAssemblies) {
    obj.stepper.setEnablePin(obj.enablePin);
    obj.stepper.setPinsInverted(false, false, true);
    obj.stepper.enableOutputs();
    obj.stepper.setMaxSpeed(1000);
    obj.stepper.setAcceleration(100);
    obj.stepper.moveTo(random(2000));
    pinMode(obj.button, INPUT_PULLUP);
    Serial.print("Initialized ");
    Serial.print(obj.name);
    Serial.print(" Stepper, enabe Button Pin:");
    Serial.println(obj.button);
    ++ii;
  }
}


void runAllSteppers() {
  int ii = 0 ;
  for (auto &stepper : steppers) {
    if (stepper.distanceToGo() == 0) {
      stepper.moveTo(-stepper.currentPosition());
      Serial.print(ii);
      Serial.print("@");
      Serial.print(stepper.currentPosition());
      Serial.print(" ");
    }
    ++ii;
    stepper.run();
  }
}

// Arduino required #####################################

void setup() {
  srandom( 20241015 + analogRead(SpeedPin) + analogRead(AccelPin));
  Serial.begin(115200);
  //enableAllSteppers();
  enableAllSteppers();
  usage();
}

void loop() {
  readAllInputs();
  process();
  runAllSteppers();
}

As an array of struct containing an AccelStepper class as a member.

This example is built around a declaration of an array of structs, where one of the elements is an AccelStepper:

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN}, X_ENABLE_PIN,3},
  {"Y", {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN}, Y_ENABLE_PIN,14},
  {"Z", {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN}, Z_ENABLE_PIN,18},
  {"A", {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN}, A_ENABLE_PIN,27},
  {"B", {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN}, B_ENABLE_PIN,29},
  {"C", {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN}, C_ENABLE_PIN,25},
};

(...where the pins are set per some RAMPS 3d-printing control board pin assignments)

The Simulation:

The full code:

/*  AccelStepper6AxisArrayStruct.ino

See https://forum.arduino.cc/t/6-accelsteppers-as-an-array-of-struct-array-of-class-array-of-object/1311789/ and 
https://wokwi.com/projects/411859783629453313 for some some parent sketches

This simulation demonstrates bouncing 6 stepper motors between different
limits while simultaneously reading potentiomters to adust speed 
acceleration, and target positions during moves.

It also demonstrates use of an array of classes in order to manage them
together as a set.

https://wokwi.com/projects/411859783629453313

  // built from :
  // https://wokwi.com/projects/390741120778917889

*/
// For RAMPS 1.4, Copied from https://wokwi.com/projects/390741120778917889
// RAMPS pins from https://reprap.org/wiki/RAMPS_1.4#Pins & https://forum.arduino.cc/t/arduino-mega-use-analog-pins-as-digital/13844/6?u=davex
// with auxiliary pins for axis C controls and A,B,C min pins

#define X_DIR_PIN          55
#define X_STEP_PIN         54
#define X_ENABLE_PIN       38
#define X_MIN_PIN           3

#define Y_DIR_PIN          61
#define Y_STEP_PIN         60
#define Y_ENABLE_PIN       56
#define Y_MIN_PIN          14

#define Z_DIR_PIN          48
#define Z_STEP_PIN         46
#define Z_ENABLE_PIN       62
#define Z_MIN_PIN          18

#define A_DIR_PIN          28
#define A_STEP_PIN         26
#define A_ENABLE_PIN       24
#define A_MIN_PIN 27

#define B_DIR_PIN          34
#define B_STEP_PIN         36
#define B_ENABLE_PIN       30
#define B_MIN_PIN 29
// 
#define C_DIR_PIN          32
#define C_STEP_PIN         47
#define C_ENABLE_PIN       45
#define C_MIN_PIN 25

#import <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/
// and https://github.com/waspinator/AccelStepper

// Assemble an array of structures
struct MyStruct {
  const char *name;
  const AccelStepper stepper;
  int enablePin;
  int button;
} stepperAssemblies[] = {
  {"X", {AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN}, X_ENABLE_PIN,X_MIN_PIN},
  {"Y", {AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN}, Y_ENABLE_PIN,Y_MIN_PIN},
  {"Z", {AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN}, Z_ENABLE_PIN,Z_MIN_PIN},
  {"A", {AccelStepper::DRIVER, A_STEP_PIN, A_DIR_PIN}, A_ENABLE_PIN,A_MIN_PIN},
  {"B", {AccelStepper::DRIVER, B_STEP_PIN, B_DIR_PIN}, B_ENABLE_PIN,B_MIN_PIN},
  {"C", {AccelStepper::DRIVER, C_STEP_PIN, C_DIR_PIN}, C_ENABLE_PIN,C_MIN_PIN},
};

const int NUM_STEPPERS = sizeof(stepperAssemblies) / sizeof(stepperAssemblies[0]);

void usage() {
  Serial.print(__FILE__ " on " __DATE__);
Serial.println(F(R"(AccelStepper6AxisRAMPSMega.ino V4_array_structs.ino
https://wokwi.com/projects/411859783629453313
Speed, acceleration change with potentiometers.
Bounce position changes with button press. )"));
}

const int PositionPin = A13, SpeedPin = A14, AccelPin = A15;
uint16_t position, speed, acceleration, lastPosition, lastSpeed, lastAccel; // pot-read

void readAllInputs() {
  uint32_t now = millis();
  const auto interval = 200;
  static auto last = - interval;
  if (now - last >= interval) {
    now += interval;
    speed = map(analogRead(SpeedPin), 0, 1023, 0, 2000);
    acceleration = map(analogRead(AccelPin), 0, 1023, 0, 2000);
    position = map(analogRead(PositionPin), 0, 1023, 0, 2000);

    for (auto &obj : stepperAssemblies) {
      if (digitalRead(obj.button) == LOW && obj.stepper.targetPosition() != position) {
        Serial.print("Retargeting stepper ");
        Serial.print(obj.name);
        Serial.print(" to ");
        Serial.println(position);
        obj.stepper.moveTo(position);
      }
    }
  }
}

void process() {
  if (acceleration != lastAccel || speed != lastSpeed) {
    for ( auto & assy : stepperAssemblies) {
      assy.stepper.setAcceleration(acceleration);
      assy.stepper.setMaxSpeed(speed);
      lastSpeed = speed;
      lastAccel = acceleration;
    }
    Serial.print("Speed:");
    Serial.print(speed);
    Serial.print(" Acceleration:");
    Serial.println(acceleration);
  }
}

void enableAllSteppersParallel() {
  for (auto &assy : stepperAssemblies) {
    assy.stepper.setEnablePin(assy.enablePin);
    assy.stepper.setPinsInverted(false, false, true);
    assy.stepper.enableOutputs();
    assy.stepper.setMaxSpeed(1000);
    assy.stepper.setAcceleration(100);
    assy.stepper.moveTo(random(2000));
    pinMode(assy.button, INPUT_PULLUP);
  }
}

void enableAllSteppers() {
  for (auto &obj : stepperAssemblies) {
    obj.stepper.setEnablePin(obj.enablePin);
    obj.stepper.setPinsInverted(false, false, true);
    obj.stepper.enableOutputs();
    obj.stepper.setMaxSpeed(1000);
    obj.stepper.setAcceleration(100);
    obj.stepper.moveTo(random(2000));
    pinMode(obj.button, INPUT_PULLUP);
    Serial.print("Initialized ");
    Serial.print(obj.name);
    Serial.print(" Stepper, enable Button Pin:");
    Serial.println(obj.button);
  }
}

void runAllSteppers() {
  for (auto &obj : stepperAssemblies) {
    if (obj.stepper.distanceToGo() == 0) {
      obj.stepper.moveTo(-obj.stepper.currentPosition());
      Serial.print(obj.name);
      Serial.print("@");
      Serial.print(obj.stepper.currentPosition());
      Serial.print(" ");
    }
    obj.stepper.run();
  }
}

// Arduino required #####################################

void setup() {
  srandom( 20241015 + analogRead(SpeedPin) + analogRead(AccelPin));
  Serial.begin(115200);
  //enableAllSteppers();
  enableAllSteppers();
  usage();
}

void loop() {
  readAllInputs();
  process();
  runAllSteppers();
}

I think that "array of AccelStepper objects" sounds better than "array of classes"

1 Like

How about this:

Array of struct/array of class for 6 AccelSteppers

or

Array of struct/array of class/array of object for 6 AccelSteppers

or

6 AccelSteppers as an array of struct/array of class/array of object

I have found it hard to search/google for more than basic examples of array of ??? declarations. I've seen them in use as finished products, but their creation looks like deep magic and easy to do wrong.

This may be true, but it is pretty basic:

https://en.cppreference.com/w/c/language/array_initialization

Here's an array of stepper objects tracking the array of FastLED pixels:

And here's an array of buttons managed by an array of ezButtons:

It is a shame that the Arduino built-in examples are mostly 1-device examples and do not show a path forward into multiples of the devices in an array or an array of structs.

Arrays (and arrays of structs) scale well, and there should be more examples of using arrays of things.

Arduino has this:

https://docs.arduino.cc/language-reference/en/variables/data-types/array/

and the How to use Arrays tutorial: