Stepper Motor Step Accuracy Issues

dev_000:
I cant visually see it missing steps(I tried this with multiple motors with code mentioned before). But then again I wont be able to see visually that accurately to see if it had missed a step(as the step angle is small).

It would be very strange if it just misses a single step out of several hundred and if it misses several steps the error should be visible.

How many steps per revolution are you using?

When you measure the distances actually moved by your machine and find an error, how many steps would be needed to "achieve" that error? For example if there are 800 steps per mm and the error is 0.25mm then that is equivalent to 200 steps.

...R

If you're talking about the first few minutes of the vid, then yes, that is the type of indicator.

Robin2:
How many steps per revolution are you using?

When you measure the distances actually moved by your machine and find an error, how many steps would be needed to "achieve" that error? For example if there are 800 steps per mm and the error is 0.25mm then that is equivalent to 200 steps.

Motor is rated for 200 steps per revolution moves 1mm. I am doing running it in Full step mode.

For the second part, Does the following info suffice?

I am thinking of getting this motor Pololu - Sanyo Pancake Stepper Motor with Encoder: Bipolar, 200 Steps/Rev, 42×24.5mm, 3.5V, 1 A/Phase, 4000 CPR with a built in encoder and test each part of my system separately(The Code, The motor if its skipping steps, The mechanical arrangement for any backlash or any other error) With the above motor I guess I can find the answer to whether motor is skipping steps in no load condition.

Image from Reply #22 so we don't have to download it. See this Simple Image Guide

...R

Please explain how to interpret the data in the table?

What program did you run to produce the data in the table? Please post the program.

At this stage I don’t see any need to get a different motor. That will just complicate things.

…R

Please explain how to interpret the data in the table?

Please check the Reply #6 for details on how to interpret it.

Ok. So I decided to do a fresh start today.

I took out my motor from the assembly and wanted to check each section to see where a potential issue be coming from. So here is what I did.

I connected the motor to Polulu DRV8825 shield via an Arduino Leonardo at a no load condition(Almost). I connected a coupler to the motor shaft and made sure its very tight to avoid any slippages. I printed out this Circular 360 degree angle picture and made sure the shaft is perfectly aligned to the center of that picture. Then I 3D printed a arrow(Very light) which goes on top of the coupler to show angle of rotation when seen from the top. (Sorry I don’t have the picture of the setup with me now, will post it tomorrow). I set the current limit of the driver to 1A.

What I wanted to test was that if there was any missing steps(By measuring the shaft angles) when I change the parameters of the code like delay between each step or when it runs lot of steps or when it is running in different modes.

Following is the code I used for the test. I change the modes and parameters in each test.

// Arduino Digital Pins and Motor Connections
int dPin = 6; // Direction motor || HIGH - Towards the Motor || LOW - Away from the Motor
int sPin = 7; // Step Pin for providing square pulses
int wake = 9; // Sleep Pin || HIGH - Driver Enabled || LOW - Enter Sleep Mode
int M1 = 4; // Mode Pins
int M0 = 5; // Mode Pins
int enb = 8; // Enable Pin for driver || HIGH - Driver Disabled || LOW - Driver Enabled
int rst = 10; // Reset Pin for driver || HIGH - Driver Enabled || LOW - Driver Disabled
int pulsePeriod = 100; // Pulse Period for the Step Waveform
char input;

// Following parameters can be changed in the tests
int delayTime = 30 ; // Delay between Each Step in milliseconds
int nMoveSteps = 1600; // Testing with values 100, 200, 400, 800, 1000

void stepMotor(boolean dir, int nSteps, int dirPin, int stepPin)  // Input - Value for Direction Pin, Number of Steps to be moved pins, uC Pins for direction and step
{
  digitalWrite(dirPin, dir);    // HIGH - Towards the Motor || LOW - Away from the Motor
  delayMicroseconds(2);
  for (int i = 0; i < nSteps; i++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulsePeriod);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(pulsePeriod);
  }
}

void setup()
{
  Serial.begin(9600);
  pinMode(dPin, OUTPUT);
  pinMode(sPin, OUTPUT);
  pinMode(wake, OUTPUT);
  pinMode(enb, OUTPUT);
  pinMode(M0, OUTPUT);
  pinMode(M1, OUTPUT);

  // Full Step Mode
  //   digitalWrite(M0, LOW);
  //  digitalWrite(M1, LOW);

  // Half Step Mode
  //  digitalWrite(M0, HIGH);
  //  digitalWrite(M1, LOW);

  // One Fourth Step Mode
  //    digitalWrite(M0, LOW);
  //    digitalWrite(M1, HIGH);

  // One Eight Mode
  digitalWrite(M0, HIGH);
  digitalWrite(M1, HIGH);

  digitalWrite(enb, HIGH);  // Logic HIGH - Driver Disabled
  digitalWrite(wake, HIGH); // Logic HIGH - Driver Enabled
  digitalWrite(rst, HIGH);  // Logic HIGH - Driver Enabled
}

