# Stepper Motor acceleration profiles for short runs

I've done a fair bit of reading on stepper motors and acceleration. I had to wade through a lot of different strategies with a lot of calculations, including one which called for several candles, and "A maiden of virtue pure" Which while interesting, seemed impractical (Not enough space on the Arduino) Basically they all boil down to this: "Accelerate using some type of ramp, run at speed, then decelerate to stop"

All good. Accelerating will get the load moving, and smooth deceleration will get the load to stop at the (hopefully) correct position.

My issue is this. All of the reading I've done so far seem to have the assumption that the distance to travel will be enough to accommodate all three phases of travel. ie Accel, Coast at speed , Decel. I've not found much discussion on how to handle very short distance situations.

For example, moving only two steps will not, can not possibly have enough distance to go through all three phases. step - step - done. While that particular example seems to be simple enough to solve, what are the best ways of determining if deceleration is required, and if so, when?

At what point do I determine that some sort of deceleration profile will be needed to get the stepper to stop at the required position without overshooting.

So after a whole bunch more looking, and reading and getting confused I decided on the simplest solution.

I stayed with a trapezoidal/triangle profile. Essentially I determined the distance a constant acceleration ramp would use to get to speed. If the acceleration distance was greater than half of the total distance to travel, I accelerate for only half the total travel distance and not worry about getting to max speed. Because I decided to use a symmetrical approach, the decel part took care of itself.

The equations I utilised are essentially the ones posted by Chuck, although the addition of different acceleration and deceleration rates he uses gives me food for thought.

Many, many thanks to all who contributed.

• A motion planner - trajectory planner solves all your questions. – Marko Buršič Sep 11 '18 at 8:40
• You speak of stepper steps as being discrete, remember that you can actually divide them up into infinitely small steps. It's similar to taking a "step" on your bike with pedals. – Harry Svensson Sep 11 '18 at 14:47
• @Marko Buršič I have been trying to find something about motion/trajectory planner that I can understand. Most things that I have found deal with either applications run on external hardware, or are concerned with motions in multiple dimensions (x, y and z axis) I'm trying to work on a single plane. The only thing that I've found which starts on an explanation is a pdf (iopscience.iop.org/article/10.1088/1757-899X/294/1/012055/pdf) But I am having a lot of difficult in following it. Can you point me to some other article? – darrob Sep 12 '18 at 7:34
• @darrob What an excellent article! ++ wiki.linuxcnc.org/cgi-bin/wiki.pl?Simple_Tp_Notes , github.com/LinuxCNC/linuxcnc/blob/master/src/emc/motion/… . Perhaps you can learn something, but you already have a code for Aruino from your's article. – Marko Buršič Sep 12 '18 at 11:00
• Thanks @darrob, note that on stack exchange, it is better to edit your question to add information requested in comments, rather than adding more comments. Comments are for helping to improve questions and answers, and are distracting, so we try to keep them to a minimum. If all of the information needed to answer the question is contained within it, the comments can be tidied up (deleted). – Mark Booth Sep 14 '18 at 12:57

Well, for short runs, it should be obvious that you can skip the coast phase.

As for the others, it's pretty simple. Maintain constant acceleration until you are halfway to the target, then decelerate until you reach the target.

However, there's a catch (there always is, isn't there?). If you have misjudged the distance to the target, and it is closer than you think, then accelerating to your (erroneous) half-way point will mean that you will not be able to stop when you reach the real target point.

You always need a deceleration ramp, or you'll incur a jerk and/or overshoot the target. My company uses acceleration and deceleration times, as in the time it takes to get from 0% to 100%. This is equivalent to an acceleration of

$$a = \frac{\Delta v}{\Delta t} \\$$

where

$$\Delta v = v_{\mbox{max}} \\ \Delta t = \mbox{time to accelerate from 0 to }v_{\mbox{max}} \\$$

Whatever convention you use to define your acceleration and deceleration rates, you should convert to "proper" acceleration rates, length/time^2.

Inline Mathjax (LaTeX) isn't enabled on this site, which is kind of a pain, but I'll use acceleration as a sub-positive and deceleration as a sub-negative, as in:

