Real-time stepper motor control algorithm - Page 1
Forum section: electronics / projects

author: ZachR
author_rank: Newbie
timestamp: December 24, 2017, 08:06:33 pm
content: I'm looking for pointers or ideas for what seems like a simple control system, but is turning out to be a little tricky (or I'm just being obtuse).Here's my setup...I have an absolute rotary encoder that spits out it's position at a fixed frequency. A relatively low end mircocontroller (yeah integer math) is connected to this encoder and is also connected to a stepper motor through a standard step+direction driver. The goal of the system is to have the stepper motor's shaft smoothly mirror the motion of the encoder. Should be easy, right? The encoder moves 10 clicks, move the motor 10 clicks. That kind of works, but in reality, it fails in a couple key areas. Without closed loop velocity control, slow encoder moves equate to choppy motor movements. Very rapid encoder accelerations or decelerations cause the stepper to loose steps, e.g. it needs proper acceleration ramping. Since I'm pretty familiar with steppers drives, these failures are not really surprising, but the surprising thing is that I can't seem to find a "standard" solution to this problem. I've done a fair bit of googling, and either the algorithms are buried into an expensive piece of hardware (with little explanation how they work) or the algorithms don't really support real-time position updates. I've found some algorithms in old EETimes articles, AVR446, etc. but they assume that each movement is discrete, knowing how far the motor will travel before it even starts. This works fine for a CNC controller, but not for real-time position tracking.Before I start writing my own nested velocity matching, integer-approximated linear ramped acceleration, position control system, I figured I'd post to see if anyone knows of something like this already out in the wild.Thanks!

author: Rerouter
author_rank: Super Contributor
timestamp: December 24, 2017, 08:40:06 pm
content: For 3d printers, i know there have been a number of people that have worked on closed loop stepper motors.One thing you will come across is 10 points on your encoder likely is not enough, almost every stepper controller in exustance uses microstepping to smooth out the motion on small steps. However you need feedback to integrate up a kick if your systems friction is too high for a single microstep.The other one that hurts is that a stepper motor generally does not have evenly sized steps. Depending on the precision you need you may come across instead of a 36 degree step for your steppers, it may be a mix of 34-38 degrees.

author: ZachR
author_rank: Newbie
timestamp: December 24, 2017, 08:53:38 pm
content: Hi Rerouter - Thanks for the reply. I simplified some of the details of my project for simplicity. I'm actually using a Trinamic driver, TMC2130 and will likely crank it up to 256 microsteps, so the actual resolution isn't an issue. Required torque is also very minimal, so I have it easier there. It's mainly just getting a control loop to run smoothly under the variety of different and changing input conditions with an MCU that has limited resources.

author: Pack34
author_rank: Frequent Contributor
timestamp: December 24, 2017, 08:55:03 pm
content: How frequently do you recieve position feedback? Does the stepper motor controller do anything else besides read the encoder and update the position?Couldn't you determine the amount of ticks and simply alter the PWM frequency going to the stepper motor driver? Or do the same by bit banging?

author: ZachR
author_rank: Newbie
timestamp: December 24, 2017, 09:24:28 pm
content: Hi Pack34, Thanks for the question/suggestions.The position updates come in at around 60Hz and the output stepping frequency could be as fast as 50KHz with microstepping enabled. The MCU juggles several functions in addition to generating stepper pulses, hence the desire for an optimized algorithm.To keep impulse current levels below the motor driver limits (when overcoming inertia), we must use acceleration ramping e.g. instant acceleration = lost steps. As far as I can tell, this ramping takes some non-trivial math especially when you mix in the ability to dynamically update both the target position and velocity.

author: Someone
author_rank: Super Contributor
timestamp: December 24, 2017, 09:38:23 pm
content: Quote from: ZachR on December 24, 2017, 08:53:38 pmThen you wouldn't be saying this:Quote from: ZachR on December 24, 2017, 09:24:28 pmCheapest solution will be to oversize the motor until you can do it without higher order control. Putting appropriate control loops into a specific target takes a few weeks of work so its not surprising you cant find any open source examples. Rather than trying to get perfect s-curves you can just wrap a few standard controls in cascade with appropriate anti-wind up and let the motor overshoot and settle back to the demanded location, it'll still be fast enough for most applications where you are following another shaft.

author: Pack34
author_rank: Frequent Contributor
timestamp: December 24, 2017, 09:42:23 pm
content: Quote from: ZachR on December 24, 2017, 09:24:28 pmRamping up and down with a stepper motor assembly isn't bad. I've done some larger scale solutions with this.If there's any weight on the thing that you're moving, I would recommend having some feedback on it. Then when the 60Hz position update occurs you can calculate your error and velocity between the control and the apparatus and then apply the position correction using a PWM on the STEP input to the driver.You're movement control should be on an independent state machine. Meaning that you independently calculate your position error and in a separate state machine do your ramps and movement routines.Since you're moving a physical thing with some weight to it, you may not want to attempt to update the stepper motor pulse train at the same interval. Your unlikely to get a mechanical response that fast. I would stagger. You have your updates that fast and then in between every other position update you do a correction to the motor control pulse train. This will also help ensure that you don't have any timer collision that could cause a motor update to occur while you're attempting to read from a sensor.

author: Pack34
author_rank: Frequent Contributor
timestamp: December 24, 2017, 09:45:23 pm
content: Quote from: Someone on December 24, 2017, 09:38:23 pmAlso using the highest voltage you can get away with. When microstepping your available torque drops exponentially. Increasing your stepper motor voltage can help mitigate this. I've always run mine at 24V minimum. Even when using light loads so that I'm positive that the mechanical action happens and it holds properly.

