本系列旨在以我本身寫的PID lib爲例,講一下PID的幾點基本優化,PID的基本原理網上有不少資料,所以本系列將不會涉及PID的基本實現原理,在這裏特別推薦Matlab tech talk的PID教程:https://ww2.mathworks.cn/videos/series/understanding-pid-control.html。html
因爲筆者大一在讀,尚未學習自動控制原理等課程,所以本系列將不會從自控原理角度展開,相反的,本系列將試圖從「直覺」展開,經過直觀的描述讓你們從直覺上感覺並理解PID的一些包括微分先行、積分分離等基礎的優化。算法
因爲筆者水平有限,文中不免存在一些不足和錯誤之處,誠請各位批評指正。ide
在個人PID庫與PID基本優化(二)中提到過,在目標信號瞬間發生變化時,會致使微分項輸出出現異常。這樣的狀況不只會致使微分項出現問題,一樣會影響積分項的穩定性。例如在系統啓動或者設定值被人爲大幅度改變時,因爲偏差瞬間增大,偏差的積分會迅速累積,從而致使積分項輸出過大,進而產生較大的超調,嚴重時甚至會引發系統振盪:函數
在消除微分衝擊問題時,咱們經過將偏差的微分拆解成兩項,去掉其中引發衝擊的一項以解決問題。但對於積分項來講,將偏差的積分拆成兩項並刪掉目標信號的積分是不現實的,由於這樣積分控制就失去了消除靜態偏差的能力。學習
所以咱們須要換一種思路,既然在目標信號瞬間變化時,偏差的瞬間增大致使了積分的過度積累。咱們只須要在偏差超過必定閾值時中止積分過程,當偏差小於這個閾值,降至合理範圍的時候,咱們再繼續積分過程,這樣就避免了因爲目標信號變化引發的巨大偏差累積到積分項中。優化
從圖二中能夠看到,積分項是在控制過程開始一段時間後開始積累,避免了過度累積,從而減少了超調:3d
庫中並無實現積分分離,而是選擇了過渡效果更平緩的變積分策略,所以如下代碼並未在庫中出現code
static void f_Integral_Separation(PID_TypeDef *pid) { //首先判斷該週期內積分項是否爲積累趨勢 //只有本次積分爲積累趨勢纔會取消積分項 //在本篇結束前會詳細分析這麼處理的意義 if (pid->Err * pid->Iout > 0) { if (ABS(pid->Err) <= pid->MaxErr) return; //完整積分 else pid->ITerm = 0;//取消積分環節 } }
變速積分與積分分離解決的問題相同,但在積分分離中,咱們對偏差只有積和不積兩種對策,但0和1之間的過渡未免太突兀了,所以咱們引入變速積分的概念。htm
變速積分與積分分離解決的問題的方式大體相同,能夠將變速積分理解爲積分分離的一個再優化。變速積分用連續函數代替積分分離中單純的0,1切換。blog
這個連續函數能夠是線性的也能夠是非線性的,通常咱們使用一個比較簡單的形式:
static void f_Changing_Integral_Rate(PID_TypeDef *pid) { if (pid->Err * pid->Iout > 0) { if (ABS(pid->Err) <= pid->ScalarB) return; //完整積分 if (ABS(pid->Err) <= (pid->ScalarA + pid->ScalarB)) //使用線性函數過渡 pid->ITerm *= (pid->ScalarA - ABS(pid->Err) + pid->ScalarB) / pid->ScalarA; else pid->ITerm = 0;//取消積分環節 } }
在積分分離與變速積分的代碼實現中,我都會在算法開始前判斷下當前週期下積分是否爲累積趨勢,只有在累積趨勢下才會經過一些方法抑制積分的過分積累。目的是爲了不在控制信號發生變化,致使偏差瞬間反向時,因爲偏差過大致使積分限制算法發揮做用,這樣一來積分沒法迅速減少。在偏差反向過程當中,積分居高不下會致使PID輸出持續保持較高水平,從而致使響應嚴重滯後。
這樣的滯後在某些控制頻率較低的場合下甚至會致使超調和振盪,下圖爲前文PID參數保持不變時將目標值歸零後控制曲線的變化:
所以,須要在積分分離或變速積分在對積分項進行處理前先判斷一下積分是否會累積,若是當前週期的偏差會致使積分減少,則無需抑制積分減少的趨勢,由於這兩種算法歸根結底是爲了不積分過分積累而非積分的快速變化。