# Optimising driving speed of stepper motor for maximum acceleration by trial and error

I'm writing code for a microcontroller that will ramp up the speed of a stepper motor as quickly as possible, for a jig that I'm building, that moves a workpiece from one position to another along a linear rail.

This question is not about modifying the mechanical or electrical system around the stepper motor, but simply the rate at which the stepper motor is stepped.

Given a desired speed, it will ramp up the speed of a stepper motor (and so the speed of the workpiece) from stationary. (The stepper motor will not have any kind of feedback to the controller other than a switch at each end so it can periodically establish its position, and stop if it's lost/gained too many steps in one direction).

So, I'll need to implement/write a function which gives the optimal speed $s$ (revolutions per second) at time $t$ for maximum acceleration. (Where $s(t=0)=0$) which the microcontroller will use to determine how fast to accelerate the workpiece / stepper motor.

The function might look like this:

$$s = kt$$

Where $k$ is an optimized constant, $t$ is in seconds, $s$ is revolutions per second.

The maximum maximum acceleration will be specified by choosing a value of $k$. It will be determined by experiment rather than calculation.

## What I want to know is:

• One (or more) formulas that I might use. I would then attempt various contants, varying them so I find values that result in good acceleration.
• A strategy for determining those constants.

E.g. using the above formula:

1. start with some value of $k=k_0$
2. Attempt #1: Run the motor with that value of $k$, starting from $t=0$. Record the speed at which the motor failed to accelerate.
3. Attempt #2: Double $k_0$, call it $k_1$. Repeat step 2.
4. Attempt #3: Use half of $k_0$ as $k_{-1}$. Repeat step 2.
5. If $k_1$ gives the highest speed, double it as $k_2$.
6. If $k_{-1}$ gives the highest speed, half it as $k_{-2}$.
7. If $k_0$ gives the highest speed, followed by $k_1$, take the average as $k_{0.5}$
8. If $k_0$ gives the highest speed, followed by $k_{-1}$, take the average as $k_{-0.5}$
9. Repeat step 2.
10. And so on

## Further thoughts

I think the above formula might work well assuming there is the equivalent of a flywheel attached to the motor, and:

• there is zero friction
• the motor exerts constant torque at any speed

Is that correct?

Similarly assuming:

• the motor and system has zero mass / inertia
• the motor exerts constant torque at any speed
• the only resistance to movement is friction

Then the motor can still accelerate to full speed immediately. (So $k$ could be infinite). And if there is inertia, assuming friction forces are constant, (ie independent of speed), assuming I'm correct so far, then the formula is still good; $k$ will just be a lower value.

But that leaves questions:

• What is a typical relationship between stepper motor speed and torque? Clearly it tails off as speed increases, otherwise there would be no limit to its speed. So it clearly won't be taken into account by the above formula. I am investigating this link which goes into much detail, but perhaps there are factors which are more significant than others, or there are more basic models that give good approximations.
• What other factors could be significant that would can not be modeled within the above formula?

One way might be to try to model and understand the physical problem. You are however clear in your question that you would prefer an empirical approach where constants are tuned to experience data.

I would suggest that the easiest and most general way is to use a piece-wise approximation of the velocity curve. Generically this may be made by using basis functions $b_i(t)$ such that the velocity $s$ at any time is given by

$$s(t) = \sum_{i=0}^{N}b_i(t)$$

A simple, and in this case likely sufficient, approach may be to use piese-wise linear velocity (corresponding to constant acceleration over a time interval). That is, divide the time into a finite number of time steps $t_0, t_1, ..., t_N$ and at each such time define a parameter $v_i$ which is the velocity that should be used at that time.

Your algorithm for the engine could then, for example, at any given time $t$ do a bisection search in your $t_i$ array and do linear interpolation between $(t_j, v_j)$ and $(t_{j+1},v_{j+i})$ to calculate the output $s(t)$ at any time.

You are likely to find that you do not need to divide the timeline into more than a few (order of 10 steps and thus order of 10 parameters) pieces in order to achieve a solution that is acceptably close to the optimal. You may also experiment with having non-constant time steps such that for example the time step increase when the time increases and there is less change in the acceleration the system can achieve.

You can also see this sample example for an illustration of how close to an optimal solution it may be possible to get only with a few (10) time steps.

The additional advantage of such an approach is that you can easily tune your velocity in one part of the process without having to adjust the parameters to maintain the response at other times. This leads us to a suggested approach for tuning the parameters:

1. Use a constant acceleration of the entire range ($v_i$ increase linearly) and tune it such that you can reach close to the terminal velocity (see the sample).
2. Tune each $v_i$ parameter individually, that is, first adjust $v_1$ such that you just about can sustain that acceleration in the time interval $[t_0, v_1)$.
3. Next you can do the same process for $v_2$ etc. etc. (and notice that once you have configured $v_i$ you can go on to tune $v_{i+1}$ without ever having to go back and adjust $v_i$
4. You have now constructed a linear approximation of the optimal velocity.
5. If you have areas where there are large changes, or the given velocity is ok in the start of a block but fails in the end you can always refine the "mesh size" in that area by introducing one additional $(t,v)$ pair.

The tuning of each parameter based on experiment may be based on a procedure as you suggest, i.e. doubling the $v_i$ if you encounter no failure, else bisecting between the highest know ok and the lowest known not ok.