void loop()
{
  if (Serial.available() > 0)
  {
    input = Serial.read();

    if (input == 'f' || 'F')
    {
      for (int i = 0; i < nMoveSteps; i++)
      {
        digitalWrite(enb, LOW);
        delayMicroseconds(2);
        stepMotor(HIGH, 1, dPin, sPin);
        delay(delayTime); // For Delay between each step  // 30ms for Sanyo Pancake motor @10V, 20ms Oriental PKP225D06A @6V, 10ms for SY35ST26 @7.4V
        digitalWrite(enb, HIGH);
      }
      Serial.println("Move Forward");
    }
    else if (input == 'b' || 'B')
    {
      for (int i = 0; i < nMoveSteps; i++)
      {
        digitalWrite(enb, LOW);
        delayMicroseconds(2);
        stepMotor(LOW, 1, dPin, sPin);
        delay(delayTime); // For Delay between each step // 30ms for Sanyo Pancake motor @10V, 20ms Oriental PKP225D06A @6V, 10ms for SY35ST26 @7.4V
        digitalWrite(enb, HIGH);
      }
      Serial.println("Move Backward");
    }
    else
    {
      Serial.println("Wrong Input");
    }
  }
}

I give Serial Input as ‘F’ which will cause the motor to move nMoveSteps as mentioned in the code.

Test results are as follows for various parameters.

My inference is that there is no missing of steps(except for a couple of times in all of the tests conducted) based on the tests above.

So I am assuming my code and the motor with no load is working precisely. (Any counter suggestions?)

What I am planning to do tomorrow is to connect loads and my mechanical setup to see if that is causing any issue.

Any thoughts on the above?

Also on a side note, lets say if I move the n steps via code and then when motor is stationary, I rotate the shaft slightly with my hand and then move n steps again via code, I see a slight jump in the reverse direction before the motor proceeds to rotate in the proper direction. Is this because of the misalignment between the energised stator and the rotor. (I will probably read up in detail about the sequencing of motors, that will probably answer the above question but just thought of asking).

When ever your code disables and then enables the controller, the magnet coils are re-energized. It is impossible to have the coils energized at identically the exact same time. This will cause movement.

Paul

I agree with @Paul_KD7HB.

Under no circumstances should the motor-driver be disabled until you are completely finished with all movements.

Re-do all your tests without ever disabling the driver.

…R

Thanks for the inputs you guys.
Do you mean to say something like this?

if (input == 'f' || 'F')
    {
       digitalWrite(enb, LOW);
       delayMicroseconds(2);
            for (int i = 0; i < nMoveSteps; i++)
            {
              stepMotor(HIGH, 1, dPin, sPin);
              delay(delayTime); // For Delay between each step          
            }

       digitalWrite(enb, HIGH);
   }

I will repeat the tests and report back

But one thing I noticed is that even if delayTime = 0, it was not missing any steps. Is that common among stepper motors? I would assume that there needs to be some delay.

Also, a general question, once a driver is disabled, how does it know which is the next sequence to be followed for a proper stepping of the motor among all its movement sequences when the next step input comes? How does it have a so called “memory”? (Or does it?)

dev_000:
Thanks for the inputs you guys.
Do you mean to say something like this?

Why have you got this line in loop()

digitalWrite(enb, LOW);

and its counterpart?

Just set the enable pin in setup() so that the motor can work and leave it set.

...R

Why have you got this line in loop()

digitalWrite(enb, LOW);

and its counterpart?

Well, for me, there were 3 reasons,

  1. Why keep the coil's energized and make it draw power all the time? (In my finished product, I would be having atleast three of these motors)

  2. When I was Enabling the driver, I could see switching noise in the A1, A2, B1, B2 coils(in a custom PCB which I made) even when there was no step signal provided.(Although it wasnt causing any motion) when I observed it through a logic analyser. (One other possibility was that it might have been due to noise coupling between the multiple channels in the logic analyser, well thats to be figured out for an another day)

  3. Well, Datasheet gives me the option to do so, hence why shouldn't I utilize it, was my thought. I was following the timing diagram in DRV8825 for the enable pin.(Page 7 of datasheet)

Stepper motors are very inefficient. If you want precision you have to accept that and not go mucking about with the enable pin.

I hope your enthusiasm for disabling your stepper driver has not been the primary cause for this whole Thread?

...R

I put the Enable pin to LOW in the setup() and then tried the above results. I am getting same results as mentioned in the table in the previous long post of mine.
So I dont think its the toggling of the enable pin that is causing the issue.

