PID算法 是控制算法中的經(jīng)典算法,特別是在一個閉環(huán)控制系統(tǒng)中更為常用。自己曾是第十三屆全國大學(xué)生“恩智浦”杯智能汽車競賽的參賽選手,相信所有的選手在電機控制算法上大多都是用PID算法,本想好好使用這種算法,卻無奈沒有學(xué)過。而網(wǎng)上查閱資料卻又是基本都是一些苦澀難懂?dāng)?shù)學(xué)公式和膾炙人口的一些PID語句,對于剛接觸PID算法的人而言無異于天書。所以寫此文章,意在用于分享自己對于PID算法的理解,希望可以幫助同樣與我曾經(jīng)有相同困惑的人排除困惑。注:本文是自己通過查閱書籍和觀看視頻學(xué)習(xí)而得,若有錯誤,歡迎批評指正。
- PS:感謝評論區(qū)的大佬指出我畫的PID的圖都有些小問題,但是我還畫不好一個比較好的圖來替代它們,所以大家可以根據(jù)自己所學(xué),結(jié)合評論區(qū)大佬的建議看看。(QAQ我盡量早些畫出比較好的圖來替代。)
- 2020.4.8:隨著這篇文章的點贊數(shù)越來越多,首先感謝大家對我的肯定,其次,不好意思,我的圖還沒畫出來,?大家一定要帶著懷疑的心態(tài)看我的圖片啊.?? 期待各位看官可以再給我提出新的問題和改進思路。?
一、簡介
1.1控制系統(tǒng) :開環(huán)控制系統(tǒng)與閉環(huán)控制系統(tǒng)
控制系統(tǒng)有幾種分類方法,其中,按控制原理的不同,自動控制系統(tǒng)分為開環(huán)控制系統(tǒng)
和閉環(huán)控制系統(tǒng)
。
- 開環(huán)控制系統(tǒng)
在開環(huán)控制系統(tǒng)中,系統(tǒng)輸出只受輸入的控制,控制精度和抑制干擾的特性都比較差。

- 閉環(huán)控制系統(tǒng)
閉環(huán)控制系統(tǒng)利用輸出量同期望值的偏差對系統(tǒng)進行控制,可獲得比較好的控制性能。閉環(huán)控制系統(tǒng)又稱反饋控制系統(tǒng)。

由圖中可以很明顯的看出,此控制系統(tǒng)比開環(huán)系統(tǒng)多了一個環(huán)節(jié)——傳感器,通過傳感器進行 采集和反饋 到控制算法中,形成一個 閉合的回環(huán) 這也就是閉環(huán)控制系統(tǒng)中的閉環(huán)。
1.2PID算法介紹
PID算法
是將偏差
的比例( P roportion)
、積分( I ntegral)
和 微分( D ifferential)
通過線性組合構(gòu)成控制量,用這一控制量對被控對象進行控制,這樣的控制器稱PID控制器。

簡單來說,偏差
= 用戶設(shè)定的期望值
— 傳感器采集回來的當(dāng)前值
,將偏差進行P、I、D
三個環(huán)節(jié)的計算,再進行求和、輸出
。
二、二位式控制算法
2.1 為什么要解釋二位式控制算法
二位式控制算法在某種程度上可謂是PID算法的前身,了解原理便可更好的理解PID算法。
2.2 以實例理解二位式控制
二位式控制算法輸出的控制量只有高 \ 低 電平
2種狀態(tài)。我們以燒水為例:假設(shè)我們要求此控制系統(tǒng)要將水加熱到100℃,當(dāng)傳感器采集反饋回的當(dāng)前值 沒有達到期望值
(100℃),便全高/低電平加熱;當(dāng)傳感器采集反饋回的當(dāng)前值達到期望值
(100℃),便停止加熱。

2.3 引入慣性環(huán)節(jié)
一個簡單的控制系統(tǒng)這么設(shè)計看似毫無問題,然而,由于我們的控制對象具有慣性
,例如我們控制加熱絲燒水,當(dāng)我們達到指定溫度停止加熱
的時候,加熱絲不會馬上冷卻下來
,水溫還會繼續(xù)升高,超過指定溫度;而過了一會兒,水溫冷卻下來低于指定溫度時,給加熱絲通電,加熱絲也無法立刻把溫度升上去
。由于我們的控制對象(加熱絲、電感、電容、電機等)具有慣性
,而二位式控制算法的輸出量只于當(dāng)前狀態(tài)有關(guān)
,故很難達到精確控制
。
eg:電機就是一個 具有慣性的對象,給他施加電壓,不能馬上轉(zhuǎn)到對應(yīng)的速度;撤去電壓,電機也不能馬上停下。

