Share this

Stepper Motor S-curve Acceleration and Deceleration Algorithm and Implementation

2026-04-06 05:20:41 · · #1

A stepper motor is an open-loop controlled motor that converts electrical pulse signals into angular or linear displacement. It is a primary actuator in modern digital program control systems and has extremely wide applications. Under non-overload conditions, the motor's speed and stopping position depend only on the frequency and number of pulse signals, and are unaffected by load changes. When the stepper driver receives a pulse signal, it drives the stepper motor to rotate a fixed angle in a set direction, called the "step angle." Its rotation occurs step by step at fixed angles. The angular displacement can be controlled by controlling the number of pulses, thus achieving accurate positioning; simultaneously, the motor's speed and acceleration can be controlled by controlling the pulse frequency, thus achieving speed regulation.

A stepper motor is a type of induction motor . Its working principle is to use electronic circuits to convert direct current into multi-phase timing control current that is supplied in a time-sharing manner. Only when this current is used to power the stepper motor can it work normally. The driver is a multi-phase timing controller that supplies power to the stepper motor in a time-sharing manner.

Stepper Motor S-curve Acceleration and Deceleration Algorithm and Implementation

Equation of the S-curve

The graph in the range [-5, 5] is shown in the figure below:

To apply this curve to the acceleration and deceleration process of a stepper motor, the equation needs to be translated in the XY coordinate system, and the curve needs to be stretched:

The A component is translated in the y direction, the B component is stretched in the y direction, and the ax+b component is translated and stretched in the x direction.

The acceleration process in the project involved speeding up from 5600Hz to 64000Hz using 4-step subdivision. The timer drive frequency used in the output comparator module was 10MHz, and 1000 points were used for acceleration processing. Ultimately, based on the project requirements, the curve equation used during the acceleration process was as follows:

.

Fcurrent represents a single frequency value among 1000 points. Fmin is the initial frequency of 5600; Fmax is the maximum frequency of 64000; -flexible*(i-num)/num stretches the S-curve, where flexible represents the S-curve range (the larger the value, the greater the compression, with greater acceleration in the middle (around x-coordinate 0); the smaller the value, the closer to uniform acceleration. The ideal S-curve value is 4-6), i is the index in the loop calculation process, starting from 0, and num is length/2 (this makes the S-curve symmetrical). In the project, i is in the range [0, 1000), and num = 1000/2 = 500. These parameters can all be modified. The provided calculation interface is as follows.

Corresponding computation interface code:

/*calculatethePeriodandFreqarrayvalue, fillthePeriodvalueintothePeriodregisterduringtheTImerinterrupt.

*calculatetheacceleraTIonprocedure,atotally1000elementsarray.

*parameterfre[]:pointtothearraythatkeepsthefreqvalue.

*period[]:pointtothearraythatkeepstheTImerperiodvalue.

*len:theprocedureofacceleraTIonlength.itisbestthingtosetthefloatnumber,somecompilesoftwaremaybetransfererrorifsetitasaint

*fre_max: maximumspeed, frequencyvale.

*fre_min: startminimumspeed, frequencyvale.mind: 10000000/65535=152, sofre_mincan'tlessthan152.

*flexible: flexiblevalue.adjusttheScurves

/

voidCalculateSModelLine(floatfre[], unsignedshortperiod[], floatlen, floatfre_max, floatfre_min, floatflexible)

{

inti=0;

floatdeno;

floatmelo;

floatdelt = fre_max - fre_min;

for (i < len; i++)

{

melo=flexible*(i-len/2)/(len/2);

deno=1.0/(1+expf(-melo));//expfisalibraryfunctionofexponential(e)

fre[i]=delt*deno+fre_min;

period[i]=(unsignedshort)(10000000.0/fre[i]);//10000000isthetimerdriverfrequency

}

return;

}

//startmovemotor

voidStartPWM()

{

DriverMotorFlag=TRUE;

Index=0;

MOTOR_EN_DISABLE=ENABLE;

OpenOC4(OC_ON|OC_TIMER_MODE16|OC_TIMER3_SRC|OC_PWM_FAULT_PIN_DISABLE, 0, 0);

//maprc13tooc4output

RPC13R=11;

//50percentduty

OC4RS = OC_PERIOD_MIN / 2;

OpenTimer3(T3_ON|T3_PS_1_8, OC_PERIOD_MIN);

INTSetVectorPriority(INT_TIMER_3_VECTOR, INT_PRIORITY_LEVEL_6);

INTSetVectorSubPriority(INT_TIMER_3_VECTOR, INT_SUB_PRIORITY_LEVEL_1);

EnableIntT3;

}

//stopmotor, hereisnodeceleration

voidStopPWM()

{

DriverMotorFlag=FALSE;

Index=0;

MOTOR_EN_DISABLE=DISENABLE;

OpenOC4(OC_OFF|OC_TIMER_MODE16|OC_TIMER3_SRC|OC_PWM_FAULT_PIN_DISABLE, 0, 0);

//maprc13tooc4output

RPC13R=0;

PORTCbits.RC13=0;

CloseTimer3();

DisableIntT3;

}

//changethetimerPeriodvalueinthecorrespondtimerratherthantheotherplace,Orthemotorwillbestalledoccasionally.

Initially, I changed the Period value of timer3 in the OC module every 1ms in another timer interrupt, which occasionally caused the motor to stall during acceleration. The modification should actually be done in the timer3 interrupt.

staticunsignedshortCountForAcc=0;

void__ISR(_TIMER_3_VECTOR, ipl6) Timer3OutHandler(void)

{

//cleartheinterruptflag,ortheinterruptwillnotoccuragain.

mT3ClearIntFlag();

if(CountForAcc++》2)//herecanadjustthetotallytimeofacceleration

{

CountForAcc=0;

//if(DriverMotorFlag==TRUE&&PR3》OC_PERIOD_MAX+SPEED_STEP)

if(DriverMotorFlag==TRUE&&Index《ACC_TIMES)

{

PR3 = Period [Index++];

OC4RS=PR3/2;

}

}

}

The following different acceleration curves are obtained through the CalculateSModelLine interface:

Yellow: CalculateSModelLine(Freq, Period, 1000, 56000, 16000, 4);

Orange: CalculateSModelLine(Freq, Period, 1000, 64000, 500, 8);

Blue: CalculateSModelLine(Freq, Period, 1000, 64000, 500, 15);

Gray: CalculateSModelLine(Freq, Period, 1000, 40000, 500, 5);

Finally, the acceleration process time and angular displacement can be estimated. Taking the orange curve as an example: CalculateSModelLine(Freq, Period, 1000, 64000, 500, 8) (assuming there is no if (CountForAcc++>2) condition in the interrupt):

Time: The value of the first point in Period is 10,000,000/500=20,000, and the value of the last point is 10,000,000/64,000=156. The average value is about 10,000. The average time of the timer interrupt is Tn=10,000/10,000,000=1ms. For 1,000 points, the total time is 1 second. Of course, the higher the starting frequency, the shorter the acceleration time. For example, if Fmin=16,000Hz and Fmax=64,000, the acceleration process can be completed in about 40ms.

Angular displacement: 1.8 (single step) * 1000 (steps) / 4 (sub-steps) = 450°

The above describes the acceleration process; the deceleration process follows the same principle, simply by changing the equation to:

The deceleration curve can be obtained as shown below:

Read next

Application Research of Variable Frequency Coordinated Control Technology in Primary Air Systems

Abstract: This paper focuses on the application of variable frequency coordinated control technology in the retrofitting...

Articles 2026-02-22