Stop Stepper Motor with Encoder Feedback

I want to know the position of a stepper motor using an optical encoder.

I did a first test with the AccelStepper.h library but on repetition the encoder would be off by about 12-25 pulses. I read online that this might have to do with the way AccelStepper calculates acceleration.

I used the simple stepper motor code and it repeated with spot on accuracy but it is a hard stop with the stepper.

The encoder has 600 pulses so with A + B it is 2400 per revolution.

I have a large Nema 42 stepper with a Leadshine microstep driver that has pul and dir.

My plan is to tell the stepper to move. Check that the encoder read where it was supposed to go to and then correct if wrong. I would also like to write this encoder position value to an SD card so that the motor knows where it is if the power goes out.

Or should I the the motor to move until a certain reading is on the encoder rather than moving the stepper and then checking the encoder?

#include <AccelStepper.h>

#include <Encoder.h>
// Define a stepper and the pins it will use
AccelStepper stepper (1,8,9); // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5


unsigned long timer;
const unsigned long delayTime = 1000;//1s wait
const long distance = 2000;//number of steps to move at a time

long previous = 0;
long oldPosition  = -999;
long newPosition;
Encoder myEnc(2, 3);

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds
unsigned long delaystate = 2000; // milliseconds
long steps;

byte directionPin = 9;
byte stepPin = 8;
enum stepperStates {  a, b, c, d }; 
int buttonState = 0;
stepperStates motorstate = a;


void setup(){  
  // Change these to suit your stepper if you want
   Serial.begin(57600);
  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  Serial.println("Basic Encoder Test:");
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(20);
  stepper.move(distance);//start by moving
  motorstate=a;
}//setup()


void loop(){
  curMillis = millis();
  readEncoder();
  //stepperState();

}//loop()

void readEncoder () {   
  newPosition = myEnc.read();

  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    steps = newPosition / 12;
    Serial.println(steps);
    
    
  }
}


void stepForward() {
  digitalWrite(directionPin, LOW);
  if (steps > -100) {if (curMillis - prevStepMillis >= millisBetweenSteps) {
    prevStepMillis += millisBetweenSteps;
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);
  }
  else {digitalWrite(stepPin, LOW);
  
  }
   }
   if (steps <= -100) {motorstate=b;}
}

void stepBackward() {
  digitalWrite(directionPin, HIGH);
  if (steps < 100) {if (curMillis - prevStepMillis >= millisBetweenSteps) {
    prevStepMillis += millisBetweenSteps;
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);
  }
  else {digitalWrite(stepPin, LOW);
  }
  }
  if (steps >= 100) {motorstate=d;}
}
void stepperState () {
// read the sensor:

    switch (motorstate) {
      case a:
        stepForward();
        
        break;
      case b:
        if (curMillis - prevStepMillis >= 2000) {
    prevStepMillis += millisBetweenSteps;
        motorstate=c;}
        break;
      case c:
        stepBackward();
        break;
      case d:
        if (curMillis - prevStepMillis >= 2000) {
    prevStepMillis += millisBetweenSteps;
        motorstate=a;}
        break;
      default:
      
         break;
    } 
       
}

If you're using AccelStepper, and you have an encoder, then look at where you are now, figure out where you want to be, calculate how many steps that is, and tell AccelStepper to move that many steps. Trying to stop when you see the encoder reading you want will NEVER land you on the right position, due to the time it takes to decelerate. And, smooth acceleration, and deceleration, are, after all, the whole point of using AccelStepper....

Regards, Ray L.

How many steps per rev is your motor?, Trying to accel or deccel too hard will cause the motor to miss steps.

More fundamentally, why don't you trust the stepper motor to move the correct number of steps?

It is hard work for an Arduino to read an encoder - especially if the step-rate is high.

Perhaps you don't need to use any stepper library? Writing your own code is not difficult for a drive that takes step and direction signals.

...R Stepper Motor Basics Simple Stepper Code

Robin2: Perhaps you don't need to use any stepper library? Writing your own code is not difficult for a drive that takes step and direction signals.

