手把手教你看懂並理解Arduino PID控制庫——初始化

引子

本文將分析《手把手教你看懂並理解Arduino PID控制庫》中:初始化的問題函數

問題定義

先看問題的圖示:ui

上一節,討論的是PID控制由開轉關的過程當中存在的問題,那麼緊接着上一節,若是在關閉後,忽然再次開啓,那麼會產生什麼問題呢?直觀來看,對於被控量會出現圖中,綠色線的一個bump,這個bump是因爲由關轉開的一瞬間,輸出忽然放大,那麼對於靈敏度高的系統,則會出現,滯後大的系統可能不會如此明顯,但無論怎麼說,爲了杜絕一切不利因素,咱們都應該想辦法消除這個bump。因爲這個bump的根因是因爲輸出的突變而形成的,因此須要想辦法控制這個輸出的突變。spa

解決方案

想想,全部此類問題都是發生在時間軸上的,那麼PID控制中時間軸會影響的項只有積分項和微分項(能夠想象,比例向爲Kp * (設定值 - 被控量),這是一個連續量,不存在突變的可能(除非是採樣時間特別長,在改變輸出前,被控量飛上天了),因此只須要從這兩項上想辦法,控制住這兩項的突變,便可控制住輸出的突變。首先問題發生在PID關閉轉開啓的過程當中,因爲PID開啓關閉控制的函數是SetMode,因此在此函數中,增長一個initial函數用於控制積分項和微分項便可。具體作法是:.net

一、更新微分項上一次採樣值爲PID開啓一瞬間的採樣值,這樣能夠保持微分項維持在上一次開啓結束的狀態不變。code

二、將積分項設置爲當前的輸出,爲何要這麼作呢?積分項因爲PID關閉長時間維持關閉前的狀態,一旦開啓,若是不改變積分項,輸出會瞬間被拉回到上一次開啓結束的狀態,突變就這樣產生了blog

代碼

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
double outMin, outMax;
bool inAuto = false;
 
#define MANUAL 0
#define AUTOMATIC 1
 
void Compute()
{
   if(!inAuto) return;
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
      double error = Setpoint - Input;
      ITerm+= (ki * error);
      if(ITerm> outMax) ITerm= outMax;
      else if(ITerm< outMin) ITerm= outMin;
      double dInput = (Input - lastInput);
 
      /*Compute PID Output*/
      Output = kp * error + ITerm- kd * dInput;
      if(Output> outMax) Output = outMax;
      else if(Output < outMin) Output = outMin;
 
      /*Remember some variables for next time*/
      lastInput = Input;
      lastTime = now;
   }
}
 
void SetTunings(double Kp, double Ki, double Kd)
{
  double SampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki * SampleTimeInSec;
   kd = Kd / SampleTimeInSec;
}
 
void SetSampleTime(int NewSampleTime)
{
   if (NewSampleTime > 0)
   {
      double ratio  = (double)NewSampleTime
                      / (double)SampleTime;
      ki *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}
 
void SetOutputLimits(double Min, double Max)
{
   if(Min > Max) return;
   outMin = Min;
   outMax = Max;
    
   if(Output > outMax) Output = outMax;
   else if(Output < outMin) Output = outMin;
 
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}
 
void SetMode(int Mode)
{
    bool newAuto = (Mode == AUTOMATIC);
    if(newAuto && !inAuto)
    {  /*we just went from manual to auto*/
        Initialize();
    }
    inAuto = newAuto;
}
 
void Initialize()
{
   lastInput = Input;
   ITerm = Output;
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}

結論

圖片說明一切。。。。。圖片

NOTE:若有不足之處請告知。^.^get

下一章將介紹若是在系統運行過程當中,控制方向對系統的影響it

NEXTio

PS:轉載請註明出處:歐陽天華

相關文章
相關標籤/搜索