Stepper Motor Array

colin_m

Member
Hi,

I am using TeensyStep4 with a Teensy 4.1 on PlatformIO. I have 10 stepper motors that I control and so I set up an array of stepper motor objects as shown below:

Code:
// Stepper objects
// Arguments are x & y where
// x is the pulse output pin
// y is the direction output pin
Stepper stepper1(STEPPER1_PULSE_PIN, STEPPER1_DIR_PIN); 
Stepper stepper2(STEPPER2_PULSE_PIN, STEPPER2_DIR_PIN); 
Stepper stepper3(STEPPER3_PULSE_PIN, STEPPER3_DIR_PIN); 
Stepper stepper4(STEPPER4_PULSE_PIN, STEPPER4_DIR_PIN); 
Stepper stepper5(STEPPER5_PULSE_PIN, STEPPER5_DIR_PIN); 
Stepper stepper6(STEPPER6_PULSE_PIN, STEPPER6_DIR_PIN); 
Stepper stepper7(STEPPER7_PULSE_PIN, STEPPER7_DIR_PIN); 
Stepper stepper8(STEPPER8_PULSE_PIN, STEPPER8_DIR_PIN); 
Stepper stepper9(STEPPER9_PULSE_PIN, STEPPER9_DIR_PIN);
Stepper stepper10(STEPPER10_PULSE_PIN, STEPPER10_DIR_PIN);
Stepper steppers[10] = {stepper1, stepper2, stepper3, stepper4, stepper5, stepper6, stepper7, stepper8, stepper9, stepper10};
StepperGroup g1{steppers[0], steppers[1], steppers[2], steppers[3], steppers[4], steppers[5], steppers[6], steppers[7], steppers[8], steppers[9]};

Moving the motors together in a group works beautifully. I have an array of target positions and I pass them to the the stepper objects as shown below:

Code:
// Set the new stepper targets
for (int i = 0; i <= 9; i++) {
  steppers[i].setTargetAbs(stepperTargets[i]);
}
// Move the stepper group
g1.move();

I'm having a problem though when I want to move only one of the motors. I have written the following subroutine to start testing a homing sequence:

Code:
// Home all the spreaders
void spreaderHoming() {
  Serial.println();
  Serial.println("Homing initiated...");
  Serial.println();

  // Set the speed for the stepper motors for the homing routine
  for (int i = 0; i <= 9; i++) {
    steppers[i].setMaxSpeed(HOME_SPEED);
    Serial.print("Spreader ");
    Serial.print(i + 1);
    Serial.print(" array initial position: ");
    Serial.println(steppers[i].getPosition());
  }

  steppers[4].moveAbsAsync(steppers[4].getPosition() - 500);
  do {
    inputsUpdate();
    if (inputArray[ADDR_PROXY_6]) {
      Serial.println("Proxy detected...");
    }
  } while (steppers[4].isMoving);
  delay(1000);
  Serial.println();
  for (int i = 0; i <= 9; i++) {
    Serial.print("Spreader ");
    Serial.print(i + 1);
    Serial.print(" array final position: ");
    Serial.println(steppers[i].getPosition());
  }
}

I would expect only the 5th stepper motor in the array to move, but all the stepper motors from the 5th to the tenth one move! This is the output that I get from the serial monitor:

Homing initiated...

Spreader 1 array initial position: 15915
Spreader 2 array initial position: 15915
Spreader 3 array initial position: 15915
Spreader 4 array initial position: 15915
Spreader 5 array initial position: 15915
Spreader 6 array initial position: 15915
Spreader 7 array initial position: 15915
Spreader 8 array initial position: 15915
Spreader 9 array initial position: 15915
Spreader 10 array initial position: 15915

Spreader 1 array final position: 15915
Spreader 2 array final position: 15915
Spreader 3 array final position: 15915
Spreader 4 array final position: 15915
Spreader 5 array final position: 15415
Spreader 6 array final position: 16415
Spreader 7 array final position: 16415
Spreader 8 array final position: 16415
Spreader 9 array final position: 16415
Spreader 10 array final position: 16415


As can be seen, the 5th stepper motor in the array does change its position correctly, but I don't know why the other stepper motors (greater than the 5th one) also change their positions (and in the opposite direction). If anyone could shed any light on this, I would appreciate it.

Thanks very much.
 
Use an array of pointers or references to the stepper objects, or else define the steppers as an array in the first place (there is some C++ syntax for initializing an array of objects with their constructor parameters that I can never remember!).

You create 10 stepper objects, then 10 more in an array that are copied from the first 10, AFAICT. I think you are relying on copy constructors being correctly setup for this to work, which might (or might not) explain the issue you are seeing.
 
