电子说
之前做电机相关的项目比较少,最近有个项目涉及到步进电机的精确控制,参考了一些资料研究了一下S型曲线加减速,这里总结一下分享给大家。
Fcurrent为计算出的当前频率。
Fmin为加速的起始频率。
Fmax为加速的最大频率。
-Flexible*(i - num)/num是对S型曲线进行拉伸变化,其中Flexible代表S曲线区间(越大代表压缩的最厉害,中间加速度越大;越小越接近匀加速。理想的S曲线的取值为4-6)。
i是在循环计算过程中的索引,从0开始。
num为加速脉冲数/2 大小。
TIM2_CLOCK_FREQ为定时器的计数频率。 之后要做的就是在加减速过程中,每输出一个PWM脉冲,重新装载一次定时器周期。具体怎样输出指定个数PWM来控制步进电机,可参考之前的文章《STM32定时器产生指定个数脉冲》。 在PWM中断中,将计算好的S曲线数组,重新装载到定时器的ARR和CCR寄存器中即可。程序如下://功能:S加速曲线初始化
//参数1 *pbuff 计算出的定时器的周期
//参数2 fre_max 最大频率 Hz
//参数3 fre_min 最小频率 Hz
//参数4 len 加速需要的脉冲数
voidCurveS_init(uint16_t*pbuff,uint32_tfre_max,uint32_tfre_min,int16_tlen)
{
int16_ti;
uint16_tflexible =4;
floatdelt = fre_max-fre_min;
floatdeno ;
floatmelo ;
floatfre;
for(i=0; i
{
melo = flexible* (i-len/2) / (len/2);
deno =1.0f/ (1+ expf(-melo));//
fre = delt * deno + fre_min;
*pbuff++ = (unsignedshort)(TIM2_CLOCK_FREQ / fre);
}
}
//PWM回调函数
voidHAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
Motor.PWMcount++;
SpeedAdjust();//速度调节
}
//速度调节函数
voidSpeedAdjust(void)
{
switch(Motor.Status)
{
/*加速*/
caseSPEED_INCREASE:
if(Motor.Count < Motor.CountMax)
{
__HAL_TIM_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;
/*匀速*/
caseSPEED_STABLE:
if(Motor.PWMcount >= (Motor.PWMneed - Motor.Count))
{
Motor.Status = SPEED_DECREASE;
}
break;
/*减速*/
caseSPEED_DECREASE:
if(Motor.Count >=0)
{
__HAL_TIM_SET_AUTORELOAD(&htim2,Period[Motor.Count]);//计算下一个PWM的周期
htim2.Instance->CCR1 = Period[Motor.Count]/2;
Motor.Count--;
}
if(Motor.PWMcount >= Motor.PWMneed)
{
HAL_TIM_PWM_Stop_IT(&htim2,TIM_CHANNEL_1);
}
break;
default:
break;
}
其中Motor是自己定义的一个结构体:
启动时,初始化参数,启动定时器输出PWM即可:typedefstruct{
uint8_tStatus;//状态
int32_tCount;//加减速过程脉冲计数
int32_tCountMax;//最大加速脉冲数
uint32_tPWMcount;//PWM计数
uint32_tPWMneed;//需要输出的PWM总数
}Motor_t;
来看一下效果,可以看到,PWM的频率是逐渐增大的。实际测试效果也不错。 审核编辑 :李倩//PWM--需要输出的脉冲个数
voidStartPWM(uint32_tPWM)
{
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_TIM_SET_AUTORELOAD(&htim2,Period[0]);
htim2.Instance->CCR1 = Period[0];
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);//启动定时器PWM输出
}
全部0条评论
快来发表一下你的评论吧 !