Skip to content

Trapezodial velocity profile for a stepper motor

Math behind it

Discrete stepping and acceleration

When using a stepper motor, we want to avoid running it immediately at full speed especially if a mass is attached to the motor since it is quite likely to induce miss-stepping. In our case, we use a stepper attached to a lead screw forming a linear stage. The stage now performs a linear motion over a total distance defined as Δs. This distance can be defined through a certain number of discrete steps ns each having a step length ss defined through the number of steps per revolution nr=400stepsrev and the pitch of the lead screw p=8mmrev:

ss=pnr,Δs=ssns

In the ideal case we would like to follow a linear increase in velocity followed by a constant plateau of maximum movement velocity vm followed by a decrease in velocity. In case of the iterative routine in which we step the motor, it makes most sense to have a formula reversely telling us which velocity we want to drive for the upcoming step is which has the center position s:

s=(is+0.5)ss,is[0,ns1]

The velocity of a stepper motor is thereby translated into the delay time td before the next discrete step occurs:

td=ssv

Linear acceleration phase

In the acceleration phase, our linearly accelerated velocity profile is described as:

s=12at2

with the velocity v being defined as:

v=at

Solving this equation for v(s) leads to:

v=2sa

Constant velocity phase

In this case we just have the velocity at a constant level vm.

Linear deceleration phase

For the deceleration phase, we have the following description of the velocity profile:

v=vma(tt2)$

or solved after (tt2)

tt2=vmva

with its distance counterpart

s=s2+vm(tt2)12a(tt2)2

or

s=s2vmvmva+(vmv)22a0=12a(vmv)2+vma(vmv)+(ss2)

Solving the quadratic equation through

x1,2=b±b24ac2a

leads to

(vmv)1,2=vma±vm2a22a(ss2)1a(vmv)1,2=vm±vm22a(ss2)v=vm22a(ss2)

Case switch

In practice we now need to find the thresholds for the three phases. s1 is defined as the position where full speed is reached, s2 is the position where we start decelerating.

We can extract the first distance as

s1=vm22a

and the second one as

s2=Δss1

If s1 becomes larger then s2 it means that full velocity will not be reached due to a short travel length or low acceleration. In this case we set s1=s2=Δs/2 and redefine vm:

vm=Δsa

Microcontroller implementation (Teensy)

C
// define before
// ss [float] --> step size in mm
// vmax [float] --> maximum desired linear velocity in mm / s
// acc [float] --> acceleration in mm/(s*s)
// deltaS [float] --> distance to travel
// fallAndRise [bool] --> true if rising and falling edge lead to stepping, otherwise false

uint32_t absSteps = round(abs(deltaS) / ss); // number of steps we need to do

// define end point of acceleration and start point of deceleration
float s_1 = vmax * vmax / (2 * acc);
float s_2 = deltaS - s_1;

if (s_1 > s_2) // if we don't even reach full speed
{
    s_1 = deltaS / 2;
    s_2 = deltaS / 2;
    vmax = sqrt(deltaS * acc);
}

float vcurr = 0;
bool stepPolarity = 0;
for (int32_t incStep = 0; incStep < absSteps; incStep++)
{
    // calculate central position of current step
    const float s = ((float) incStep + 0.5) * ss;

    // calculate velocity at current step
    if (s < s_1)
    {
	vcurr = sqrt(2 * s * acc);
    }
    else if (s < s_2)
    {
	vcurr = vmax;
    }
    else
    {
	vcurr = sqrt(vmax * vmax - 2 * (s - s_2) * acc);
    }

    // convert velocity to delay
    const uint32_t tDelay = round(ss / vcurr * 1e6); // in micros

    if (fallAndRise) {
        stepPolarity = !stepPolarity;
        digitalWriteFast(pinStep, stepPolarity);
        delayMicroseconds(tDelay);
    } else {
        digitalWriteFast(pinStep, HIGH);
        delayMicroseconds(tDelay / 2.0);
        digitalWriteFast(pinStep, LOW);
        delayMicroseconds(tDelay / 2.0);
    }
}

Created by Urs Hofmann