A4988 sleep mode use causing motor jitter/jerk

Hello!

I am using A4988 drivers to control my NEMA17 steppers, and using 1/16 microstepping by setting MS1, MS2 and MS3 high. Everything works well.

I am also using the SLEEP pins of A4988s to turn the motors off when not in use. And I control the logic as follows:

#define speed_delay 2000         // pulse width for motor 700
#define sleep_delay 1000         // works with 10?

#define num_motors 4

struct Stepper {
  int stepPin;
  int dirPin;
  int sleepPin;
};

Stepper steppers[num_motors] = {
  { 2, 3, 10 },
  { 4, 5, 11 },
  { 6, 7, 12 },
  { 8, 9, 13 }
};

int newPos[num_motors];
int multiplier = 1;

void setup() {
  for (int i = 0; i < num_motors; ++i) {
    pinMode(steppers[i].stepPin, OUTPUT);
    pinMode(steppers[i].dirPin, OUTPUT);
    pinMode(steppers[i].sleepPin, OUTPUT);
    digitalWrite(steppers[i].stepPin, LOW);
    digitalWrite(steppers[i].dirPin, LOW);
    digitalWrite(steppers[i].sleepPin, LOW);
  }
}

void loop() {
  for (int i = 0; i < num_motors; ++i) {
    newPos[i] = (i % 2 == 0) ? (i * 1000 * multiplier) : (i * -1000 * multiplier);
    go_there(i);
    delay(1000);
  }
  multiplier = multiplier * -1;
}

void go_there(int i) {
    if (newPos[i] < 0) {   // clockwise
      digitalWrite(steppers[i].dirPin, HIGH);
      newPos[i] = newPos[i] * -1;
    } else if (newPos[i] > 0) {   // counter-clockwise
      digitalWrite(steppers[i].dirPin, LOW);
    }

    digitalWrite(steppers[i].sleepPin, HIGH);

    delay(sleep_delay);   // <-- this highlights the problem

    while (newPos[i] != 0) {
      digitalWrite(steppers[i].stepPin, HIGH);
      delayMicroseconds(speed_delay);
      digitalWrite(steppers[i].stepPin, LOW);
      delayMicroseconds(speed_delay);
      newPos[i] = newPos[i] - 1;
    }

    digitalWrite(steppers[i].sleepPin, LOW);
}

When I set the sleep_delay to 10, the motor seems to work fine. When I increase it to 1000, there is a erratic jerk/jitter followed by 1000ms delay, and then the motor runs smoothly.

Why is this happening?

I started debugging this because I have a suspicion that this erratic jerk/jitter might be happening with 10ms sleep_delay as well, which could be affecting my precision measures. But I wasn't completely sure because 10ms delay is too tiny to observe by looking, and so I started increasing this number to see the effects.

Please post the entire code. Possibly important information is missing.

Thank you @Railroader. I have updated the full code in the post.

Thanks.
I suggest splitting speedDelay into a pulseDelay being some 10 - 20 microseconds and speedDelay some 10000. The speedDelay will be controlling the speed of the stepper. Note that maximum speed for the stepper calls for acceleration/deceleration. Without those You need to check other stepper parameters like run-in, run-out for max useful speed and they are lower. Light load versus high load on the stepper axle also effects the value. Exceeding those values gives You a buzzer instead.

To turn the motors off, the ENABLE Pin is a better choice. SLEEP sets the A4988 itself to sleep mode, and it needs a little time to 'wake up'. Also it resets the microstep state.
ENABLE only turns the motor off, without resetting any internal state of the A4988 - the A4988 itself stays active.

Thank you @MicroBahner. I rewired and started using ENABLE. The jitter has significantly reduced (it is still there, but it is very minor and so it is fine).

I have a related question here. Let's say when I do the following:

  1. Start the motor and rotate it few steps.
  2. After the steps are completed, I use ENABLE pin to disable the motor.
  3. While the motor is disabled, I manually rotate the shaft arbitrarily.
  4. Then I use the ENABLE pin to enable the motor.

In this case, I see the same large jitter/jerk on step 4. Is this because the manual rotation of shaft in point 3 would have changed the internal coil positions, and then when I ENABLE the motor the internal rotor basically jumps to the nearest coil position that matches the wave signal correctly, which results in this jerk/jitter?

If I do not do point 3 above, then there is no large jerk/jitter.

Every stepper motor has a detent torque. This means that it will only stop in certain positions without energized coils. You can normally feel this when you turn the motor by hand. The movement isn't completely smooth. It only stops by itself in certain positions. So if you switch off the coils, it will move to the nearest detent position. When the coils are switched on again, it then moves jerkily to the position corresponding to the coil currents. The larger the difference between the detent position and the position defined by coil currents the larger the jerk. That's normal stepper behaviour. If this small jerk is troublesome, you must not switch off the coils.

Thank you @MicroBahner. I am observing something opposite of what you're describing.

But when I switch off the coils, I do not see the shaft move at all.

Am I misunderstanding something here?

Then the shaft is already at a detent position. Avoid using microstepping until you understand the full step behavior, as microstepping is intended for smooth running, rather than accurate shaft positioning.

Thank you @jremington. I just now did some experiments where I disabled micro-stepping. I am still observing the same behavior. When the coils are switched off, the shaft does not move anywhere. And I tried these experiments with various different random positions. There is no way all of those random positions are also detent positions, right?

Determine that for yourself by slowly and carefully turning the shaft by hand, after the coils have been turned off.

Detent torque with coils off is much smaller than the holding torque with coils on. So the movement to the detent positions is not jerky and less noticeable than the movement to the holding position.

The issue of stepper motors jumping when powered up is a relatively common issue, and it's due to the way stepper motors work.

The only thing approaching a "fix" is to use a brake on the shaft.

Thank you @MicroBahner. This makes sense.

Could the movement to the holding position when the coils are turned on be "reduced" using microstepping? Since the jerky movement when the motor gets turned on is because of holding position, if the amount of microstepping increases (e.g., 1/16 instead of 1/2), then will the holding position be somewhere nearer resulting in a smaller jerk?

I don't think so. Microstepping allows you to position the stepper in more positions between the detent positions. But do you know what microstepping position you are at when you deactivate the motor - away from the full step positions?
This behavior also depends a lot on your stepper and the mechanics. How is the stepper (mechanically) loaded?
I tried it with my test stepper (completely unloaded), and there was only a very small jerk when deactivating/activating - barely noticeable.

Thank you @MicroBahner. This makes sense.

Out of curiosity, which stepper are you testing with? I am using an off-the-shelf NEMA17 + A4988 for my tests, which is giving the jerky behavior.