首页 > 编程知识 正文

步进电机s型曲线加减速算法与实现,步进电机特性曲线

时间:2023-05-05 13:33:02 阅读:221685 作者:4158

 之前做电机相关的项目比较少,最近有个项目涉及到步进电机的精确控制,参考了一些资料研究了一下S型曲线加减速,这里总结一下分享给大家。

硬件是:STM32+驱动器+步进电机。

STM32定时器输出PWM,控制驱动器来驱动步进电机。单片机只要控制电机方向,以及PWM的频率即可,具体驱动由驱动器实现。

首先说一下什么是S型曲线加速,为什么要S型曲线加速。

S型曲线加速是指步进电机的启动速度按照S型曲线逐渐增加,以达到设定的最大速度。具体的S型曲线方程如下:

x取值-5~5的曲线图如下:

可以看到,刚开始加速和达到最大速度时加速比较缓慢,中间加速比较快。

电机的转矩和转速的乘积的k倍等于功率,也就是说,功率一定的时候,转速与转矩成反比关系。所以,转速越低,转矩越大。当电机直接高速启动时,电机可能存在震动、丢步甚至启动不起来的情况。因此需要S型曲线加速,使电机能够缓慢启动。

程序实现

控制电机的速度,其实就是控制PWM的输出频率。首先需要对S曲线方程进行一些变化,如下:

Fcurrent = Fmin + (Fmax-Fmin)/(1+exp( -Flexible(i - num )/num) )

Fcurrent为计算出的当前频率。

Fmin为加速的起始频率。

Fmax为加速的最大频率。

-Flexible*(i - num)/num是对S型曲线进行拉伸变化,其中Flexible代表S曲线区间(越大代表压缩的最厉害,中间加速度越大;越小越接近匀加速。理想的S曲线的取值为4-6)。

i是在循环计算过程中的索引,从0开始。

num为 加速脉冲数/2 大小。

上面计算出的是频率的S曲线,还需要将频率转换成定时器的计数周期,程序如下:

//功能:S加速曲线初始化//参数1 *pbuff 计算出的定时器的周期//参数2 fre_max 最大频率 Hz//参数3 fre_min 最小频率 Hz//参数4 len 加速需要的脉冲数void CurveS_init(uint16_t *pbuff,uint32_t fre_max,uint32_t fre_min,int16_t len){ int16_t i; uint16_t flexible =4;      float delt = fre_max-fre_min;      float deno ; float melo ;      float fre; for(i=0; i<len; i++) { melo = flexible* (i-len/2) / (len/2); deno = 1.0f / (1 + expf(-melo)); // fre = delt * deno + fre_min; *pbuff++ = (unsigned short)(sldqyg2_CLOCK_FREQ / fre); }}

sldqyg2_CLOCK_FREQ为定时器的计数频率。

之后要做的就是在加减速过程中,每输出一个PWM脉冲,重新装载一次定时器周期。具体怎样输出指定个数PWM来控制步进电机,可参考之前的文章《STM32定时器产生指定个数脉冲》。

在PWM中断中,将计算好的S曲线数组,重新装载到定时器的ARR和CCR寄存器中即可。程序如下:

//PWM回调函数void HAL_sldqyg_PWM_PulseFinishedCallback(sldqyg_HandleTypeDef *htim){ Motor.PWMcount++; SpeedAdjust();//速度调节}//速度调节函数void SpeedAdjust(void){ switch(Motor.Status) { /*加速*/ case SPEED_INCREASE: if(Motor.Count < Motor.CountMax) { __HAL_sldqyg_SET_AUTORELOAD(&htim2,Period[Motor.Count]);//计算下一个PWM的周期 htim2.Instance->CCR1 = Period[Motor.Count]/2;//占空比50% Motor.Count++;//加速次数 } else { Motor.Status = SPEED_STABLE; Motor.Count--; }      break; /*匀速*/ case SPEED_STABLE: if(Motor.PWMcount >= (Motor.PWMneed - Motor.Count)) { Motor.Status = SPEED_DECREASE; }      break; /*减速*/ case SPEED_DECREASE: if(Motor.Count >= 0) { __HAL_sldqyg_SET_AUTORELOAD(&htim2,Period[Motor.Count]);//计算下一个PWM的周期 htim2.Instance->CCR1 = Period[Motor.Count]/2; Motor.Count--; } if(Motor.PWMcount >= Motor.PWMneed) { HAL_sldqyg_PWM_Stop_IT(&htim2,sldqyg_CHANNEL_1); }       break; default : break; }

其中Motor是自己定义的一个结构体:

typedef struct{ uint8_t Status; //状态 int32_t Count; //加减速过程脉冲计数 int32_t CountMax; //最大加速脉冲数 uint32_t PWMcount;//PWM计数 uint32_t PWMneed; //需要输出的PWM总数}Motor_t;

启动时,初始化参数,启动定时器输出PWM即可:

//PWM--需要输出的脉冲个数void StartPWM(uint32_t PWM){ Motor.PWMcount = 0; Motor.PWMneed = PWM; Motor.Count = 0; Motor.Status = SPEED_INCREASE; Motor.CountMax = 300;       //初始化加速曲线,最小频率100,最大频率10K,加速脉冲数300       CurveS_init(Period,10000,100,Motor.CountMax); __HAL_sldqyg_SET_AUTORELOAD(&htim2,Period[0]); htim2.Instance->CCR1 = Period[0]; HAL_sldqyg_PWM_Start_IT(&htim2, sldqyg_CHANNEL_1); //启动定时器PWM输出}

来看一下效果,可以看到,PWM的频率是逐渐增大的。实际测试效果也不错。

推荐阅读:

STM32F4通过U盘升级程序

STM32CubeMX系列教程

STM32定时器应用合集

欢迎关注公众号"嵌入式技术开发",大家可以后台给我留言沟通交流。如果觉得该公众号对你有所帮助,也欢迎推荐分享给其他人。

CSS中div滚动条样式如何设置

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。