本系列旨在以我自己寫的PID lib為例,講一下PID的幾點基本優化,PID的基本原理網上有很多資料,因此本系列將不會涉及PID的基本實現原理,在這里特別推薦Matlab tech talk的PID教程:https://ww2.mathworks.cn/videos/series/understanding-pid-control.html。
由於筆者大一在讀,還沒有學習自動控制原理等課程,因此本系列將不會從自控原理角度展開,相反的,本系列將試圖從“直覺”展開,通過直觀的描述讓大家從直覺上感受並理解PID的一些包括微分先行、積分分離等基礎的優化。
由於筆者水平有限,文中難免存在一些不足和錯誤之處,誠請各位批評指正。
我的PID庫與PID基本優化(一)中講解了代碼結構與代碼使用,算法有關內容於該篇開始
1 梯形積分
1.1 問題
積分項的作用在絕大多數情況下是消除靜差,為了更精准的消除靜差,我們需要提高積分項的計算精度。在一般的PID算法中,我們通過矩形面積來近似計算積分,在微積分中我們了解到,當 \(\Delta t\) 趨近於無窮小時,這些矩形面積的累加就會無限逼近曲線與坐標軸圍成的面積。
1.2 解決方案
為了達到更精准的控制,我們一般可以通過提高控制頻率來實現,但在某些情況下受制於控制設備算力,我們無法以很高的頻率來運行我們的算法。因此我們可以用梯形代替矩形,以此獲得更高的積分精度,這種方式在控制頻率越低的場合提高精度的效果越好。
1.3 代碼實現
static void f_Trapezoid_Intergral(PID_TypeDef *pid)
{
pid->ITerm = pid->Ki * ((pid->Err + pid->Last_Err) / 2);
}
2 微分先行
2.1 問題
在常規PID中,微分項是微分系數乘誤差的微分,而誤差的微分又可以化成目標信號的微分減去輸入(測量值)的微分,即:
當目標信號瞬間發生變化時,其微分會變得非常非常大,這會導致微分項的值也在瞬間變得巨大。這樣異常的微分項添加至控制算法中,會導致PID的輸出出現我們不希望看到的峰值,這樣的峰值可能會影響系統的穩定性,甚至對執行器或者系統其他部分造成損壞,我們稱這種現象為微分沖擊(Derivative Kick)。
如下圖所示,微分沖擊會使被控對象發生瞬間的抖動,通過觀察PID輸出與微分項輸出,我們可以直觀感受到微分沖擊的威力:

將圖像2放大來看,在階躍信號剛產生時,微分項會給整個輸出帶來巨大的尖峰:

2.2 解決方案
通過公式我們可以看到,是目標信號的微分引入的異常數值,因此我們只需要扔掉目標信號的微分,只保留輸入(測量值)的微分(注意不要漏掉符號):
經過對微分項的一點點調整,我們可以看到,現在的控制曲線變得更加平滑,PID的輸出也不會出現異常的峰值:

2.3 代碼實現
static void f_Derivative_On_Measurement(PID_TypeDef *pid)
{
pid->Dout = pid->Kd * (pid->Last_Measure - pid->Measure);
}