之前做電機(jī)相關(guān)的項(xiàng)目比較少,最近有個(gè)項(xiàng)目涉及到步進(jìn)電機(jī)的精確控制,參考了一些資料研究了一下S型曲線加減速,這里總結(jié)一下分享給大家。
STM32定時(shí)器輸出PWM,控制驅(qū)動(dòng)器來驅(qū)動(dòng)步進(jìn)電機(jī)。單片機(jī)只要控制電機(jī)方向,以及PWM的頻率即可,具體驅(qū)動(dòng)由驅(qū)動(dòng)器實(shí)現(xiàn)。 首先說一下什么是S型曲線加速,為什么要S型曲線加速。
S型曲線加速是指步進(jìn)電機(jī)的啟動(dòng)速度按照S型曲線逐漸增加,以達(dá)到設(shè)定的最大速度。具體的S型曲線方程如下:x取值-5~5的曲線圖如下:可以看到,剛開始加速和達(dá)到最大速度時(shí)加速比較緩慢,中間加速比較快。電機(jī)的轉(zhuǎn)矩和轉(zhuǎn)速的乘積的k倍等于功率,也就是說,功率一定的時(shí)候,轉(zhuǎn)速與轉(zhuǎn)矩成反比關(guān)系。所以,轉(zhuǎn)速越低,轉(zhuǎn)矩越大。當(dāng)電機(jī)直接高速啟動(dòng)時(shí),電機(jī)可能存在震動(dòng)、丟步甚至啟動(dòng)不起來的情況。因此需要S型曲線加速,使電機(jī)能夠緩慢啟動(dòng)。程序?qū)崿F(xiàn)控制電機(jī)的速度,其實(shí)就是控制PWM的輸出頻率。首先需要對S曲線方程進(jìn)行一些變化,如下:Fcurrent = Fmin + (Fmax-Fmin)/(1+exp( -Flexible(i - num )/num) )
-
Fcurrent為計(jì)算出的當(dāng)前頻率。
-
Fmin為加速的起始頻率。
-
Fmax為加速的最大頻率。
-
-Flexible*(i - num)/num是對S型曲線進(jìn)行拉伸變化,其中Flexible代表S曲線區(qū)間(越大代表壓縮的最厲害,中間加速度越大;越小越接近勻加速。理想的S曲線的取值為4-6)。
-
i是在循環(huán)計(jì)算過程中的索引,從0開始。
-
num為 加速脈沖數(shù)/2 大小。
TIM2_CLOCK_FREQ為定時(shí)器的計(jì)數(shù)頻率。 之后要做的就是在加減速過程中,每輸出一個(gè)PWM脈沖,重新裝載一次定時(shí)器周期。具體怎樣輸出指定個(gè)數(shù)PWM來控制步進(jìn)電機(jī),可參考之前的文章《STM32定時(shí)器產(chǎn)生指定個(gè)數(shù)脈沖》。在PWM中斷中,將計(jì)算好的S曲線數(shù)組,重新裝載到定時(shí)器的ARR和CCR寄存器中即可。程序如下://功能:S加速曲線初始化
//參數(shù)1 *pbuff 計(jì)算出的定時(shí)器的周期
//參數(shù)2 fre_max 最大頻率 Hz
//參數(shù)3 fre_min 最小頻率 Hz
//參數(shù)4 len 加速需要的脈沖數(shù)
void CurveS_init(uint16_t *pbuff,uint32_t fre_max,uint32_t fre_min,int16_t len)
{
int16_t i;
uint16_t flexible =4;
floatdelt=fre_max-fre_min;
floatdeno;
float melo ;
floatfre;
for(i=0; i
{
melo = flexible* (i-len/2) / (len/2);
deno = 1.0f / (1 + expf(-melo)); //
fre = delt * deno + fre_min;
*pbuff++ = (unsigned short)(TIM2_CLOCK_FREQ / fre);
}
}
//PWM回調(diào)函數(shù)
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
Motor.PWMcount++;
SpeedAdjust();//速度調(diào)節(jié)
}
//速度調(diào)節(jié)函數(shù)
void SpeedAdjust(void)
{
switch(Motor.Status)
{
/*加速*/
case SPEED_INCREASE:
if(Motor.Count < Motor.CountMax)
{
__HAL_TIM_SET_AUTORELOAD(&htim2,Period[Motor.Count]);//計(jì)算下一個(gè)PWM的周期
htim2.Instance->CCR1 = Period[Motor.Count]/2;//占空比50%
Motor.Count++;//加速次數(shù)
}
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_TIM_SET_AUTORELOAD(&htim2,Period[Motor.Count]);//計(jì)算下一個(gè)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是自己定義的一個(gè)結(jié)構(gòu)體:
啟動(dòng)時(shí),初始化參數(shù),啟動(dòng)定時(shí)器輸出PWM即可:typedef struct{
uint8_t Status; //狀態(tài)
int32_t Count; //加減速過程脈沖計(jì)數(shù)
int32_t CountMax; //最大加速脈沖數(shù)
uint32_t PWMcount;//PWM計(jì)數(shù)
uint32_t PWMneed; //需要輸出的PWM總數(shù)
}Motor_t;
來看一下效果,可以看到,PWM的頻率是逐漸增大的。實(shí)際測試效果也不錯(cuò)。//PWM--需要輸出的脈沖個(gè)數(shù)
void StartPWM(uint32_t PWM)
{
Motor.PWMcount = 0;
Motor.PWMneed = PWM;
Motor.Count = 0;
Motor.Status = SPEED_INCREASE;
Motor.CountMax = 300;
//初始化加速曲線,最小頻率100,最大頻率10K,加速脈沖數(shù)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); //啟動(dòng)定時(shí)器PWM輸出
}
審核編輯 :李倩
-
驅(qū)動(dòng)器
+關(guān)注
關(guān)注
53文章
8263瀏覽量
146682 -
步進(jìn)電機(jī)
+關(guān)注
關(guān)注
151文章
3115瀏覽量
147649
原文標(biāo)題:步進(jìn)電機(jī)S型曲線加速的實(shí)現(xiàn)
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論