這是項目中非常重要的PID控制器,為什么電機會時刻保持穩定,主要就是靠它,目前我認為它應該以實際位置與目標位置的差值作為PID的控制器輸入,控制電機的PWM波形的生產相關參數作為輸出。到底是不是呢,先看看函數本身的定義和之后的調用就清楚了。
/************************/
/* PID Controller? ? ? */
/************************/
// PID integer inplementation
//? DTms? ... sample period (ms)//采樣周期
//? DTinv ... sample frequency (Hz), inverse of DT (just to avoid division)//采樣頻率,采樣周期的倒數,提前算好,避免由控制器計算除法,減小計算量
int32_t ComputePID(int32_t DTms, int32_t DTinv, int32_t in, int32_t setPoint, int32_t *errorSum, int32_t *errorOld, int32_t Kp, int16_t Ki, int32_t Kd)
//int32_t 是32位有符號整型數,可以看到PID控制器的參數有DTms采樣周期,DTinv采樣頻率,in(實際值),setPoint設定值,誤差errorsum誤差總和,errorOld上一步誤差,Kp,Ki,Kd,為PID的三個整定參數。
{
int32_t error = setPoint - in;//計算當前周期內的誤差,給定值-實際值=誤差
int32_t Ierr;
Ierr = error * Ki * DTms;//計算當前周期的誤差積分
Ierr = constrain_int32(Ierr, -(int32_t)1000*100, (int32_t)1000*100);//對lerr的數值進行大小限制,控制在±100000之內,是不是為了避免積分飽和呢?
*errorSum += Ierr;//當前誤差積分與歷史誤差積分相加,產生新的歷史誤差積分
/*Compute PID Output*/
int32_t out = (Kp * error) + *errorSum + Kd * (error - *errorOld) * DTinv;//正好是三項,第一項比例項,第二項積分項,第三項微分項(相鄰兩個周期的誤差相減除以周期,就是誤差曲線的斜率)
*errorOld = error;//為下一次計算做準備,將本次周期的誤差存為上一次誤差
out = out / 4096 / 8;//這里為什么要連續除以4096和8的目的還不清楚,需要配合日后引用的代碼進行分析
return out;
}
通過分析,可以看出這個PID控制器是采用位置式的實現發放,也就是全量式的。
全量式有什么樣的缺點呢?
1)由于全量輸出,所以每次輸出均與過去狀態有關,計算時要對e(k)(k=0,1,…n)進行累加,工作量大。其實到也沒有多大的計算量,實際編程中也是逐項累加起來的,一個循環周期內也只是用到歷史綜合和當前誤差。倒是需要對積分飽和的問題進行控制。
2)因為計算機輸出的u(n)對應的是執行機構的實際位置,如果計算機出現故障,輸出u(n)將大幅度變化,會引起執行機構的大幅度變化,有可能因此造成嚴重的生產事故,這在實際生產中是不允許的。
與此相對應的還有增量式的,具體實現方法可以參考這里。