改進初學者的PID-手自動切換

  最近看到了Brett Beauregard發表的有關PID的系列文章,感受對於理解PID算法頗有幫助,因而將系列文章翻譯過來!在自我提升的過程當中,也但願對同道中人有所幫助。做者Brett Beauregard的原文網址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner’s-pid-onoff/算法

 

1、問題所在函數

  有一個 PID 控制器雖然是很好的,但你並非何時都須要它。oop

 

  假設在程序中的某個時刻,您但願將輸出強制爲某個值 (例如 0),您固然能夠在調用例程中執行此操做:spa

1 void loop()
2 {
3   Compute();
4   Output=0;
5 }

  這樣,不管 PID 輸出是什麼,您只需覆蓋其值。然而,這在實踐中是一個可怕的想法。PID 會變得很是混亂:「我一直髮送輸出,可是什麼都沒有發生!到底發生了什麼事? !我再發送一下。」所以,當您中止覆蓋輸出並切換回 PID 時,您可能會當即獲得一個巨大的輸出值改變。翻譯

2、解決方案code

  解決這個問題的辦法是有辦法關閉和打開 PID。這些狀態的經常使用術語是 "手動" (我將手動調整輸出值) 和 "自動" (PID 將自動調整輸出)。讓咱們看看這是如何在代碼中完成的。blog

3、代碼get

 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 double outMin,outMax;
 8 bool inAuto = false;
 9  
10 #define MANUAL 0
11 #define AUTOMATIC 1
12  
13 void Compute()
14 {
15    if(!inAuto) return;
16    unsigned long now = millis();
17    int timeChange = (now - lastTime);
18    if(timeChange>=SampleTime)
19    {
20       /*Compute all the working error variables*/
21       double error = Setpoint - Input;
22       ITerm+= (ki * error);
23       if(ITerm> outMax) ITerm= outMax;
24       else if(ITerm< outMin) ITerm= outMin;
25       double dInput = (Input - lastInput);
26  
27       /*Compute PID Output*/
28       Output = kp * error + ITerm- kd * dInput;
29       if(Output > outMax) Output = outMax;
30       else if(Output < outMin) Output = outMin;
31  
32       /*Remember some variables for next time*/
33       lastInput = Input;
34       lastTime = now;
35    }
36 }
37  
38 void SetTunings(double Kp,double Ki,double Kd)
39 {
40   double SampleTimeInSec = ((double)SampleTime)/1000;
41    kp = Kp;
42    ki = Ki * SampleTimeInSec;
43    kd = Kd / SampleTimeInSec;
44 }
45  
46 void SetSampleTime(int NewSampleTime)
47 {
48    if (NewSampleTime > 0)
49    {
50       double ratio  = (double)NewSampleTime
51                       / (double)SampleTime;
52       ki *= ratio;
53       kd /= ratio;
54       SampleTime = (unsigned long)NewSampleTime;
55    }
56 }
57  
58 void SetOutputLimits(double Min,double Max)
59 {
60    if(Min > Max) return;
61    outMin = Min;
62    outMax = Max;
63    
64    if(Output > outMax) Output = outMax;
65    else if(Output < outMin) Output = outMin;
66  
67    if(ITerm> outMax) ITerm= outMax;
68    else if(ITerm< outMin) ITerm= outMin;
69 }
70  
71 void SetMode(int Mode)
72 {
73   inAuto = (Mode == AUTOMATIC);
74 }

  一個至關簡單的解決方案。若是您不在自動模式下,請當即離開計算函數,而不調整 "輸出" 或任何內部變量。it

4、最終結果io

 

  的確,您能夠經過不象例程那樣調用計算來實現相似的效果,但此解決方案保持PID所包含的工做原理,這是咱們所須要的。經過保持事物的內部過程,咱們能夠跟蹤處於哪一種模式中,更重要的是,當咱們改變模式時,它讓咱們知道有哪些工做須要進行。這就引出了下一期.....。

歡迎關注:

相關文章
相關標籤/搜索