DRV8825 Jumps @enble/disable

I have the DRV8825 connected to an Arduino. The Reset pin is attached to one pin #13.

When I send a disable and enable command, the stepper (1.8 amp), the motor seems to jump the next position. My question is how do I stop this?

I’ve seen similar discussions but never a solution. My current is set using the potentiometer on the board at .9 volts.

I’m not using microstepping; this is to control a BBQ smoker; I don’t need fine control, but I do need very accurate placement over time because I will be running the system for up to 14 hours.

Code is below just to demonstrate issue:

#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
#include "BasicStepperDriver.h"


#define MOTOR_STEPS 200     // Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define RPM 60

#define MICROSTEPS 1

#define DIR 2                    // All the wires needed for full functionality
#define STEP 3                   // All the wires needed for full functionality
#define SLEEP 13

LiquidCrystal_I2C lcd(0x27, 20, 4);                                           // set the LCD address to 0x27 for a 16 chars and 2 line display

BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP);        //Uncomment line to use enable/disable functionality

void setup() {
  delay(25);
  Serial.begin(9600);                                  //  Initialize the serial port and set communication speed at 9600 baud
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Setting UP");
  stepper.begin(RPM, MICROSTEPS);
  stepper.setEnableActiveState(LOW);   //  use for Sleep command or comment out for enable/disable on ENABLE pin (active LOW)
  stepper.disable();
}


void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Starting Loop");
  delay(100);
  for (int x = 0; x <= 10; x++) {
    stepper.enable();
    lcd.setCursor(0, 1);
    lcd.print(x);
    delay(100);
    stepper.disable();
    delay(100);
  }

Hello.

Can you post some pictures of your setup? We did not make the BasicStepperDriver library you are using and I am not that familiar with it, but it seems like the program you posted would not actually command the stepper motor to move anywhere. Is that correct? If running this program demonstrates the problem you are describing, it might be useful to post a video showing that. The forum does not allow users to post very large videos, but it does work well with videos linked from other sites (like YouTube or Vimeo).

You might try actuating the nENABLE pin instead of the nSLEEP pin to deenergize your stepper motor to see if that makes a difference. However, depending on your load, the stepper motor jumping a little bit whenever you energize it might be unavoidable. Whenever you deenergize the motor the rotor is probably moving into a position between steps where it would not normally be if were energized, so when you energize the motor again it will naturally jump back to a step position. Have you considered just leaving the stepper motor energized while your system is running? Alternatively, maybe you could avoid this behavior and still be able to deenergize your motor if you add some type of braking mechanism. There are stepper motors with built-in electromagnetic brakes, but none of our stepper motors have brakes.

- Patrick

You are correct; this code does not make the motor move. I simplified it to only disable and enable the stepper. I’ve modified the code in an attached a video that does show the stepper going one revolution in one direction, enabling/disabling 5 times, then reversing direction one revolution and then enabling/disabling 5 more time. You can actually hear the stepper jumping (skipping?) position. it is also obvious just before the revolution.

I will work on the nENABLE versus SLEEP, but I haven’t had much success with either. I also tried using digitalWrite(13, HIGH) etc.

My project is going to be to control a BBQ smoker over a 12-14 hour timeframe. Based on the temperatures that I’m seeing on the bench, I don’t think the motor and driver would survive being “ON” for that period of time.

The video is too large to post, but a link in iCloud is here: The file will only be good for 30 days. Click to Download

Thanks for the reply and appreciate any help or suggestions.

Can you post some pictures that show the wiring to your driver and share what specific stepper motor you are using?

- Patrick

Picture1

I used a very standard connection. Image attached.
Photo of my actual breadboard is attached.
Arduino1

At your suggestion, I disabled the enable/disable and am writing directly to the enable pin. Seems to be somewhat “better”, but still is jumping (skipping?).

#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
#include "BasicStepperDriver.h"


#define MOTOR_STEPS 200     // Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define RPM 60

#define MICROSTEPS 1

#define DIR 2                    // All the wires needed for full functionality
#define STEP 3                   // All the wires needed for full functionality
#define SLEEP 13

