News center

新闻中心

步进电机S曲线加减速算法及实现

2021-03-25  浏览次数:9671

步进电机是将电脉冲信号转换成角位移或线位移的开环控制电机。它是现代数字程控系统的主要执行部件,应用广泛。在非过载情况下,电机的转速和停止位置只取决于脉冲信号的频率和脉冲数,不受负载变化的影响。步进驱动器接收到脉冲信号后,驱动步进电机在设定的方向旋转一个固定的角度,称为“步角”,其旋转以固定的角度步进运行。角位移可以通过控制脉冲数来控制,从而达到精确定位的目的;同时,可以通过控制脉冲频率来控制电机的速度和加速度,从而达到调速的目的。

步进电机是感应电机的一种。其工作原理是利用电子电路将直流电转换成分时供电和多相定时控制电流。只有用这个电流给步进电机供电,步进电机才能正常工作。驱动器是一个多相定时控制器,分时向步进电机供电。

  步进电机S型曲线加减速算法与实现

s型曲线方程

,在[-5,5]图形中如下图所示:

如果想把这条曲线应用到步进电机的加减速过程中,需要在XY坐标系中平移方程,同时拉起曲线:

其中a分量在y方向平移,b分量在y方向拉伸,ax b分量在x方向平移拉伸。

项目中的加速过程:从5600Hz加速到64000Hz,采用4细分。输出比较模块中使用的定时器驱动频率为10M,1000点用于加速处理。后,根据项目需要,加速过程中采用的曲线方程为:

其中Fcurrent是长度为(1000)点的单个频率值。Fmin启动频率为5600;Fmax为频率64000;-flexible*(i-num)/num为S形曲线的拉伸变化,其中flexible表示S形曲线的区间(越大压缩越剧烈,中间加速度越大(X坐标0点附近);越小越接近匀加速。理想S曲线的值是4-6),I是循环计算过程中的指标,num是从0开始的长度/2(可以使S曲线对称)。在项目中I的区间[0,1000]内,num=1000/2=500。这些参数可以修改。提供的计算接口如下。

相应计算接口的代码:

/*计算周期和频率阵列值,在定时器中断期间将周期值填入周期寄存器。

*计算acceleraTIon过程,总共1000个元素的数组。

*参数fre[]:指向保存freq值的数组。

* period[]:指向保存TImer period值的数组。

* len:加速长度的程序,好设置浮点数,有些编译软件可能会转移

error if set it as a int

  * fre_max: maximum speed, frequency vale.

  * fre_min: start minimum speed, frequency vale. mind : 10000000/65535 = 152, so fre_min can‘t less than 152.

  * flexible: flexible value. adjust the S curves

  void CalculateSModelLine(float fre[], unsigned short period[], float len, float fre_max, float fre_min, float flexible)

  int i=0;

  float deno ;

  float melo ;

  float delt = fre_max-fre_min;

  for(; i《len; i++)

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

  deno = 1.0 / (1 + expf(-melo)); //expf is a library function of exponential(e)

  fre[i] = delt * deno + fre_min;

  period[i] = (unsigned short)(10000000.0 / fre[i]); // 10000000 is the timer driver frequency

  return ;

  // start move motor

  void StartPWM()

  DriverMotorFlag = TRUE;

  Index = 0;

  MOTOR_EN_DISABLE = ENABLE;

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

  // map rc13 to oc4 output

  RPC13R = 11;

  // 50 percent duty

  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;

  //stop motor, hereis no deceleration

  void StopPWM()

  DriverMotorFlag = FALSE;

  Index = 0;

  MOTOR_EN_DISABLE = DISENABLE;

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

  // map rc13 to oc4 output

  RPC13R = 0;

  PORTCbits.RC13 = 0;

  CloseTimer3();

  DisableIntT3;

  //change the timer Period value in the correspond timer rather than the other place, Or the motor will be stalled occasionally.

  // 刚开始我在另外的一个定时器中断中每隔1ms改变 应用在OC模块的timer3 的Period值,结构偶发的造成电机在加速过程中堵转。其实应该是在timer3的中断中修改。

  static unsigned short CountForAcc = 0;

  void __ISR(_TIMER_3_VECTOR, ipl6) Timer3OutHandler(void)

  // clear the interrupt flag, or the interrupt will not occur again.

  mT3ClearIntFlag();

  if(CountForAcc++ 》 2) // here can adjust the totally time of acceleration

  CountForAcc = 0;

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

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

  PR3 = Period[Index++];

  OC4RS = PR3 / 2;

  通过CalculateSModelLine接口得到如下不同的几条加速曲线:

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

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

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

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