Problem using multiple stepper.h library

#include <AccelStepper.h>
#include <MultiStepper.h>

#define stepPinX 7
#define dirPinX 8
#define stepPinY 9
#define dirPinY 10

AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);
AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);
MultiStepper steppers;

void setup() {
    stepperX.setMaxSpeed(1000); // Set max speed for X
    stepperX.setAcceleration(500); // Set acceleration for X
    stepperY.setMaxSpeed(1000); // Set max speed for Y
    stepperY.setAcceleration(500); // Set acceleration for Y

    steppers.addStepper(stepperX);
    steppers.addStepper(stepperY);
}

void loop() {
    moveTo(400, 602); // Move to (500, 802)
    delay(2000); // Wait before moving to another position
    moveTo(0, 0); // Move back to (0, 0)
    delay(2000);
}

void moveTo(int targetX, int targetY) {
    long positions[2];
    positions[0] = targetX;
    positions[1] = targetY;

    steppers.moveTo(positions);

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0) {
        steppers.runSpeedToPosition();
        delay(1); // Add a small delay to ensure synchronization
    }
}

Hi everybody,
i have been using the above code to run 2 stepper motors using tb6600 driver, but the problem is the motors keep skipping some steps in every cycles
i request you to go through it and help me through it!
Regards.

Strart testing by using a much lower acceleration.

AccelStepper's MultiStepper doesn't do acceleration:

Caution: only constant speed stepper motion is supported: acceleration and deceleration is not supported All the steppers managed by MultiStepper will step at a constant speed to their target (albeit perhaps different speeds for each stepper).

1 Like

This is a good project to compare with a simulation.
Wokwi has unlimited power, and stepper motors never skip.

Your sketch in Wokwi:

1 Like

I have already done that but no difference at all!

Yes you are correct I removed it but the problem is about the motors skipping steps

Yes I just checked it in the simulation the motors are not skipping any steps but in my setup both the motors are skipping steps in every cycle

It's quite common that in simulation things work but not in the realiy.

What is the setting for current and what's the rating of the power supply, in Volt and in Amps?

1 Like

The power supply I use is 14volts and 20 amps

Stepper current setting was also requested...

I use 1.5 amps, when i individually tested the stepper motor using only stepper.h library the steps were not lost

arham1008, we use the common reply button at the bottom. Replying to posts does not work well on this forum.
You can select text with mouse and use the "quote". Just try it. Select text that someone wrote.
For example:


I think that DaveX in post #3 pinpointed the problem.
Can you use AccelStepper on its own, without the MultiStepper ?

Motors skipping steps is a symptom of the torque not matching the requirements. If the load is too high, the speed is too high, the power too low, or the motor is too weak for the purpose, the steps won't happen as expected.

If you unload the motors by removing the motors from whatever they are driving, does it work better? Does it work better at slower speeds?

When i remove the load the motors start stuttering sometimes, but when i use other libraries like stepper.h the motor rotates perfectly.

But I need coordinated movements between the motors so i need to use Multistepper

If the MultiStepper is not working, then you can not use it.
I have changed the sketch in Wokwi to show the difference between AccelStepper and MultStepper: https://wokwi.com/projects/403760098803505153
Look at the acceleration and deceleration of the blue arrow. That is okay, the MultiStepper is not okay.

But then i want coordinated movements between the motors how will i achieve that without multistepper

I'm not sure if my math is correct, but what about this:

Stepper motor 1: steps = 200, acceleration = 200, max speed = 2000.
Stepper motor 2: steps = 100, acceleration = 100, max speed = 1000.

Would they reach the endpoint at the same time ?
I made a first attempt in the same project: https://wokwi.com/projects/403760098803505153

The sketch:

// 18 July 2024
// A test with the AccelStepper by Koepel
//
// Forum: https://forum.arduino.cc/t/problem-using-multiple-stepper-h-library/1282890
// This Wokwi project: https://wokwi.com/projects/403760098803505153
// Update 19 July 2024: 
//   Showing differerence between AccelStepper and MultiStepper.
// New update 19 July 2024:
//   A calculated coordination of two AccelStepper.
//   I don't know if the math is correct.
//

#include <AccelStepper.h>
#include <MultiStepper.h>

#define stepPinX 7
#define dirPinX  8
#define stepPinY 9
#define dirPinY  10
#define stepPinZ 11
#define dirPinZ  12
const int stepPinCo1 = A3;
const int dirPinCo1  = A2;
const int stepPinCo2 = A1;
const int dirPinCo2  = A0;

AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);
AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);
AccelStepper stepperZ(AccelStepper::DRIVER, stepPinZ, dirPinZ);
AccelStepper Co1(AccelStepper::DRIVER, stepPinCo1, dirPinCo1);
AccelStepper Co2(AccelStepper::DRIVER, stepPinCo2, dirPinCo2);
MultiStepper steppers;

// Variables for millis timer
unsigned long previousMillis;
const unsigned long interval = 8000UL;