Not if you want good performance and reliability! Stepper motors require careful control to get reliable performance, and no lost steps or outright stalling. Simple, brute-force approaches will work only at low speed, and low load. Doing it well requires proper acceleration and deceleration ramping, micro-stepping, and low-jitter on the step pulses.

But, hey! What do I know? I've only been using steppers and servos in embedded systems for 15+ years....

Regards, Ray L.

RayLivingston: But, hey! What do I know?

Probably a lot more than the OP (and me).

Do you find it necessary to use an encoder to verify that your stepper motor is not missing steps?

...R PS. How about writing a follow-on tutorial for people that need more advanced advice than my Stepper Motor Basics

Robin2: Do you find it necessary to use an encoder to verify that your stepper motor is not missing steps?

Absolutely not! It is commonly accepted that stepper motors will ALWAYS be subject to "lost steps". But, this is dead wrong. I've owned several fairly high-performance CNC machines using stepper motors, and NEVER "lost a step", except when I grossly over-loaded the motor by running into a hard stop, or something similar.

A properly-designed stepper driven system, operated within its limits, will never lose steps. But you don't get a properly-designed system by guesswork. It takes knowledge, careful selection of components, based on the actual requirements of the system being designed, and testing to ensure the limits of the system are truly understood in detail. Trouble is, many, if not most, hobbyists do not take the time to learn how to properly design a stepper-based system, and end up with a system that is doomed to disappoint. They pick motors based on guesswork, or what they've seen others used in similar applications, or even cost, without ever looking at a torque-speed curve, much less understanding the effects of supply voltage, current limit, micro-stepping, and other critical factors. They read, but don't understand, the motor spec sheet, but see the motor is rated for 5V, so they hook it up to a 5V supply, when it should have perhaps a 45V, or even 75V supply to get maximum performance. They completely ignore the motors inductance, when having low inductance is critical to getting high-speed and high torque.

This is, by far, the best "tutorial" on stepper motors and drivers I've ever seen:

http://homepage.cs.uiowa.edu/~jones/step/

Regards, Ray L.

RayLivingston: Trying to stop when you see the encoder reading you want will NEVER land you on the right position, due to the time it takes to decelerate.

I intuitively thought this. It does stop in my current no load setup but I see how I should not rely on that method.

Have you noticed any missed steps or travel in accuracies with the AccelStepper library?