$$\mbox{Acceleration} = a_+ \\ \mbox{Deceleration} = a_- \\$$

You can use acceleration and top speed to get the time to top speed as:

$$\Delta t = \frac{v_{\mbox{max}}}{a} \\$$

Double integrate acceleration to get displacement:

$$dS = S_0 + v_0\Delta t + (0.5)a\Delta t^2 \\$$

Assuming your starting position is zero and your starting speed is zero, that reduces to:

$$dS = (0.5)a\Delta t^2 \\$$

So you have two distances that you can travel, which aren't necessarily the same - the distance you traverse on acceleration, and then the distance you traverse on deceleration. If the accel/decel rates are the same then the distances are the same, but this seems to be the confounding point for you if they're not.

No worries! You have a time to accelerate to top speed:

$$\Delta t_+ = \frac{v_{\mbox{max}}}{a_+} \\$$

And you have a time to decelerate from top speed:

$$\Delta t_- = \frac{v_{\mbox{max}}}{a_-} \\$$

So you have a distance you traverse on acceleration and a distance you traverse on deceleration:

$$dS_+ = (0.5)a_+\Delta t_+^2 \\ dS_- = (0.5)a_-\Delta t_-^2 \\ dS_{\mbox{total}} = dS_+ + dS_- \\$$

This is your test condition. If your targetDistance is greater than dS (which is the combination of dS+ and dS-) then you will need some coast time at top speed. The coast time is:

$$\mbox{distanceRemaining} = \mbox{targetDistance} - dS \\ \Delta t_{\mbox{coast}} = \frac{v_{\mbox{max}}{\mbox{distanceRemaining}} \\$$

If your targetDistance is LESS than dS, then you need to crop your acceleration and deceleration ramps. This means solving for the new top speed. Working out the dS equation from earlier:

$$dS_{\mbox{total}} = dS_+ + dS_- \\ dS_{\mbox{total}} = (0.5)a_+\Delta t_+^2 + (0.5)a_-\Delta t_-^2 \\ dS_{\mbox{total}} = (0.5)a_+\left(\frac{v_{\mbox{max}}}{a_+}\right)^2 + (0.5)a_-\left(\frac{v_{\mbox{max}}}{a_-}\right)^2 \\$$

Pull out the vMax term:

$$dS_{\mbox{total}} = \left((0.5)a_+\left(\frac{1}{a_+}\right)^2 + (0.5)a_-\left(\frac{1}{a_-}\right)^2\right)\left(v_{\mbox{max}}\right)^2 \\$$

Acceleration terms cancel:

$$dS_{\mbox{total}} = \left((0.5)\left(\frac{1}{a_+}\right) + (0.5)\left(\frac{1}{a_-}\right)\right)\left(v_{\mbox{max}}\right)^2 \\$$

Pull out the 0.5, too:

$$dS_{\mbox{total}} = (0.5)\left(\left(\frac{1}{a_+}\right) + \left(\frac{1}{a_-}\right)\right)\left(v_{\mbox{max}}\right)^2 \\$$

Then clean it up and start solving for vMax:

$$dS_{\mbox{total}} = (0.5)\left(\frac{1}{a_+} + \frac{1}{a_-}\right)\left(v_{\mbox{max}}\right)^2 \\ 2\left(dS_{\mbox{total}}\right) = \left(\frac{1}{a_+} + \frac{1}{a_-}\right)\left(v_{\mbox{max}}\right)^2 \\ 2\left(dS_{\mbox{total}}\right)\frac{1}{\left(\frac{1}{a_+} + \frac{1}{a_-}\right)} = \left(v_{\mbox{max}}\right)^2 \\$$

The acceleration terms can be cleaned up by cleverly multiply by one in the form of a+/a+ or a-/a-:

$$2\left(dS_{\mbox{total}}\right)\frac{1}{\left(\frac{a_-}{a_-a_+} + \frac{a_+}{a_-a_+}\right)} = \left(v_{\mbox{max}}\right)^2 \\$$

Now those fractions add:

$$2\left(dS_{\mbox{total}}\right)\frac{1}{\left(\frac{a_- + a_+}{a_-a_+}\right)} = \left(v_{\mbox{max}}\right)^2 \\$$

So now they can be inverted:

$$2\left(dS_{\mbox{total}}\right)\left(\frac{a_-a_+}{a_- + a_+}\right) = \left(v_{\mbox{max}}\right)^2 \\$$

Which finally leaves:

$$v_{\mbox{max}} = \sqrt{2\left(dS_{\mbox{total}}\right)\left(\frac{a_-a_+}{a_- + a_+}\right)}\\$$

Once you have this, you go back and re-calculate the acceleration and deceleration times (t+ and t-) and that gives you your new speed profile.

Final note/P.S. - Note that if a- is equal to a+ (drop the subscripts and just use 'a') that you get:

$$v_{\mbox{max}} = \sqrt{2\left(dS_{\mbox{total}}\right)\left(\frac{aa}{a + a}\right)}\\ v_{\mbox{max}} = \sqrt{2\left(dS_{\mbox{total}}\right)\left(\frac{a^2}{2a}\right)}\\ v_{\mbox{max}} = \sqrt{2\left(dS_{\mbox{total}}\right)\left(\frac{a}{2}\right)}\\ v_{\mbox{max}} = \sqrt{\left(dS_{\mbox{total}}\right)a}\\$$

I know from great experience that sometimes the hardest part of reading papers is that the authors all seem to believe the math is trivial for a particular step, so they skip sometimes crucial (to us) points in the derivation, or bad authors omit the derivation entirely. For that reason, I've tried to be explicit about every step I've taken, but if I've left something off or you're still confused just let me know.

• @darrob - Glad to help! Again, if there are any points I skipped or something's still unclear, just let me know and I can try to clarify. – Chuck Sep 20 '18 at 0:58

If you want to roll your own it will be something like this.

• If accel == decel then the number of steps for the accel phase is equal to the total number of steps required / 2.
• Accelerate until you reach the target number of steps or until you reach Vmax.
• Note the step count, c.
• Run at Vmax until you reach target - c.
• Start deceleration.
• Stop at target.

If you have accel != decel then you have some additional work to do to work out the ratios.

• The final situation you describe comes closest to the issue that I'm facing. Most, in fact all discussions that I've read (and to be frank, could actually understand) describe situations where there is enough time to accel, coast, decel, even if coast is 0 (ie triangular profile). It's the very small movements that are my concern. Are there situations where it is reasonable to accelerate then just stop? (as in a one or two step movement) and if so, how to determine where that is reasonable – darrob Sep 12 '18 at 7:26
• The danger with a sudden stop is that the inertia of the motor + load causes the motor to break free and overshoot. Your registration is then out until you re-home. You could look at the number of steps required and if low then run at constant speed to target and stop but I think a more generic routine would be better. – Transistor Sep 12 '18 at 7:41
• Ah. It's the generic routine that I am after, hoping that it does cater for very small movements. It does look like I'm going to have to put in a bunch of conditionals based on small step counts. – darrob Sep 12 '18 at 7:55
• No, you shouldn't have to. Write some pseudo code or a flowchart and add it into your question or a new question for review. I had a look yesterday for a sample flowchart but couldn't find one. I've to sit in a hospital for a while today so I may have time to sketch something out. Meanwhile, annals.fih.upt.ro/pdf-full/2013/ANNALS-2013-3-06.pdf. – Transistor Sep 12 '18 at 8:07
• Thanks for the link. It looks like the exact some one I've been struggling through, reformatted. (iopscience.iop.org/article/10.1088/1757-899X/294/1/012055/pdf) I'll think on how to add my concern as a flowchart (which might also clarify my own thinking :) ) In the meantime, I do hope you get over what is keeping you in hospital soon. Cheers... – darrob Sep 12 '18 at 8:13

I gave you links of simple traj. planner from linuxnc.org. It has to be noted that is not in use since it has been superseeded by new and better (more complex) one.

wiki.linuxcnc.org/cgi-bin/wiki.pl?Simple_Tp_Notes

Source code

So, how it works:

At the beginning you set pos_cmd = curr_pos (actual position), the planner does nothing. Then you set a new pos_cmd (setpoint position) and vel_req (setpoint velocity) with constraints: max_acc , max_vel.

