1

TL;DR : How to prevent step-skipping with a NEMA gearbox motor at low speed.

I am in the process of creating a system in which I want an object to turn on a plate and to show a letter depending on the angle of the rotation. The object is quite heavy hence the rotation should be quite slow, this is why I took a Planetary Gearbox NEMA Stepper.

My system consists in:

This is the code I ended up with:

// Define stepper motor connections and steps per revolution:
#define dirPin 6
#define stepPin 7
#define stepsPerRevolution 5373
int degree_init = 1;

int mouvement=0;

// create a mapping between letters and degrees
int letterToDegree[33] ;
int degree;
// function to map letters to degrees
int mapLetterToDegree(char letter) {
  if (letter=='.'){
    return letterToDegree[27];
  }
  else if (letter==':'){
    return letterToDegree[28];
  }
  else if (letter=="\'"){
    return letterToDegree[29];
  }
  else if (letter==' '){
    return letterToDegree[30];
  }
  else {
  int letterIndex = letter - 'A'; // get the index of the letter in the alphabet
  return letterToDegree[letterIndex]; // return the degree associated with that letter
  }
}

void setup() {
  // Declare pins as output:
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
    Serial.begin(9600); 
    for (int i = 0; i < 33; i++){
    letterToDegree[i]= degree_init;
    degree_init=degree_init+10;
  }
}

void loop() {
  int p= NULL;
  // Set the spinning direction clockwise:
  digitalWrite(dirPin, HIGH);
  String input= "NOW THE NOW THE AAAAA";
  // loop through the letters
  for (int i = 0; i < input.length(); i++) {
    // get the degree for each letter
    degree = mapLetterToDegree(input[i]);
    Serial.print("Letter: ");
    Serial.print(input[i]);
    Serial.print(" Degrees: ");
    Serial.println(degree);
    // wait for the movement to complete
    delay(1000);
 
  int p_new= map(degree,0,360,0,5373);
  Serial.print(" position: ");
  Serial.println(p_new);
  if (p!=NULL){
    mouvement=p_new-p;
    p=p_new;
  Serial.print(" mouvement: ");
  Serial.println(mouvement);
  }
  else{
    p = p_new;
  }
  if (mouvement<0){
    digitalWrite(dirPin, LOW);
    mouvement=abs(mouvement);
    Serial.println("change de direction");
  }
  Serial.print(" stepper: ");
  Serial.println(mouvement);

  // Spin the stepper motor 1 revolution slowly:
  for (int i = 0; i < mouvement; i++) {
    // These four lines result in 1 step:
    digitalWrite(stepPin, HIGH);
    delay(20);
    digitalWrite(stepPin, LOW);
    delay(20);
  }
 
  delay(1000);
  digitalWrite(dirPin, HIGH);
}
}

I tried following this tutorial and it works in broad terms but sometimes the motor skips steps, especially when changing direction.

I can't seem to understand how torque works within this system and how to minimise the stress I put on the motor. My hypothesis is that since the system is at equilibrium and the friction is minimised due to the ball bearing, there should be no need for a lot of power from the motor, and that this motor should suffice.

My hypothesis of why steps are skipped:

  • Too high a speed for the motor
  • Not enough torque power supplied
  • Not good enough electricity supply to the motor.

I am not sure how to go about and test these hypothesis and if those are correct. I am also having a lot of trouble understanding the relationship between the time delay in the code and the movement of the motor.

Especially this bit:

  for (int i = 0; i < mouvement; i++) {
    // These four lines result in 1 step:
    digitalWrite(stepPin, HIGH);
    delay(20);
    digitalWrite(stepPin, LOW);
    delay(20);
  }

Is it ok to change them as I did? do they need to be symetrical (same delay for high and low)?

I am also looking for an explanation of how to apply acceleration and decceleration algorithms for stepper motor, even though I am not sure it makes sense at this speed.