LiquidCrystal_I2C lcd(0x27, 20, 4);                                           // set the LCD address to 0x27 for a 16 chars and 2 line display

// BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP);        //Uncomment line to use enable/disable functionality
BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP);        //Uncomment line to use enable/disable functionality

void setup() {
  delay(25);
  Serial.begin(9600);                                  //  Initialize the serial port and set communication speed at 9600 baud
  pinMode(13, OUTPUT);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Setting UP");
  delay(1000);
  stepper.begin(RPM, MICROSTEPS);
  delay(500);
  //  stepper.setEnableActiveState(LOW);   //  use for Sleep command or comment out for enable/disable on ENABLE pin (active LOW)
  delay(500);
  //  stepper.disable();
  digitalWrite(13, HIGH);
  delay(500);

}


void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Starting Loop");
  delay(500);
  for (int x = 0; x <= 4; x++) {
//  stepper.enable();
  digitalWrite(13, LOW);
    lcd.setCursor(0, 1);
    lcd.print(x);
    delay(100);
    //    stepper.disable();
    digitalWrite(13, HIGH);
    delay(500);
  }
 //  stepper.enable();
  digitalWrite(13, LOW);
  stepper.move(200);
  //    stepper.disable();
  digitalWrite(13, HIGH);
  delay(1500);
  lcd.clear();
  lcd.print("Starting Loop");
  for (int x = 0; x <= 4; x++) {
    stepper.enable();
    lcd.setCursor(0, 1);
    lcd.setCursor(0, 1);
    lcd.print(x);
    delay(100);
    //    stepper.disable();
    digitalWrite(13, HIGH);
    delay(500);
  }
//  stepper.enable();
  digitalWrite(13, LOW);
  stepper.move(-200);
//  stepper.disable();
    digitalWrite(13,HIGH);
  delay(1500);
}

I could not find a specific driver for the 8825 in the Arduino library. There were several, but for other devices. If you have one (driver) that is compatible with the 8825 that you recommend, please pass along the information. This is for an Arduino Nano.

I did some testing here and was able to reproduce something similar to the behavior you are seeing with multiple different stepper motors and stepper motor drivers, so I think what you are seeing is mostly a result of the rotor’s rest position just being slightly different from its holding position when energized. That means it is probably going to be impractical to completely avoid this issue on some level unless you add a brake or just avoid deenergizing your motor like I suggested earlier. However, I am not sure if it would really be that consequential, and if it is, then I think there might be some ways to work around it.

The behavior in my testing mostly seemed to follow the particular stepper motor. For my smaller stepper motor it seems like denergizing and energizing the motor mostly just causes it to shift slightly out of and then back into the same step position, so I do not think it is actually losing position. I was able to produce behavior more like what you see with a larger stepper motor. The rotor would do a larger jump the first time it was deenergized and then energized again after moving to a new position, possibly causing it to skip a step. After that initial larger jump though, subsequent deenergize then energize cycles would only cause the same kind of minor shifting I saw with the smaller motor.

In my tests I was able to get rid of the larger jumps by using nENABLE instead of nSLEEP to deenergize the motor, but I suspect the success that change is largely going to depend on the particular motor. So, if that does not work, you might be able to work around the issue just by establishing if the behavior is fairly consistent and then accounting for it in your program (e.g. always command your motor to one step less or more than your actual target position). Alternatively, maybe you could add some type of position feedback to your setup that will recognize if the position error from that behavior accumulates to a point that could cause problems (e.g. position a limit switch that triggers at one point in the motor’s rotation and use it to confirm that the motor position makes sense).

I am not sure what you mean when you say that you could not find a specific driver for the DRV8825 in your library. It seems like you are using this StepperDriver library available on GitHub. If so, it seems like that library does include files specifically intended for use with the DRV8825 (in the src folder), but I am not sure if those are that helpful and think your use of the library was generally fine already.