PS: I am getting a constant hum on the motor now as I have driver is enabled always not to mention the DRV8825 getting warmer because of the constant power draw.

I will try with the mechanical setups today and see if something improves.

dev_000:
PS: I am getting a constant hum on the motor now as I have driver is enabled always not to mention the DRV8825 getting warmer because of the constant power draw.

All that is perfectly normal.

Stepper motors and drivers are usually so hot that they are uncomfortable to touch.

...R

So I might have been wrong about the Enable pin part.
Here is what I tried today.

I used the same motor and firmware setup(which was having no missing steps, at no load conditons) as yesterday. I mounted it on my mechanical system with a ball screw arrangement with a 1mm pitch. I am using a high quality C3 grade ball screw. I connected an optical encoder on the axis next to it to measure the linear motion.

There are two mechanical arrangements which I am testing it on, one is a vertical shaft with Motor mounted on the top and another is one with a horizontal shaft. Torque requirement is larger for the vertically mounted motor because of what is connected on the shaft perpendicular to it.

I moved the motor with the forward command 'F', three times, and backward command 'B', three times, to return back to the initial position. A, B, C, D, E, F, G are the corresponding position labels.

In the firmware, I had three options with the Enable pin.

  • Global Enable: Where I make the enable pin go low in setup() and the driver is always energized and drawing a constant current
  • Individual Step Enable: Where I make the enable pin low just before each step is moved and then make it high again. It has low power requirement and timing is done as per the driver's datasheet
  • Batch Enable: Where I enable the driver when the motor is doing a set of steps in one single go and then deactivates it (Not in every step though) till next batch of step signals come.

Following are the readings with different parameters for the vertically mount motor.

What I am seeing is that, reading at intermediate positions (A-G) are not coming perfectly. There is always a significant error even when I change various parameters. I got a proper reading only once(SlNo 14) when I was using a particular section of the ball screw for the movement. So I might be inclined to think there was wear tear and that is causing me to not travel correct distances? There has been a lot of movement on those threads. But I dont think it has reached its end of life though based on it usage.

So when a larger load is placed(Because of the vertical mount) Its not properly moving correct distances. Any other explanations possible?

Now for the horizontal axis motor, following are the readings

This ball screw hasn't suffered the same amount of motion on it as the vertical mount motor ball screw. I am getting acceptable readings of error. But its seems to be working only in the Global Enable mode, not in any of the other modes.

Any idea on why its working only in the global enable mode and not in other ones? I cant use the global enable in the final design because of constant power draw constraints, hum of the motor and switching noise its inducing. So I have to get it working in one of the other enable modes and also achieve good accuracy. I cant seem to think of a reasonable explanation as to why it is stepping only in Global enable mode.

Have you ever verified that the threads on your ball screws are consistently giving you 1 mm of movement across the entire threaded length of the screw? I am not thinking about how you are moving the screw with a stepper motor, but turning one complete turn by hand with an index marker of some kind.

Paul

Try a simple program with no user input apart from pressing the Arduino reset button. And with the stepper motors enabled all the time.

Get it to move enough steps for (say) 50mm of movement out an back with a short pause when the direction changes. It should be back at the original position. If it is not tell us the amount of error for each run of (say) 10 tests.

I have a really cheap Sieg C1 lathe to which I attached stepper motors. When I build an allowance for backlash into my program the error is less than 0.05mm as measured with a dial test indicator.

It is a complete waste of your time to try alternative enable modes until after you get the precision you want when the motors are permanently enabled.

...R

Have you ever verified that the threads on your ball screws are consistently giving you 1 mm of movement across the entire threaded length of the screw? I am not thinking about how you are moving the screw with a stepper motor, but turning one complete turn by hand with an index marker of some kind.

I can give it a shot if I can figure out how to get an index marker by which I can turn 1 rotation accurately.
I am using SG0801-100R140C3 KSS ballscrew. Datasheet. The company did accuracy tests before dispatch and it did come with a report. But I have been using it for few months now, so I am not sure if there could be some wear and tear.

Get it to move enough steps for (say) 50mm of movement out an back with a short pause when the direction changes. It should be back at the original position. If it is not tell us the amount of error for each run of (say) 10 tests.

Will try it out and let you know on Monday.

I tried what Robin2 had suggested for both the horizontal and vertical setups I was using. Both were with motor continuously enabled and drawing a constant current. Motor was in full step mode.

For the horizontal setup following are the readings for various settings.

Error here is more or less acceptable for me.
Confusing part for me is why is it working only in the global enable mode only.

But when I go for the vertical case, errors are very high. So I have feeling the load/torque on the shaft on the vertical motor is causing this issue.

I couldn't do what Paul_KD7HB had told me because, I cant reliably turn the motor by hand by 360 degrees.

Please post your images here. You clearly know how.

Also post the test program that you used.

...R