由于慣性環(huán)節(jié)的存在,會使控制對象超出期望值。
三、位置式PID算法
- ①如果我們把二位式控制算法理解為數(shù)字量輸出,那么PID算法則就是模擬量輸出。
- ②二位式控制算法只于當(dāng)前偏差有關(guān),而PID算法則是考慮到過去、現(xiàn)在、和未來的控制算法。
我們規(guī)定:用戶期望值為 Expect,每隔一個固定時間對控制對象進行信息采樣Xn,在此基礎(chǔ)上,我們在三個環(huán)節(jié)中介紹三個序列。
3.1 P環(huán)節(jié)(現(xiàn)在)
P(比例)環(huán)節(jié):對當(dāng)前時刻的偏差進行比例放大。
- 采樣序列:系統(tǒng)中每個時刻采集回來的當(dāng)前值 Xn 。
- X1、X2、X3 … Xn-1、Xn; 第k時刻的 偏差:e(k)=Expect — Xk;
- e(k)>0 :控制系統(tǒng)還未達到期望值;
- e(k)=0 :控制系統(tǒng)已經(jīng)達到期望值;
- e(k)<0 :控制系統(tǒng)已經(jīng)超過期望值;
- P環(huán)節(jié)的第k時刻的輸出:
u(k)=Kp * e(k)
。 - Kp:P比例系數(shù),可以理解為放大倍數(shù)。
- 單P算法中的缺陷:當(dāng)系統(tǒng)不存在偏差(e(k)=0)時,執(zhí)行部件便無輸出,被控對象處于失控狀態(tài)。

3.2 I 環(huán)節(jié)(過去)
I(積分)環(huán)節(jié):對過去所有時間的偏差進行積分。
- 偏差序列:e(k)=Expect — Xk
- e1、e2、e3 … en-1、en; ∑ei:對過去所有時間的偏差進行求和;
- ∑ei<0 :控制系統(tǒng)在 過去大部分時間段還未達到期望值;
- ∑ei=0 :控制系統(tǒng)在 過去大部分時間段已經(jīng)達到期望值;
- ∑ei>0 :控制系統(tǒng)在 過去大部分時間段已經(jīng)超過期望值;
- I環(huán)節(jié)的第k時刻的輸出:
u(k)=Ki * ∑ei
。(Ki:i比例系數(shù))
在控制系統(tǒng)剛啟動時,由于I環(huán)節(jié)的 偏差累積效應(yīng),可以 更快的達到期望值。但同時也由于偏差的累積效應(yīng),使得系統(tǒng)第一次達到期望值時,過去所有時刻都未達標(biāo),即∑ei很大,所以曲線其實會超過期望的那條虛線并持續(xù)增長,所以,我們通常會在I環(huán)節(jié)中除以積分時間Ti,即u(k)=Ki * ∑ei/Ti
另一個解決辦法 我們后面在增量式算法中再進行討論。

3.3 D環(huán)節(jié)(將來)
D(微分)環(huán)節(jié):通過偏差的偏差,對控制系統(tǒng)的輸出走向進行預(yù)判,起超前調(diào)節(jié)的作用。
- 偏差的偏差序列:
△ek=ek-ek-1
; - △e1、△e2、△e3 … △en-1、△en;
- △e(k)很大時,表示控制系統(tǒng)上一刻的輸出很“陡峭”,表明控制系統(tǒng)離目標(biāo)相差很遠,所以D環(huán)節(jié)的輸出也很大。
- D環(huán)節(jié)的第k時刻的輸出:
u(k)=Kd * △e(k)
。 - Kd:D積分系數(shù),除了超前預(yù)判,還可理解為阻尼力。

四、增量式PID算法
位置式PID:u(k)=Kp * e(k)+Ki / T * ∫ e(k) dt+Kd*d e(k);
增量式PID:u(k)=Kp * e(k-1)+Ki *e(t) +Kd *(e(k)-2e(k-1)+e(k-2));
很顯然,對位置式PID進行求導(dǎo)(dx = f(x) - f(x-1)),就得到了增量式PID。
對于前面談到的,位置式PID的 I 環(huán)節(jié),是對過去所有時間
的偏差進行積分,其輸出與過去所有時間都有關(guān),而增量式的PID只于最近的三個時刻
的偏差有關(guān)。
其實,增量式PID我覺得也沒有很多需要理解的,自然而然的代入應(yīng)用即可。
//電機控制 增量式 P I 算法 Err_speed=Expect_speed-actual_speed; Err_dev_speed=Err_speed-Err_speed_last; Err_speed_last=Err_speed; gradinets=(int) (PID_P*Err_dev_speed+PID_I*Err_speed);
float PID_Cal(float Speed){ pid.SetSpeed = Speed; pid.Err = pid.SetSpeed - pid.ActualSpeed;//誤差的計算,即比例控制 pid.Integral += pid.Err;//誤差相加,即積分控制 pid.Voltage = pid.Kp * pid.Err + pid.Ki * pid.Integral + pid.Kd * (pid.Err - pid.Err_last);//根據(jù)位置型PID控制的公式 pid.Err_last = pid.Err; pid.ActualSpeed = pid.Voltage * 1.0; //轉(zhuǎn)換 return pid.ActualSpeed;//PID控制后的實際輸出值}