author: ajb
author_rank: Super Contributor
timestamp: December 24, 2017, 09:49:44 pm
content: Similar to an application I had recently, the challenge is that most stepper movement algorithms that are out there assume that the input is a single "move to X" command that can be completed atomically. I was hoping to find an off-the-shelf control solution for my application, but didn't find one that permitted the target position to be updated on the fly, which is basically what you're after.A simple approach with constant acceleration (no anti-jerk) is fairly straightforward, and can be accomplished by proportional control of the step rate (the velocity is proportional to the error). You will still need to limit the acceleration rate in response to large step changes in target position, limit the maximum step rate to whatever suits your mechanics, and it may not be a bad idea to include a bit of low pass filtering to avoid jitter, but it's pretty easy as control loops go. One challenge comes when the target position changes to be behind what the deceleration curve can hit, the motor will have to overshoot the target and then smoothly reverse.A slightly more complex system incorporating basic anti-jerk can be accomplished by limiting the rate at which you change the velocity. At this point the integral/derivative relationships between position, velocity, acceleration and jerk start to become quite clear. You could consider that a proportional response to position error gives you a target velocity, a proportional response to velocity error gives you a target acceleration, and a constant increment/decrement of your acceleration rate until the acceleration error is zero will make your position an s-curve. You will of course still need to cap the target values to reasonable levels, but I think that will give you a reasonably smooth and performant system and without any crazy math or logic. The loops can be implemented one at a time fairly easily, so you can try the simple constant acceleration method first and add the other layers later if needed.Edit: another advantage of this technique is that its internal state consists solely of the current position, velocity, and acceleration, so it can be recomputed every cycle even across wide changes in target position very easily versus techniques that consider acceleration, cruise, and deceleration as separate phases of operation.

author: ZachR
author_rank: Newbie
timestamp: December 24, 2017, 10:05:06 pm
content: Someone - Haha yes, I can see how my responses seem contradictory. I guess what I was trying to convey was that even with my low torque requirement, I need some ramping. I'm certainly not looking for perfect s-curves and agree that coming up with this from scratch could be weeks of work, but that's exactly why I though I would ask you smart people before I dove in and rolled my own.Pack34 - I'm using a 24v system.Ajb - Sounds like an off-the-shelf solution may just not be in the cards. Thanks for the advise on the nested PIDs (or almost just Ps)!

author: miceuz
author_rank: Frequent Contributor
timestamp: December 25, 2017, 01:26:22 pm
content: I am not entirely sure if I get your problem clear, but maybe this can help.I have had somewhat similar task in the 4-tonn line follower project we hacked last spring - we were using a huge stepper motor to turn the wheel, it's set angle position was provided by an external control algorithm. We had to follow ramping to avoid missing steps. We were fortunate to have a feedback from wheel position to calibrate by putting the wheel to center from time to time.I have used this stepper library:http://www.airspayce.com/mikem/arduino/AccelStepper/You can have a look at this file to get the idea how I am using it:https://github.com/Technariumas/smalsiukas/blob/master/smalsiukas/steering.hAlso this project has a demo doing exactly the thing you are interested in I think:http://tropical-labs.com/index.php/mechaduino

author: David Hess
author_rank: Super Contributor
timestamp: December 25, 2017, 06:23:43 pm
content: Quote from: ZachR on December 24, 2017, 08:06:33 pmThat makes sense because knowing the destination ahead of time is necessary to know when acceleration has to reverse at the middle of a movement. If the movement was shortened after this point and a higher acceleration was not used, then it would overshoot.It is a fascinating problem. The standard motion control algorithm could be used to complete every motion living with the overshoot but it would be annoying when continuously turning the encoder because of the starts and stops. Writing your own implementation which follows the destination with acceleration and slew rate limiting seems like the best solution. I might use a lower acceleration for normal movements and higher acceleration for when the destination moves closer after deceleration has already started to prevent overshoot.

author: rstofer
author_rank: Super Contributor
timestamp: December 25, 2017, 11:35:27 pm
content: First of all, you might want to research S curve acceleration.http://www.ni.com/product-documentation/4824/en/There is another concept used in the early days of numerical control (and may still be used) called following error. There was no tight coupling between the math unit that generated the steps and the servo valve controller. Rather, counts were added to an accumulator and the valve was controlled by the absolute value of the contents of the accumulator. When the motion started up, the accumulator contained zero so the machine wasn't moving. As counts were added, the machine started to move and the position controller removed counts as it measured the motion. This guaranteed a slow ramp up to speed and a slow ramp down to stop. Slow being a relative term when you're moving a cross-arm that weighs tens of tons. The following error was essentially the contents of the accumulator - increments of motion yet to occur.http://digital.ni.com/public.nsf/allkb/899AE29CB4E3578B8625709D0070A725Given the slow position update rate, I don't see this control working out. How can the motor possibly step much faster than the feedback and not be jerky.

author: ZachR
author_rank: Newbie
timestamp: December 26, 2017, 05:27:14 pm
content: Hi Miceuz - On your suggestion, I dug out an Arduino and tried out AccelStepper. Within 5 minutes I had a working example. It does almost exactly what I need right out of the box!!! Thank you! Their code uses several floats in the "computeNewSpeed" function (not ideal for my application), but since they are using the David Austin's Taylor series approximation for the acceleration equations, I think I can convert it to using integers using the techniques in the aforementioned AVR446 app note.