// Absolute positions of the coordinated stepper motors.
long position1 = 0;
long position2 = 0;

// The speed and acceleration that the fysical hardware can handle.
float defaultSpeed = 2000.0;
float defaultAcceleration = 200.0;

// Variable to start the millis timer immediately.
bool firstRun;

// Variabe to change the positions for MultiStepper X and Y and
// the AccelStepper Z.
int count;

void setup() {
  Serial.begin(115200);
  Serial.println("AccelStepper versus MultiStepper.");
  Serial.println("A first attempt with coordinated AccelStepper.");

  stepperX.setMaxSpeed(300);     // Set max speed for X
  stepperX.setAcceleration(100); // value is ignored
  stepperY.setMaxSpeed(300);     // Set max speed for Y
  stepperY.setAcceleration(100); // value is ignored
  stepperZ.setMaxSpeed(2000);    // Set max speed for Z
  stepperZ.setAcceleration(100); // Set acceleration for Z

  Co1.setMaxSpeed(defaultSpeed); // Set max speed for Coordinated stepper 1
  Co1.setAcceleration(defaultAcceleration); // Set acceleration
  Co2.setMaxSpeed(defaultSpeed); // Set max speed for Coordinated stepper 1
  Co2.setAcceleration(defaultAcceleration); // Set acceleration

  steppers.addStepper(stepperX);
  steppers.addStepper(stepperY);

  firstRun = true;
}

void loop() 
{
  unsigned long currentMillis = millis();
  
  // millis timer
  if(currentMillis - previousMillis >= interval or firstRun)
  {
    previousMillis = currentMillis;
    firstRun = false;

    // --------------------------------------------------
    // Coordinated stepper motors
    // --------------------------------------------------

    // Determine a new position
    long newPosition1 = 0;
    long newPosition2 = 0;
    if(count == 0)
    {
      newPosition1 = random(-1500,1500);
      newPosition2 = random(-4,4) * 100;
    }
    else if(count == 1)
    {
      newPosition1 = 0;
      newPosition2 = 0;
    }

    Serial.print("Coordinated steppers going to: ");
    Serial.print(newPosition1);
    Serial.print(", ");
    Serial.print(newPosition2);
    Serial.println();

    // calculate the absolute distance to the new position
    long absDelta1 = labs(newPosition1 - position1);
    long absDelta2 = labs(newPosition2 - position2);

    // Set the default speed and acceleration for the stepper motor that
    // makes the most steps. Then adjust the speed and acceleration
    // for the other stepper motor, relative to the number of steps.
    if(absDelta1 > absDelta2)
    {
      float relative = float(absDelta2) / float(absDelta1);

      Co1.setAcceleration(defaultAcceleration);
      Co2.setAcceleration(relative * defaultAcceleration);      

      Co1.setMaxSpeed(defaultSpeed);
      Co2.setMaxSpeed(relative * defaultSpeed);
    }
    else
    {
      float relative = float(absDelta1) / float(absDelta2);

      Co2.setAcceleration(defaultAcceleration);
      Co1.setAcceleration(relative * defaultAcceleration);      

      Co2.setMaxSpeed(defaultSpeed);
      Co1.setMaxSpeed(relative * defaultSpeed);
    }

    // Finally, tell the library to move the stepper motors.
    Co1.moveTo(newPosition1);
    Co2.moveTo(newPosition2);

    // Update the global variables for the new position
    position1 = newPosition1;
    position2 = newPosition2;


    // --------------------------------------------------
    // MultiStepper X and Y and AccelStepper Z
    // --------------------------------------------------
    long positions[2];

    if(count == 0)
    {
      positions[0] = 1234;
      positions[1] = 200;
      steppers.moveTo(positions);

      stepperZ.moveTo(1000);    
    }
    else if(count == 1)
    {
      positions[0] = 0;
      positions[1] = 0;
      steppers.moveTo(positions);

      stepperZ.moveTo(0);
    }

    count++;
    if(count > 1)
      count = 0;
  }

  // Keep the AccelStepper library going with the .run() function.
  // Call these all the time, as often as possible.
  // Call these even when there is no motion.
  // The library decides if a step should be done. 
  Co1.run();  
  Co2.run();
  steppers.run();   // Keep the MultiStepper going (X and Y steppers)
  stepperZ.run();   // Keep the Z stepper going.
}

Yes that math looks correct, and should work for the accel/cruise/decel and accel/decel speed profiles that Accelstepper approximates. There may be some misalignment due to accelstepper’s approximations of v=at and p=1/2at^2 but it is small.

This thread discusses the multi-axis motion planning through calculating accel/speed constants versus the Bresenham algorithm that CNCs use:

1 Like

Thank you :smiley:
I read the link (and the links in that), but I do not agree with everything.

I never understand why others put the .run() function in a if-statement. Either I am the only one who does it right, or I am the only one who does it wrong :roll_eyes:

Perhaps I should request the steps from the library during the motion and see if the X-Y curve is straight :thinking: