最近看到了Brett Beauregard發表的有關PID的系列文章,感覺對於理解PID算法很有幫助,於是將系列文章翻譯過來!在自我提高的過程中,也希望對同道中人有所幫助。作者Brett Beauregard的原文網址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-tuning-changes/
1、問題
對於任何可靠的PID算法,擁有在系統運行時更改整定參數的能力都是必須的。
如果你試圖在系統運行時改變整定參數,在初學PID的人看來會顯得有點瘋狂。讓我們看看這是為什么?以下是初學者的 PID 在上述參數更改前后的狀態:
因此,我們可以立即將這種差異歸咎於積分項(或“I項”)。只有當參數發生變化時,它才會發生劇烈的變化。為什么會這樣?這與初學積分的人對積分的理解有關:
這種解釋在 Ki 被改變之前都是可以正常工作的。然后,你突然把這個新的 Ki 乘以你積累的整個誤差總和。這不是我們想要的!我們只想影響事情后續的發展。
2、解決方案
有幾種方法可以處理這個問題。我在上一個庫中使用的方法是重新縮放偏差累計。Ki 翻了一倍?或者把偏差累計削減一半。這可以避免積分項撞擊,並且也能工作的很好。不過,這有點笨拙,我想出了更優雅的東西。(我不可能是第一個想到這個問題,但我確實是一個人想到的。這算數!)
這個方案需要一個小的基本代數 (還是微積分?)
我們不是讓 Ki 處在積分之外,而是把它帶到里面。看起來我們視乎什么都沒做,但我們會看到,在實踐中,這帶來了很大的變化。
現在,我們把誤差乘以那個時候的Ki。然后我們存儲它的和。當Ki發生變化時,沒有任何變化,因為所有舊的Ki都已經“存在銀行”了。我們得到一個平穩的轉換,沒有額外的數學運算。這可能會讓我成為一個極客,但我覺得這很性感。
3、代碼
1 /*working variables*/ 2 unsigned long lastTime; 3 double Input,Output,Setpoint; 4 double ITerm,lastInput; 5 double kp,ki,kd; 6 int SampleTime = 1000; //1 sec 7 void Compute() 8 { 9 unsigned long now = millis(); 10 int timeChange = (now - lastTime); 11 if(timeChange>=SampleTime) 12 { 13 /*Compute all the working error variables*/ 14 double error = Setpoint - Input; 15 ITerm += (ki * error); 16 double dInput = (Input - lastInput); 17 18 /*Compute PID Output*/ 19 Output = kp * error + ITerm - kd * dInput; 20 21 /*Remember some variables for next time*/ 22 lastInput = Input; 23 lastTime = now; 24 } 25 } 26 27 void SetTunings(double Kp,double Ki,double Kd) 28 { 29 double SampleTimeInSec = ((double)SampleTime)/1000; 30 kp = Kp; 31 ki = Ki * SampleTimeInSec; 32 kd = Kd / SampleTimeInSec; 33 } 34 35 void SetSampleTime(int NewSampleTime) 36 { 37 if (NewSampleTime > 0) 38 { 39 double ratio = (double)NewSampleTime 40 / (double)SampleTime; 41 ki *= ratio; 42 kd /= ratio; 43 SampleTime = (unsigned long)NewSampleTime; 44 } 45 }
因此,我們用復合積分項變量替換了 [第4行]偏差求和變量。它計算 Ki * 偏差,而不僅僅是偏差 [第15行]。此外,由於 Ki 現在被隱藏在積分項中,因此它將從主 PID 計算 [第19行] 中刪除。
4、結果
那么,這是如何解決問題的。在修改Ki之前,它重新計算了所有偏差的總和;我們看到的每一個偏差值。有了這段代碼,之前的偏差將保持不變,而新的Ki只會影響事情的進展,這正是我們想要的。
譯注:對於本篇討論的修改整定參數對積分項的影響問題。采用位置式PID公式確實存在這一問題,作者的解決方式也很贊。因為這就是增量式PID積分項的默認處理方式。所以如果采用增量式PID就不會存在這個問題了。
歡迎關注: