PID算法的離散化
論述了PID算法的基本形式,並對其控制過程的實現有了一個簡要的說明,通過上一節的總結,基本已經可以明白PID控制的過程。這一節中先繼續上一節內容補充說明一下。
1.說明一下反饋控制的原理,通過上一節的框圖不難看出,PID控制其實是對偏差的控制過程;
2.如果偏差為0,則比例環節不起作用,只有存在偏差時,比例環節才起作用。
3.積分環節主要是用來消除靜差,所謂靜差,就是系統穩定后輸出值和設定值之間的差值,積分環節實際上就是偏差累計的過程,把累計的誤差加到原有系統上以抵消系統造成的靜差。
4.而微分信號則反應了偏差信號的變化規律,或者說是變化趨勢,根據偏差信號的變化趨勢來進行超前調節,從而增加了系統的快速性。
好了,關於PID的基本說明就補充到這里,下面將對PID連續系統離散化,從而方便在處理器上實現。下面把連續狀態的公式再貼一下:
假設采樣間隔為T,則在第K個 T時刻:
偏差err(K)=rin(K)-rout(K);
積分環節用加和的形式表示,即err(K)+err(K+1)+……;
微分環節用斜率的形式表示,即[err(K)-err(K-1)]/T;
從而形成如下PID離散表示形式:
其中T為采樣時間,Kp為比例帶,TI為積分時間,TD為微分時間。PID控制的基本原理就是如此。
則u(K)可表示成為:位置型PID
可以這么理解:比例環節將誤差線性放大,積分環節將誤差值的積分放大,微分環節將兩次的誤差值放大,所有的值相加得到最終輸出值
在不斷變化中,err(k)(設定值與實際輸出值差值)會降低或者升高,不斷降低時比例和微分環節對最終的輸出貢獻變少而積分環節因為誤差值的不斷累加貢獻最大。
至於說Kp、Ki、Kd三個參數的具體表達式,我想可以輕松的推出了,這里節省時間,不再詳細表示了。
其實到這里為止,PID的基本離散表示形式已經出來了。目前的這種表述形式屬於位置型PID,另外一種表述方式為增量式PID,由上述表達式可以輕易得到:增量式PID
那么:
這就是離散化PID的增量式表示方式,由公式可以看出,增量式的表達結果和最近三次的偏差有關,這樣就大大提高了系統的穩定性。需要注意的是最終的輸出結果應該為
u(K)+增量調節值;
PID的離散化過程基本思路就是這樣,下面是將離散化的公式轉換成為C語言,從而實現微控制器的控制作用。
當然,增量型PID必須記得一點,就是在記住U(k)=U(k-1)+∆U(k)。
PID 控制算法可以分為位置式 PID 和增量式 PID 控制算法。
兩者的區別:
(1)位置式PID控制的輸出與整個過去的狀態有關,用到了誤差的累加值;而增量式PID的輸出只與當前拍和前兩拍的誤差有關,因此位置式PID控制的累積誤差相對更大;
(2)增量式PID控制輸出的是控制量增量,並無積分作用,因此該方法適用於執行機構帶積分部件的對象,如步進電機等,而位置式PID適用於執行機構不帶積分部件的對象,如電液伺服閥。
(3)由於增量式PID輸出的是控制量增量,如果計算機出現故障,誤動作影響較小,而執行機構本身有記憶功能,可仍保持原位,不會嚴重影響系統的工作,而位置式的輸出直接對應對象的輸出,因此對系統影響較大。
增量型PID的C語言實現
上一節中介紹了最簡單的位置型PID的實現手段,這一節主要講解增量式PID的實現方法,位置型和增量型PID的數學公式請參見我的系列文《PID控制算法的C語言實現二》中的講解。實現過程仍然是分為定義變量、初始化變量、實現控制算法函數、算法測試四個部分,詳細分類請參加《PID控制算法的C語言實現三》中的講解,這里直接給出代碼了。
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 struct _pid{ 5 float SetSpeed; //定義設定值 6 float ActualSpeed; //定義實際值 7 float err; //定義偏差值 8 float err_next; //定義上一個偏差值 9 float err_last; //定義最上前的偏差值 10 float Kp,Ki,Kd; //定義比例、積分、微分系數 11 }pid; 12 13 void PID_init(){ 14 pid.SetSpeed=0.0; 15 pid.ActualSpeed=0.0; 16 pid.err=0.0; 17 pid.err_last=0.0; 18 pid.err_next=0.0; 19 pid.Kp=0.2; 20 pid.Ki=0.015; 21 pid.Kd=0.2; 22 } 23 24 float PID_realize(float speed){ 25 pid.SetSpeed=speed; 26 pid.err=pid.SetSpeed-pid.ActualSpeed; 27 float incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last); 28 pid.ActualSpeed+=incrementSpeed; 29 pid.err_last=pid.err_next; 30 pid.err_next=pid.err; 31 return pid.ActualSpeed; 32 } 33 34 int main(){ 35 PID_init(); 36 int count=0; 37 while(count<1000) 38 { 39 float speed=PID_realize(200.0); 40 printf("%f\n",speed); 41 count++; 42 } 43 return 0; 44 }
運行后的1000個數據為:(結果自行運行觀看)
結論:從最終數據的結果顯示來看,增量式PID數據的穩定性要好於位置型PID的;