RayLivingston: [i Simple, brute-force approaches will work only at low speed, and low load. Doing it well requires proper acceleration and deceleration ramping, micro-stepping, and low-jitter on the step pulses.

The motor moves with the AccelStepper library and with me giving it delayed pulses. I assume the above means that you recommend using the library rather than just pulsing the motor driver. Depending on the dip switches the drive can turn my 1.8 deg / 200 rev motor at 400 - 25000 microsteps.

Robin2: More fundamentally, why don't you trust the stepper motor to move the correct number of steps?

It is hard work for an Arduino to read an encoder - especially if the step-rate is high.

I do trust the motor but will not be able to be present to watch or repair the system. It is part of a kinetic exhibit at a museum. I will have a limit switch set for a homing routine but thought that adding an encoder would add an additional level of safety factor.

The Arduino seems to be keeping up with the Encoder but it is a high resolution one with 600 pulses for a resolution of 2400 per rev. Do you recommend taking that complication out of the system?

RayLivingston: Absolutely not! It is commonly accepted that stepper motors will ALWAYS be subject to "lost steps". But, this is dead wrong. I've owned several fairly high-performance CNC machines using stepper motors, and NEVER "lost a step", except when I grossly over-loaded the motor by running into a hard stop, or something similar.

A properly-designed stepper driven system, operated within its limits, will never lose steps. But you don't get a properly-designed system by guesswork. It takes knowledge, careful selection of components, based on the actual requirements of the system being designed, and testing to ensure the limits of the system are truly understood in detail. Trouble is, many, if not most, hobbyists do not take the time to learn how to properly design a stepper-based system, and end up with a system that is doomed to disappoint. They pick motors based on guesswork, or what they've seen others used in similar applications, or even cost, without ever looking at a torque-speed curve, much less understanding the effects of supply voltage, current limit, micro-stepping, and other critical factors.

I fully admit to being a hobbyist, tinkerer, artist. In this case I worked with a motor company to calculate the torque needed, the inertia of all the parts, how much load I was moving. This system had a position feedback system with a motor with ~1900 oz/inch torque. Unfortunately that company could not ship the motor in time for this project so I ordered from another company a motor with double the torque specified by the calculations but without a feedback system.

The motor is a Nema 42 with 4248 oz/inch power.

High Torque Nema 42 Stepper Motor

It uses this driver

Leadshine DM2282 Digital Stepper Driver 80-230 VAC with Max 8.2A

Thank you both for the feedback. I will read the links you provided.

I think I understand how to check the encoder after a movement but I then do not know how to correct if something is wrong.

Your life would be a whole lot easier if you simply used an existing open-source CNC controller, like GRBL, or virtually an 3D printer controller, and simply write G-code to define the motion. You'll put hundreds of hours into creating your own motion controller, and for what benefit? With GRBL, you could have it up and running in hours.

That motor will not be fast, as it has relatively high inductance. May or may not matter in your application. If you've done your calculations correctly, I think the feedback is a waste of time, effort, and money. Simple limit switches will tell you if it ever goes out of expected bounds, in which case you stop, re-home, and start over. Or, simply do a re-home at the end of each full motion cycle. But, if you've designed it properly, it will never mis-behave, unless something breaks.

Regards, Ray L.

Lukinio: I do trust the motor but will not be able to be present to watch or repair the system. It is part of a kinetic exhibit at a museum. I will have a limit switch set for a homing routine but thought that adding an encoder would add an additional level of safety factor.

In my opinion the encoder would only add unnecessary complication that could cause other problems.

Perhaps you can arrange that the normal kinetic motion always triggers an optical switch at some part in the cycle. The Arduino can watch for that and if it does not happen it could go through a re-initializing routine.

The limit / homing switch does not have to be at the end of the travel - it could be anywhere.

...R

RayLivingston: This is, by far, the best "tutorial" on stepper motors and drivers I've ever seen:

I have a copy of that somewhere. It is a bit dense for a beginner - but perhaps it is appropriate once you have got past the simple basics.

...R

RayLivingston: Your life would be a whole lot easier if you simply used an existing open-source CNC controller, like GRBL, or virtually an 3D printer controller, and simply write G-code to define the motion. You'll put hundreds of hours into creating your own motion controller, and for what benefit? With GRBL, you could have it up and running in hours.

Live and learn. This is why I like these forums and the internet. Although I did not learn about GRBL controllers until now and not in time for this project I will look in to using them for the next one.

RayLivingston: That motor will not be fast, as it has relatively high inductance. May or may not matter in your application. If you've done your calculations correctly, I think the feedback is a waste of time, effort, and money. Simple limit switches will tell you if it ever goes out of expected bounds, in which case you stop, re-home, and start over. Or, simply do a re-home at the end of each full motion cycle. But, if you've designed it properly, it will never mis-behave, unless something breaks.

Robin2: In my opinion the encoder would only add unnecessary complication that could cause other problems.

I just ordered a 3d printed part that allows attaching the 6mm encoder to the 19mm shaft of the motor but based on your feedback that part will be saved for another project.

The last think I want is for me to make a mistake attaching the encoder or a "slop" in the encoding to tell the stepper the wrong information. Perhaps I was being too worried. Since I have doubled the touque of the motor and will be going at low speeds I will relay on the steps and the limit switch.

If power goes out I will have the first state on start up be a standby state until a human presses a botton confirming that it is ok to home.

  • Does that seem like a good idea?
  • Can either of you confirm that the AccelStepper library is accurate and that my repeating encoder tests were wrong? The encoder was "spot on" when I manually pulsed the stepper but was off a bit when using the AccelStepper. I am taking the encoder out of the system now.

I have not personally used AccelStepper for anything serious but I have not heard of any problems with it.

It should be easy to test by getting a motor to move an exact number of revolutions. It should be obvious if it is missing steps. If it does miss steps I would suspect a power-supply or driver problem rather than a problem with AccelStepper.

...R

Thanks.

good day
saw that you wanted the same as I want a closed stepper motor itself I do not come from there, I hope you succeeded if yes I will then info or may even thank the code wim