By the way, I realized that I forgot to comment earlier about you setting the current limit to 1.8A. That is greater than what we would normally expect the DRV8825 to handle without additional cooling (about 1.5A), so especially if the ultimate goal is to use this in a higher temperature environment, I would suggest reducing that. Alternatively, if you really need to maximize the power from the motor, you might consider one of our larger stepper motor drivers that can handle higher currents, or perhaps one of our Tic Stepper Motor Controllers. Our Tics and some of our other drivers (like the MP6500) also have features that let you dynamically adjust the current limit while they are running, so if you go with one of those a workaround option might be to reduce the current limit while the motor is holding position to limit heat build-up instead of disabling it entirely.

- Patrick

Patrick, thanks for the feedback.
I worked on the nENABLE and nSLEEP and still not quite satisfactory so I tried a couple of other things (later).

I was pulling the library from GitHub at the same link you sent, but it was authored by an individual and was not attributed to Pololu. I did not check the src folder (still new to this), but will try it tonight.

Thanks for the hint on the current. I was setting it for the motor. I overlooked the current capacity of the 8825. I think I had seen that it could do something larger with cooling, which I was planning to provide, but for now, on the bench, I’ll dial the voltage back to 0.75 Vdc. I did find that if I go too low on the current, I get very random motor movements.

This is a one-off prototype that I’m building so I’m not too concerned about parts costings. I will look into the Tic and MP6500 controllers. Thanks for those hints.

I did have some success creating my own driver. This code rotates the motor one direction and then the other. I was using it to test repeatability. So far, I’m not getting any jumps or skips. See what happens on your set-up:

// Define stepper motor connections and steps per revolution:
#define dirPin 2                   // direction pin of the motor driver
#define stepPin 3                  // step pin of the motor driver
#define enablePin 13               // enable/disable pin of the motor driver
#define stepsPerRevolution 200
char Rotation = "HIGH";
int Speed = 60;
int Direction = 1;                     //  Sets a CW direction for the motor; -1 is CCW
int Steps = 200;

void setup() {
  Serial.begin(9600);
  Serial.println("Set UP");
  pinMode(stepPin, OUTPUT);              // Declare pins as output:
  pinMode(dirPin, OUTPUT);               // Declare pins as output:
  pinMode(enablePin, OUTPUT);            // Declare pins as output:
  delay(100);
  digitalWrite(enablePin, HIGH);
  Serial.println(" End");
}

void loop() {
  Direction = Direction * -1;
  Move_Stepper(Steps, Speed, Direction);
  delay(5000);
}

void Move_Stepper(int Steps, int Speed, int Direction) {
  Speed = Speed / 60;                                            //converts RPM to Rev/Sec
  int Time_Delay = (1000000) / (Speed * stepsPerRevolution * 2); //Converts speed and steps per revolution to uS
   if (Direction == -1)    Direction = 0;
 
  char *Rotation[] = {LOW, HIGH};

  digitalWrite(enablePin, LOW);                          // Enable the motor
  digitalWrite(dirPin, Rotation[Direction]);             // Set the spinning direction HIGH for clockwise, LOW for  counterclockwise
  for (int i = 0; i < Steps; i++) {                      // Spin the stepper motor the number of steps at 60 rpm:
    digitalWrite(stepPin, HIGH);                         // These four lines result in 1 step:
    delayMicroseconds(Time_Delay);                       // These four lines result in 1 step:
    digitalWrite(stepPin, LOW);                          // These four lines result in 1 step:
    delayMicroseconds(Time_Delay);                       // These four lines result in 1 step:
  }
  
  if (Direction == 0)  Direction = -1;

  digitalWrite(enablePin, HIGH);                           // Disable the motor
  delay(500);
}

Just to clarify, we did not make and do not support the StepperDriver library you have been using. I just looked into it briefly and used it to test your code.

The random movement behavior you see if you lower the current limit too much is expected since at sufficiently low limits the motor will not be able to draw enough current to act reliably.

Running your new code I think I can still notice small inconsequential shifts from deenergizing and energizing, but I did not see any larger jumps. That matches the behavior I discussed in my last post since this program uses the nENABLE pin. As I mentioned before, the results are probably going to mostly depend on your particular motor, so if this approach is making it work now, I would keep running with it.

- Patrick