改進初學者的PID-正副作用

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

 

1、問題所在函數

  將PID鏈接過程分爲兩組:直接做用和反向做用。到目前爲止,我所展現的全部例子都是直接行動。也就是說,輸出的增長會致使輸入的增長。對於反向做用過程,狀況正好相反。例如,在冰箱中,冷卻水的增長會致使溫度降低。要使初學者 PID 使用反向過程,kp、ki 和 kp 的符號都必須爲負數。spa

這自己不是問題,但用戶必須選擇正確的符號,並確保全部參數都具備相同的符號。翻譯

2、解決方案code

  爲了讓這個過程簡單一點,我要求 kp、ki 和 kp 都是大於等於0的。若是用戶鏈接到反向進程,則使用SetControllerDirection函數指定反向進程。這能夠確保全部參數都具備相同的符號,並使事情操做起來更直觀。blog

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 double outMin,outMax;  8 bool inAuto = false;  9  
 10 #define MANUAL 0
 11 #define AUTOMATIC 1
 12  
 13 #define DIRECT 0
 14 #define REVERSE 1
 15 int controllerDirection = DIRECT;  16  
 17 void Compute()  18 {  19    if(!inAuto) return;  20    unsigned long now = millis();  21    int timeChange = (now - lastTime);  22    if(timeChange>=SampleTime)  23  {  24       /*Compute all the working error variables*/
 25       double error = Setpoint - Input;  26       ITerm+= (ki * error);  27       if(ITerm > outMax) ITerm= outMax;  28       else if(ITerm < outMin) ITerm= outMin;  29       double dInput = (Input - lastInput);  30  
 31       /*Compute PID Output*/
 32       Output = kp * error + ITerm- kd * dInput;  33       if(Output > outMax) Output = outMax;  34       else if(Output < outMin) Output = outMin;  35  
 36       /*Remember some variables for next time*/
 37       lastInput = Input;  38       lastTime = now;  39  }  40 }  41  
 42 void SetTunings(double Kp,double Ki,double Kd)  43 {  44    if (Kp<0 || Ki<0|| Kd<0) return;  45  
 46   double SampleTimeInSec = ((double)SampleTime)/1000;  47    kp = Kp;  48    ki = Ki * SampleTimeInSec;  49    kd = Kd / SampleTimeInSec;  50  
 51   if(controllerDirection ==REVERSE)  52  {  53       kp = (0 - kp);  54       ki = (0 - ki);  55       kd = (0 - kd);  56  }  57 }  58  
 59 void SetSampleTime(int NewSampleTime)  60 {  61    if (NewSampleTime > 0)  62  {  63       double ratio  = (double)NewSampleTime  64                       / (double)SampleTime;  65       ki *= ratio;  66       kd /= ratio;  67       SampleTime = (unsigned long)NewSampleTime;  68  }  69 }  70  
 71 void SetOutputLimits(double Min,double Max)  72 {  73    if(Min > Max) return;  74    outMin = Min;  75    outMax = Max;  76  
 77    if(Output > outMax) Output = outMax;  78    else if(Output < outMin) Output = outMin;  79  
 80    if(ITerm > outMax) ITerm= outMax;  81    else if(ITerm < outMin) ITerm= outMin;  82 }  83  
 84 void SetMode(int Mode)  85 {  86     bool newAuto = (Mode == AUTOMATIC);  87     if(newAuto == !inAuto)  88     {  /*we just went from manual to auto*/
 89  Initialize();  90  }  91     inAuto = newAuto;  92 }  93  
 94 void Initialize()  95 {  96    lastInput = Input;  97    ITerm = Output;  98    if(ITerm > outMax) ITerm= outMax;  99    else if(ITerm < outMin) ITerm= outMin; 100 } 101  
102 void SetControllerDirection(int Direction) 103 { 104    controllerDirection = Direction; 105 }

4PID 完成get

  差很少結束了。咱們已經把「初學者的PID」變成了我目前知道的最健壯的控制器。對於那些正在尋找PID庫的詳細解釋的讀者,我但願您獲得了您想要的。對於那些正在編寫本身的PID的人,我但願您可以收集到一些想法,這些想法能夠爲您節省一些時間。數學

最後說明兩點:it

  1. 若是這個系列中的東西看起來不對,請告訴我。我可能錯過了什麼,或者可能只須要在個人解釋中更清楚。不管哪一種方式,我都想知道。
  2. 這只是一個基本的PID。爲了簡單起見,我有意省略了許多其餘問題。在個人腦海中:前饋,重置平鋪,整數數學,不一樣的PID形式,使用速度而不是位置。若是有興趣讓我探討這些話題,請讓我知道。

歡迎關注:

相關文章
相關標籤/搜索