PID控制器/算法的思想和實現


PID介紹

why - 在講是什麼之前,先舉個(也許不太恰當的)🌰來說說爲什麼需要PID

假設我們在燒水,我們現在希望把水控制在60度,一種簡單粗暴的解決方案:當我們發現水溫超過了60度我們就打開開關(假設目前只有最大功率[打開開關]和0功率[關閉開關]),結果打開開關後功率太大,水溫立馬超過了60度,我們又立刻關掉開關,這個時候水溫很快就掉到60度以下。很顯然,這個方案並不能穩定地將水溫控制在60度,很容易在60度上下形成波動很大的曲線。

因此,我們需要一個方案,能夠穩定控制水溫。更直觀地就反映在,如何控制某一個時刻的加熱功率,讓水溫能夠保持在目標溫度上。

how - 如何解決上面場景的問題呢

相信大家很快可以想到,當剛開始燒水的時候,離目標溫度比較遠,我們就把功率開大一點,當離目標溫度越來越近後,我們就逐漸調小功率。所以我們需要建立一個t時刻的燒水功率關於目標溫度和當前溫度的函數,用來計算t時刻應該有的燒水功率。

what - pid是什麼

上述🌰中,t時刻的燒水功率我們設定用u(t)表示,t時刻目標溫度和當前溫度的差值用e(t)表示,PID的公式可以表示爲:
在這裏插入圖片描述
可以看到公式分爲三部分,即P、I、D,簡單理解下上面三部分:

P:比例,可以看到該部分是與e(t)的一次函數關係,從🌰上來理解就是,與目標溫差越大的時候,就會讓輸出功率越大

其中Kp爲比例係數

I:積分,該部分主要是e(t)關於時間t的積分,假設當加熱到50度的時候,此時比例部分算出來的加熱功率帶來的加熱速度與自然散熱速度相等了,那此時水溫就會一直停留在50度(D此時也無法起到作用,因爲e(t)變化速率此時趨近於0),積分的作用就可以體現出來了,此時積分值不斷增大,會反應在功率上,從而使水溫可以超過50度(即:消除靜差

其中Ti爲積分時間常數(本質上就是一個帶單位的常數,目的是爲了配平量綱)

D:微分,即在t時刻e(t)的變化趨勢,起到反向抑制的作用,使得最終溫度能夠趨近穩定在目標溫度上,而不是有幅度的波動

其中Td爲微分時間常數(同樣是一個帶單位的常數)

PID實現

位置式PID

假設採樣間隔爲T(T越小越精確),uk爲第k次採樣時的輸出,代入PID原始公式,則可以得到離散式PID公式如下:

在這裏插入圖片描述

此即爲位置式PID,其中Kp、Ti、Td、T均爲常數,位置式PID依賴過去所有采樣的偏差值

增量式PID

增量式PID,顧名思義,計算出控制量的變化Δ\Deltauk,從而計算出uk=Δ\Deltauk+uk-1

Δ\Deltauk通過位置式PID可以得到,即Δ\Deltauk=uk-uk-1,如下圖(紅框圈出來的部分是demo中用的計算式):

在這裏插入圖片描述

可以看到,增量式PID只依賴過去兩次偏差值和前一次計算得出的控制量

調節經驗

參數整定找最佳,從小到大順序查
先是比例後積分,最後再把微分加
曲線振盪很頻繁,比例度盤要放大
曲線漂浮繞大灣,比例度盤往小扳
曲線偏離回覆慢,積分時間往下降
曲線波動週期長,積分時間再加長
曲線振盪頻率快,先把微分降下來
動差大來波動慢。微分時間應加長
理想曲線兩個波,前高後低4比1
一看二調多分析,調節質量不會低

demo c++/java

使用c++和java各寫了一版PID控制器,源碼詳見:https://github.com/LeiDengDengDeng/pid-controller

運行效果

輸出如下內容:

--------------Positional--------------
current:30,output:350
current:50,output:210
current:60,output:190
--------------------------------------

--------------Incremental-------------
current:30,output:350
current:50,output:210
current:60,output:190
--------------------------------------

參考文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章