The algorithm computes for each step (recursion) the distance to stop regarding the actual velocity, actual position, max_acc.

If the position to stop is equal or bigger than actual distance to stop, then it begins to coast.

Else if the current velocity is smaller than vel_req it ramps up with max_acc ramp.

Else if the current velocity is equal or grater than vel_req, then it moves with constant velocity.

It has to be said that this is pure open loop control, no feedback. The planner generates trapezoidal profile and outputs setpoints for position and velocity and the drive has to follow it. As said it may not stop at exact position, see notes.

P.S: IMO the article you have proposed is more specific fo use for stepper motors, in fact it calculates pulses. The linuxcnc is more generalized approach, but you can have a wider look for your problem. There is no flaw using a planner either for small or large movements, all calculations are limited by phyisical constraints that are input as parameters.

When planning a trapezoidal move profile, if you are not travelling far enough, it devolves into a triangular move. I.e. "accelerate, max velocity, decelerate", becomes "accelerate, decelerate".

I typically calculate cruise distance based on subtracting acceleration & deceleration distances (based on max. acceleration and max. velocity) from the total distance. If this cruise distance is negative, I recalculate acceleration & deceleration distances & velocities based on half the total distance (or the ratio of max acceleration & max deceleration if they are different).

Trapezoidal move profiles are often used because they are simple, and easy to calculate move speed and distance for each waypoint. The problem is, they are not very flexible, as they assume an instantaneous change in acceleration, which as we know is only an approximation to the behaviour of real systems.

Many move controllers have the option of using S-curve motion profiles. You start off by ramping up acceleration at the start of the acceleration phase, and ramping it down at the end, doing the same agasn at the start and end of the deceleration phase.

While it might seem logical that the fastest move you can do would involve accelerating at the highest rate possible, then decelerating at the highest rate possible, that may not always be the case. Reducing jolt (jerk) on a move by starting with a lower initial acceleration can enable you to maintain a higher peak acceleration for longer, resulting in a higher overall acceleration, all at the expense of more complex trajectory planning calculations.

This is especially a problem with stepper motors without encoders. Stepper motors suffer from the problem that if you demand they do something they can only just manage, their behaviour is unpredictable. Push your stepper motor just a little too hard and it will miss steps. If you don't have an encoder to detect these missed steps and correct for them (in your servo loop) then you will have to down-rate your max. acceleration parameter to the point that it can cope with all potential situations.

In general, you want to try to avoid discontinuities in control, so control algorithms should, much like the motors they control, transition smoothly between different modes of operation.

• I've got the motion for travelling using trapezoidal/triangle profile working okay. For the smaller movements I do also re-calculate by halving the distance. But is still comes down to this: At what point is there no need to calculate a deceleration phase? – darrob Sep 12 '18 at 7:43
• When the total move time/distance is smaller than a single waypoint then effectively you have no planning, you just have a single 'jump' move. In that case you are more relying on the tuning parameters of your servo loop than any explicit move planning. – Mark Booth Sep 12 '18 at 14:27
• Yeah, it's the 'servo loop' that I'm trying to tune for the exceptional situations. In my case, it is a very simple task, needing only to move a trolly in one of two directions. There are three (well six, including direction) possibilities. Move to a distant point at max speed, move to a distant point in low speed or move a minute distance at any speed. And when I say minute, I'm talking anywhere between 1 to 50 steps (equates to 0.00125 to 0.0625mm). This is where the accel/decel headache is coming in :) – darrob Sep 12 '18 at 15:32
• Thanks for the info about vote button. My reputation isn't high enough to record the scores – darrob Sep 12 '18 at 15:33
• Generally speaking @darrob you shouldn't be tuning your servo loop for specific moves, you should be tuning your servo loop for best overall response and then using your planning loop to get the most out of the tuned system. I've seen systems try to change PID parameters for different types of moves and it never ends well. You may want to look at using cubic splines (), and planning moves with fixed distance with variable time rather than traditional fixed time (period) with variable distance. This would turn the fixed step size into an asset rather than a restriction. – Mark Booth Sep 14 '18 at 11:07