Inconsistencies in printing each step taken by stepper (AccelStepper)

Hi all.

Hardware:
-Elegoo Uno R3
-17HS4023 stepper (supplied 12V)
-DRV8825 driver with expansion board (full step, 200 steps per revolution)

I am new to both Arduino / programming / this forum. Kindly excuse me for any stupid mistakes.

In the code below, I ask it to take 200 steps, while printing each taken step.
The problem is that it seems to print more steps than actually taken, or perhaps the stepper is taking more steps than instructed.

#include <AccelStepper.h>

AccelStepper mtr(AccelStepper::DRIVER, 6, 7);
int spd = 300;
int stp = 200;

void setup()
{
  Serial.begin(9600);
  mtr.setMaxSpeed(1000);
  mtr.setCurrentPosition(0);
}

void loop()
{
  int i = 1;
  while (mtr.currentPosition() != stp)
  {
    mtr.setSpeed(spd);  
    mtr.moveTo(stp);
    mtr.runSpeedToPosition();
    Serial.println(String(i++) + "/" + String(stp));
  }
  while (1);
}

Print out from Serial Monitor:

1/200
2/200
3/200
......
198/200
199/200
200/200
201/200
202/200
203/200
204/200
205/200
206/200
207/200
208/200
209/200
210/200

As you can see, it prints out beyond 200, as I click reset, sometimes it ends at 210, sometimes 209, sometimes 208, just not 200.

Alternatively, if I swap line 22 with

Serial.println(String(mtr.currentPosition()) + "/" + String(stp));

then I get many 0/200 at the beginning before the steps start to add up.

0/200
0/200
0/200
0/200
0/200
0/200
1/200
2/200
3/200
4/200
5/200
6/200
7/200
8/200
9/200
10/200
......

Any insight is appreciated.

In your while loop, the serial print is called every time through the while loop so will increment the i variable every time through the while loop. The runSpeedToPosition() function also is called every time through the while loop, but will only step the motor and increment the currentPosition when it is time to step according to the speed setting. So the incrementing of i and the currentPosition are not necessarily one to one.

1 Like

Thank you. That makes sense.

Printing .currentPosition() is the right way to go, right? Will you / others kindly explain the mechanism behind the first few 0/200? I assume it's because .runSpeedToPostion() wasn't executing the first few times through the loop, but why?

(I understand printing each step greatly reduces speed. I'm only doing this for learning / making sure the stepper is doing what I think it's doing).

It is the most accurate way to keep track of position, so yes.

I have to say that I do not know. There is nothing that I see in the reference to explain it.

So jack up the serial baud rate. I usually run at 115200 baud, but you can go much higher if you are printing with hardware serial to the serial monitor. Be sure to change both the code [Serial.begin(baudRate);] and the baud rate in the serial monitor window.

image

1 Like

Thank you very much groundFungus!
You've answered my question but I want to leave the post open in case someone can shed light on:

I assume it's because .runSpeedToPostion() wasn't executing the first few times through the loop, but why?

According to the max. acceleration it may take some time until the first step taken. I admit that its strange that just the first step is delayed, but this may be due to rounding artifacts in the calculations.

1 Like

My first thought, too, but the runSpeedToPosition() function does not use acceleration.

From the AccelStepper reference.

Executes runSpeed() unless the targetPosition is reached. This function needs to be called often just like runSpeed() or run(). Will step the motor if a step is required at the currently selected speed unless the target position has been reached. Does not implement accelerations.

1 Like

Why? Because it is not time to step based on your speed setting. Logic says there is no reason to step until one is required.

2 Likes

Is your loop going faster than the motor can keep up? I mean, does the loop have feedback to know that the motor is in position before moving to the next step? Seems like 'mtr.currentPosition()' position needs time to catch up. I'm guessing. I've not used stepper libraries yet.

1 Like

As already stated, .runSpeedToPosition() doesn't always execute a step when it is called, but only when a step is due. And it tells you if it executed a step or not: The returned value is TRUE if a step has been executed, and FALSE if not. So you only need to use this information and print only if there was really a step:

#include <AccelStepper.h>

AccelStepper mtr(AccelStepper::DRIVER, 6, 7);
int spd = 300;
int stp = 200;

void setup()
{
  Serial.begin(115200);
  mtr.setMaxSpeed(1000);
  mtr.setCurrentPosition(0);
}

void loop()
{
  int i = 1;
  while (mtr.currentPosition() != stp)
  {
    mtr.setSpeed(spd);  
    mtr.moveTo(stp);
    if ( mtr.runSpeedToPosition() ) {
        // step has been executed, print it!
        Serial.println(String(i++) + "/" + String(stp));
    }
  }
  while (1);
}
1 Like

Thank you all for the help! Happy new year.

Happy New Year!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.