I think what you propose is something I should try (although I'll have to try find some examples of pointer array declarations and how to work with them). What I found subsequently to my original post was that if I called getPosition from one of the original stepper motor objects (such as stepper5.getPosition() for example) after making my group move with the array, it reported its position as still being 0. So, the array of stepper objects is definitely separate to the original list of stepper object declarations, which was not the intention.
 
To intialize an array of steppers you can do:
Code:
Stepper steppers[] = {
    {STEPPER1_PULSE_PIN, STEPPER1_DIR_PIN},
    {STEPPER2_PULSE_PIN, STEPPER2_DIR_PIN},
    {STEPPER3_PULSE_PIN, STEPPER3_DIR_PIN},
    {STEPPER4_PULSE_PIN, STEPPER4_DIR_PIN},
    {STEPPER5_PULSE_PIN, STEPPER5_DIR_PIN},
    {STEPPER6_PULSE_PIN, STEPPER6_DIR_PIN},
    {STEPPER7_PULSE_PIN, STEPPER7_DIR_PIN},
    {STEPPER8_PULSE_PIN, STEPPER8_DIR_PIN},
    {STEPPER9_PULSE_PIN, STEPPER9_DIR_PIN},
    {STEPPER10_PULSE_PIN, STEPPER10_DIR_PIN}
    };

As MarkT pointed out, your original code makes copies of the steppers which will not work (I will disable the copy constructor / assignment operator in the next version to avoid this). Let me know if this fixes your intial problem. Might be related to something else..
 
Thanks luni. I will try this now. If I want to use the stepper objects in a StepperGroup for synchronised motion, would I still declare the object as follows:

StepperGroup g1{steppers[0], steppers[1], steppers[2], steppers[3], steppers[4], steppers[5], steppers[6], steppers[7], steppers[8], steppers[9]};
 
I implemented the stepper array as suggested and also the StepperGroup as per my previous post. The group moves all work perfectly as expected, but my homing routine behaves strangely. This is the code for my homing routine:

Code:
void spreaderHoming() {

  bool proxyDetected[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

  Serial.println("\nHoming initiated...");

  // Set the speed for the stepper motors for the homing routine
  for (int i = 0; i <= 9; i++) {
    steppers[i].setMaxSpeed(HOME_SPEED);
  }

  // Get the current input status of the proxies
  inputsUpdate();

  for (int i = 4; i >= 0; i--) {
    if (!inputArray[ADDR_PROXY_2 + i]) {
      steppers[i].moveAbsAsync(-MAX_STEPS);
      Serial.print("Spreader ");
      Serial.print(i + 1);
      Serial.println(" homing started.");
      do {
        inputsUpdate();
        // Watch for the stop proxy
        if (inputArray[ADDR_PROXY_2 + i] && !proxyDetected[i]) {
          Serial.print("Spreader ");
          Serial.print(i + 1);
          Serial.println(" proxy detected.");
          steppers[i].emergencyStop();
          // Set the spreader position to 0
          steppers[i].setPosition(0);
          // Homing completed
          proxyDetected[i] = true;
        }
      } while (not proxyDetected[i]);
    } else {
      Serial.print("Spreader ");
      Serial.print(i + 1);
      Serial.println(" already homed.");
    }
    delay(100);
    if (!inputArray[ADDR_PROXY_11 - i]) {
      steppers[9 - i].moveAbsAsync(-MAX_STEPS);
      Serial.print("Spreader ");
      Serial.print(10 - i);
      Serial.println(" homing started.");
      do {
        inputsUpdate();
        // Watch for the stop proxy
        if (inputArray[ADDR_PROXY_11 - i] && !proxyDetected[9 - i]) {
          Serial.print("Spreader ");
          Serial.print(10 - i);
          Serial.println(" proxy detected.");
          steppers[9 - i].emergencyStop();
          // Set the spreader position to 0
          steppers[9 - i].setPosition(0);
          // Homing completed
          proxyDetected[9 - i] = true;
        }
      } while (not proxyDetected[9 - i]);
    } else {
      Serial.print("Spreader ");
      Serial.print(10 - i);
      Serial.println(" already homed.");
    }
    delay(100);
  }
}

If I do a homing routine as soon as the Teensy boots up, then the stepper motors work as expected, homing one at a time from the inside of the array outwards. Perfect. However, if I try do a homing routine after I've done some group moves, then it's chaos. This is what I've observed:
- Stepper[4] starts homing as expected, but then at the same time Stepper[5] starts moving in the wrong direction,
- After Stepper[4] reaches it's proxy, Stepper[3], Stepper[4], Stepper[5] and Stepper[6] start moving,
- I kill the power
 
Back
Top