電賽訓練了大半個暑假,人漸漸開始進入到了疲倦期。既然這樣那就好好休息下自己也好吧。
休息也不能光休息,乘機把平常寫過的一些東西好好整理也好。
從第一次訓練開始我們就接觸到了一個新的名詞——PID控制理論。接觸這個理論時間還是挺早的。大二某天晚上與學長“促膝交談”時他就有跟我提起過這個算法。當初他給我說的一個應用的場合就是在智能小車兩個輪子速度的控制上,通過pid使得兩個輪子的速度盡可能接近相等。那個時候就感覺很糾結,速度控制直接左邊慢一點就給左邊加速,反之給右邊加速。但真正當第一個題目(恆溫水壺)做出來的時候就發現,如果用傳統的方法去做控制(即溫度高則不加溫,溫度低則加溫),控制的提升速度與控制值的超調范圍無法達到兩者兼顧的效果(這也是為什麼最後我們做出來的結果都不怎麼好的原因之一,因為我網上百度的pid算法是個偽的。)。理論上(PID到現在為止沒有調試成功過),通過PID算法能夠使被控制量兼顧效率與精度這兩個我們所關注的量。
PID理論說白了就是三個量。Kp,Ki,Kd。
先說下Kp,K是常量的意思,p代表的比例(proportion),Kp可以說是PID算法中必不可少的一個量。沒有它控制就不可能實現。它的作用是根據當前量與設定量的差值按照一定比例放大後得到控制量。比如一個溫控系統,很自然的我們能夠想到當溫度越接近我們設定值時我們就越要放慢速度加熱,kp就是起一個這樣的作用。比如kp我設為10,我設定恆溫的溫度為60度,當前溫度為49度,那麼我輸出的控制量(使用占空比對熱得快實現控溫)為10*(60-49)=110;如果當前溫度為20度我輸出為10*(60-20)=400,但由於400太大了,比最大控制值0xff(255)還大,我就直接255了。如果當前溫度為61度我輸出為10*(60-61)=-10<0我輸出就為0。即不加熱讓其自然冷卻。講了這麼多歸納一個公式就是UKp=Kp*(Uset-Unow),其中UKp是通過Kp這個參數計算所輸出的控制量,Uset為設定溫度,Unow為當前溫度。
接下來就是Ki這個量,i代表的是integration,積分。空洞的說沒意思,直接舉栗子,依舊是溫控系統,當我溫度上升到59度時(設定溫度是60度)這個時候我通過上面Kp得到的控制量是10,但此時環境溫度很低。你10的控制量所提供的能量剛剛好能夠抵消掉散失到空氣中的熱量,此時溫度就恆定在59度了,當然這是與60度我們設定的值有了差距。這個時候KI就要開始起作用了,KI基本公式是從0到當前時刻(Uset-Unow)的積分值乘以Ki,但在單片機(計算機中也是)中只有數字量,於是分就變成了相乘,公式就成了UKi=UKi+KI*(Uset-Unow)*dt,dt是系統的采樣周期,即Unow隔dt采樣一次。這個值比較小,大多都不為整數,而眾所周知的51單片機中浮點數運算較慢,於是我一般會將公式改為UKi=UKi+KI*(Uset-Unow)/F,F為頻率,一般為比一大的整數,即F=1/dt。回到剛才的問題,積分的作用就非常明顯了。系統恆定在59度這KI*(60-59)/F隨著時間不斷在積分在增加,當控制量超過一定值時系統溫度就會開始上升了,由於在接近我們設定的點之前(Uset-Unow)較大,而這一部分的值依舊被積分到了Uk之中,所以Ki的作用會導致最終的控制量有一定的超調,也就是說Ki設置好之後可以稍微減少Kp的值。
最後就是Kd,d代表對時間微分(differential),即速度,是對未來趨勢的一種預測,比如還是恆溫系統,我停止加熱之後溫度並不會立即停止上升(熱得快有余溫還有就是水受熱不均所致),此時通過微分量預測上升的速度對輸出的控制量進行適當縮小,可以盡量避免“沖過頭”這種事情發生。公式UKd=UKd+Kd*((Uset-Unow)now-(Uset-Unow)before)/dt。(Uset-Unow)now是現在的(Uset-Unow)值,(Uset-Unow)before是在前一刻(Uset-Unow)的值。把dt依舊轉化成F即UKd=UKd+Kd*((Uset-Unow)now-(Uset-Unow)before)*F,UKd即為微分所對應的控制量。
好啦。。三個量都講完了,最終的輸出控制量Uk就是這三個量之和,即UK=UKp+UKi+UKd。但在51單片機中,浮點數運算會較慢,於是除了0以外我們最小只能設定PID的三個參數為1,大多數時候這個1都還是很大的一個值。所以在得到最終的輸出值時我們一般都會對這個值做移位處理(右移)即移動n位相當於除以2的n次方。調整這個n可以使得輸出在一個合適的值之內。
對PID三個常量的分析基本上說完了。。先吃飯去鳥。。吃完飯回來開始寫第二篇——PID這3個常量調整的方法。
推介閱讀英文版的維基百科關於PID的頁面。那裡面三個圖把這三個變量起的作用描述的很清楚了。。
http://en.wikipedia.org/wiki/PID_controller