My questions are:

  • How to calculate the best speed for such a system and how to implement it?
  • Is there need for acceleration/ decceleration?
  • Does microstepping makes sense when using a gearbox?
  • Are there some obvious flaws in my system/ code that I am missing out?

Arduino and Driver stepper and ball bearing plate Behaviour description System description

7
  • If the object is heavy instant start/stop/direction change can let the motor skip due to the objects inertia. Do you want to do the acceleration algorithm yourself? If not, try the AccelStepper library, which will do that for you.
    – chrisl
    Feb 1 at 14:30
  • you have un-necessary code in the if (p != NULL) { block ... else is not needed ... p = p_new; is always executed ... put p = p_new; after the if block
    – jsotola
    Feb 1 at 18:21
  • you have not said anything about the desired rotation rate
    – jsotola
    Feb 1 at 18:29
  • A general question: Did you consider using a limit switch (home position) and a rotary encoder (track the steps)?
    – Roland J.
    Feb 2 at 15:12
  • @jsotola Thanks for noticing it, I changed it. The rotation rate should be really slow. Feb 7 at 10:18

1 Answer 1

0

How to calculate the best speed for such a system and how to implement it?

There is no one best speed. This depends on your requirements, the motor torque with the supplied power and driver and the rotational inertia of the object on the motor axis. You can measure the rotational inertia and set yourself a value for the acceleration (even if you don't write the program for acceleration, it will accelerate on the first steps), that you want to have. Then you can check, if your motor has enough torque for this.

Speaking about the motor: Check the ratings of the motor. A good supplier should also give you information on how much torque your motor has at specific currents. Then check if your driver can handle the current (these small stick drivers often cannot handle much current, like 1 or 2A max). These drivers also have a small potentiometer on board, which controls the motor current. Your supplier should also provide information on how to set it correctly (by checking the voltage on one of the pins). You can even find information about this online, when you search for your type of driver. Setting this wrong can lead to either an underperforming motor or the motor overheating. So when setting the motor current with the potentiometer, check the motor temperature afterwards while it is running. Every motor has its own temperature rating, but I would suggest not letting it get too hot to touch.

Having done all above you can drive a test for checking motor speeds. Forget about your current code for a while. Just drive the motor with specific speeds, starting from only a few steps per second and going up until you notice the motor skipping. Then you know how fast you can drive the motor in your configuration without skipping and acceleration. If that is fast enough for you, you can just stick to that.

Is there need for acceleration/ decceleration?

That depends on the above. If the non-skip speed is not fast enough, you can accelerate by gradually increasing the steps per second (aka decreasing the delay between step pulses). To halt at a specific position you then need to decelerate, so you need to plan the movement and control the steps per second accordingly. If you don't want to do that yourself I would suggest using the AccelStepper library. There you can set the target speed and the maximum acceleration and the library will then handle the motor for you.

You wrote in a comment, that you tried the AccelStepper library and that it didn't help. Though you didn't state how exactly it didn't help and what exactly you tried. Maybe you just didn't use the library correctly.

Does microstepping makes sense when using a gearbox?

With microstepping you can get a smoother movement, though I doubt, that this is the problem here. Activating microstepping will of course mean, that you need to send more pulses to the driver for the same speed. Just keep that in mind.

Is it ok to change them as I did? do they need to be symetrical (same delay for high and low)?

The first delay establishes the pulse for the driver. It needs to be big enough, that the driver recognizes the pulse. 20ms is very long for that. If you look at the datasheet of the your driver chip, there should be some information on that. I used a delay of about 50us in the past (so delayMicroseconds(50)), though you might even get shorter.

The second delay then handles the time between pulses, aka the speed of the motor. Though keep in mind, that the first delay is also still a constant in that equation. The speed in steps per second would then be 1/(delay1+delay2) (ignoring the time for the execution of the rest of the code, because only relevant at high speeds).

1
  • Thanks for the detailled response, I eventually chose a bigger, close-loop motor but it helped me understand how to go about it. Feb 17 at 14:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.