前面我們發佈了一系列PID控制器相關的文章,包括經典PID控制器以及參數自適應的PID控制器。這一系列PID控制器雖說實現了主要功能,也在實際使用中取得了良好效果,但還有很多的細節部分可以改進以提高性能和靈活性。所以在這篇中我們來討論改進PID控制器以串級調節等複雜控制方式。
1、提出問題
我們前面提到的PID控制器其實都是基於單迴路來考慮的。但有些時候同一個被控對象可能會受到2個控制變量的影響,或者說爲了實現一個被控對象更精確的控制需要同時引入兩個控制變量才能得到更好的效果。這個時候我們可以將對被控對象起主要作用的控制變量定義爲主變量,相應的控制器作爲主控制器;而將對被控對象起次要作用的控制變量定義爲從變量,相應的控制器作爲從控制器。於是一個串級調節系統就建立起來了。
由以上的控制方框圖我們可以知道,如果將副迴路看作一個整體的執行單元的話,主控制迴路就是一個單迴路的PID控制。同樣只考慮副迴路的話也只是一個單迴路的PID控制。但有所不同的是副迴路的設定值並非由我們輸入給它的,而是由主控制器的輸出施加給它的。所以,我們想解決PID控制器的串聯問題,需要考慮的就是處理如何將主控制器輸出施加給副控制器作爲設定的問題。
2、分析設計
我們已經提出了實現PID控制器串級需要考慮的主要問題。接下里我們需要分析採用什麼辦法解決這一問題並將其數字化。在此,我們先來考慮一下幾個方面的問題。
第一個問題是主控制器的輸出方式。一般來說,PID算法輸出的是實際物理量值的大小。在我們的PID控制器中我們輸出了實際物理量值和百分比。
第二個問題是副控制器的輸入方式。對於PID控制器設定值輸入肯定是與控制變量的物理量相對應的。很顯然以主控制器的物理量值作爲副控制器的設定輸入肯定是不合適的。所以我們只有以百分比的方式作爲副控制器設定值的輸入。
第三個問題是主副控制器的結合問題。既然以主控制器百分比輸出作爲副控制器的設定輸入。而副控制器的設定值爲物理量,我們需要根據百分比和副控制變量的量程來獲得副控制器的真正設定值。
第四個問題是PID算法該如何調整。對PID算法的調整並不複雜,事實上我們只需要根據是否是串級來處理設定值就好了。如果不是串級就正常處理;如果是串級就需要根據輸入和量程來計算設定值。我們可以用如下的流程圖來說明:
爲了保持PID控制器算法的嚴謹性,我們並不需要將這段處理設定值的操作添加到PID控制算法內部,而只需要獨立處理完設定值的計算並賦值就可以了。
3、軟件實現
我們已經設計瞭如何實現PID控制器串級的方式。我們還需要將其算法以軟件的方式實現才能真正獲得我們想要的結果。
首先,我們在PID對象類型中添加標識是否爲串級的屬性。這一屬性用於標識這一PID控制器是否處於串級控制狀態。只有副控制器需要設定爲串級狀態。
其次,我們在PID控制器中添加針對串級副控制器設定值輸入的代碼。其實很簡單,就是在串級狀態下,將輸入的設定值百分比在物理量量程下計算爲設定值的最終值。
/* 通用PID控制器,採用增量型算法,具有變積分,梯形積分和抗積分飽和功能,微分項採用不完全微分,一階濾波,alpha值越大濾波作用越強 */
void PIDRegulator(CLASSICPID *vPID)
{
float thisError;
float result;
float factor;
float increment;
float pError,dError,iError;
if(*vPID->pMA<1) //手動模式
{
vPID->output=*vPID->pMV;
//設置無擾動切換
vPID->result=(vPID->maximum-vPID->minimum)*vPID->output/100.0+-vPID->minimum;
*vPID->pSV=*vPID->pPV;
vPID->setpoint=*vPID->pSV;
}
else //自動模式
{
if(vPID->sm==SMOOTH_ENABLE) //設定值平滑變化
{
SmoothSetpoint(vPID);
}
else
{
if(vPID->cas==CASCADE) //串級處理
{
vPID->setpoint=(vPID->maximum-vPID->minimum)*(*vPID->pSV)/100.0+vPID->minimum;
}
else
{
vPID->setpoint=*vPID->pSV;
}
}
thisError=vPID->setpoint-(*vPID->pPV); //得到偏差值
result=vPID->result;
if (fabs(thisError)>vPID->deadband)
{
pError=thisError-vPID->lasterror;
iError=(thisError+vPID->lasterror)/2.0;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
//變積分系數獲取
factor=VariableIntegralCoefficient(thisError,vPID->errorabsmax,vPID->errorabsmin);
//計算微分項增量帶不完全微分
vPID->deltadiff=(*vPID->pKd)*(1-vPID->alpha)*dError+vPID->alpha*vPID->deltadiff;
increment=(*vPID->pKp)*pError+(*vPID->pKi)*factor*iError+vPID->deltadiff; //增量計算
}
else
{
if((fabs(vPID->setpoint-vPID->minimum)<vPID->deadband)&&(fabs((*vPID->pPV)-vPID->minimum)<vPID->deadband))
{
result=vPID->minimum;
}
increment=0.0;
}
//正反作用設定
if(vPID->direct==DIRECT)
{
result=result+increment;
}
else
{
result=result-increment;
}
/*對輸出限值,避免超調和積分飽和問題*/
if(result>=vPID->maximum)
{
result=vPID->maximum;
}
if(result<=vPID->minimum)
{
result=vPID->minimum;
}
vPID->preerror=vPID->lasterror; //存放偏差用於下次運算
vPID->lasterror=thisError;
vPID->result=result;
vPID->output=(vPID->result-vPID->minimum)/(vPID->maximum-vPID->minimum)*100.0;
*vPID->pMV=vPID->output;
}
}
4、總結
這裏我們對PID控制器添加了串級控制的配置參數。當一個PID控制器作爲串級調節的副控制器時,我們將串級配置參數使能,這樣將主調節器的輸出給副調節器的設定時就可實現串級。而此時主控制器的串級配置參數並不需要使能,其設定值由操作者給予。
嚴格來講串級控制並不是一種單獨的控制算法,而是一種控制方式。但爲了實現串級控制方式,我們需要對PID控制算法做必要的適應性修改。