Stepper Motor Not Working with Encoder Code

Hello! I'm moving a stepper motor to a set position as read by and encoder I've installed. If everything works as it should, the stepper motor will move until the encoder reached that degree. (There is a magnet attached to the part of the motor that's moving). I can confirm that everything is wired up correctly, as they each work with their individual isolated code. However, I've found when I add this one line of code, "currentPosition = encoder.getScaledAngle", my stepper motor will not move. The AS5600 encoder library I am using is here: [AS5600] (AS5600/examples at master · kanestoboi/AS5600 · GitHub) and the library I'm using for the stepper motor is the Accelstepper library. My guess is that when it calls that function it takes too long, messing with the stepper pulses? But I'm not too sure. Please let me know what you think. I've posted the combined code below.

#include <AS5600.h>
#include <AccelStepper.h>   
AS5600 encoder;   
int speed;    
int requestedPosition = 180;
float currentPosition;   
float positionDiff;   
AccelStepper stepper(1, 18, 19);   // (Type:driver(1 is default driver), STEP, DIR)   

void setup() {   
  Serial.begin(9600);   
  stepper.setMaxSpeed(2000);   

}   
void loop() {   
  // get the angle in degrees of the encoder   
  currentPosition = encoder.getScaledAngle();  //the line that stops the stepper when added
  currentPosition -= 95;   //zeroing encoder
  if (currentPosition < 0) {   
    currentPosition += 360;   
  }   
  speed = -1500;   
  stepper.setSpeed(speed); //steps per second   

  positionDiff = currentPosition - requestedPosition;  //check rotation
  if (positionDiff < 0) {   
    speed *= -1;
  }  

  if (currentPosition > (requestedPosition + .5) && currentPosition < (requestedPosition - .5)) { //set tollerance & check if arrived
    speed = 0;
  }
  stepper.runSpeed();
  //Serial.println(currentPosition);  //testing purposes. Was not part of the code when run
}   

Thank you!

Did you try to output encoder.getScaledAngle values to Serial just after reading it? please show the output

Yes, when I’m printing to Serial the encoder functions as it should, telling me the motor’s rotation. The motor just won’t move to it

A stepper-motor does not essentially need an encoder as long as you rotate the stepper-motor under suitable conditions (which means the torque-load is lesser than the maximun-torque the stepper-motor can deliver.
Then each step of the stepmotor relates to a certain angle.

The only thing really needed is a reference-point to find a defined position.
If the defined position is detected each step clockwise or counterclockwise is in a fixed relation to this reference-point and can be exactly calculated without any measurings.

Most stepper-motors have 200 full-steps per revolution = 1.8 degree per step.
Most stepper-motors are used in halfstep-mode 400 steps per revolution = 0.9 degree per halfstep
some are used in microstepping degree per step = 360 degree / (fullsteps_per_rev * microstepping-factor)

the functions of AccelStepper are either blocking you can do nothing else until target is reached or you are forced to do repeated functions-calls like runspeed() at a higher frequency as each step-pulse must be created.

If you want to do other things in parallel this limits the maximum step-pulse-frequency down to how long it takes to execute the other things.

The MobaTools-library has a different approach to create the step-pulses.
With this approach you can achieve pretty high step-pulse-frequency and still beeing able to do other things in parallel

best regards Stefan

1 Like

Thanks for your reply. I know you are able to run steppers without an encoder but I wanted to have one anyway in case of skipping steps and just ease of programming. (Between you and I, I’m not the best programmer haha.) But it seems that’s what I’ll have to do

Thanks

the manufacturer trinamic has stepper-motor-drivers that drive the stepper-motor on very low noise-level and that have inbuild stall-detection.

It is the TMC-series
TMC2208, TMC2209, etc.

Depending on your budget you might consider using a servo-motor who has inbuild encoders
JMC has a good quality price ratio

To anyone who may read this I found the solution. Turns out it was just the limit of the microcontroller. I fixed this problem using a blink without delay concept so it would only read inputs from the encoder ever 75ms instead of its normal speed (very fast). This allowed the microcontroller to have the processing available to produce the correct step pulses.

Something like this?

#include <AS5600.h>  // https://github.com/kanestoboi/AS5600
#include <AccelStepper.h>   
AS5600 encoder;   
int speed;    
int requestedPosition = 180;
float currentPosition;   
float positionDiff;   
AccelStepper stepper(1, 18, 19);   // (Type:driver(1 is default driver), STEP, DIR)   

void setup() {   
  Serial.begin(9600);   
  stepper.setMaxSpeed(2000);   

}   
void loop() {   
  static uint32_t last;
  if(millis() - last >= 75){
    last = millis();
    // get the angle in degrees of the encoder   
    currentPosition = encoder.getScaledAngle();  //the line that stops the stepper when added
    currentPosition -= 95;   //zeroing encoder
    if (currentPosition < 0) {   
      currentPosition += 360;   
    }   
    speed = -1500;   
    stepper.setSpeed(speed); //steps per second   

    positionDiff = currentPosition - requestedPosition;  
    //check rotation
    if (positionDiff < 0) {   
      speed *= -1;
    }  

    if (currentPosition > (requestedPosition + .5) && currentPosition < (requestedPosition - .5)) { //set tollerance & check if arrived
      speed = 0;
    }
  }
  stepper.runSpeed();
  //Serial.println(currentPosition);  //testing purposes. Was not part of the code when run
}

Yes however I actually found a even better solution. The problem with that one was that it would overstep since it has to wait until reading the position. If you use two microcontrollers, have one read positions and one move steppers it works better. You can connect the two via GPIOs and say “when at position > write gpio to other microcontroller high” “when GPIO on other microcontroller high > stop motors.” And etc based on the functions you need it to move. Feel free to check out my Instagram RoboticWorx to see it in action. I just wrote a mimic me robotic arm algorithm based entirely on the concept I just described

1 Like

Hmm. I'd have figured that the next step would be to use AccelStepper's move commands.

Hi I am having an issue with my own steppers. They work when in an individual code but when I add them to a larger code its as if the fucntion ignores the motor code. What exactly do you mean by the limit of the microcontroller ? If you need any more information I will be glad to send it on. Thanks

I think the problem with mine was the encoder data was being prioritized by the microcontroller. I have my driver on 1600 micro steps (1600 pulses = 1 step) driving multiple steppers which took a lot of processing. I think the microcontroller was having a problem with driving the steppers while constantly reading the encoder data (that’s a lot of processing). You can likely improve performance by making sure the serial isn’t printing, reducing processing demands, upgrading your microcontroller (ESP32-S3 rocks!), or just double checking your programming and making sure you have all the included functions. (Make sure you didn’t accidentally put a necessary function in a if statement or something.)

@c00255094

you should open your own thread.
What you did here is hijacking another users thread.

You can read what more information is needed here

best regards Stefan

If you really need that precision I would change to servomotors. On a servomotor the inbuild controller will do all the details of reading the encoder
JMC has servomotors with a good price to perfomance ration
best regards Stefan

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.