STM32L476應用開發之七:流量的PID控制


在氣體分析儀使用過程中,為了力求分析結果的准確性,一般要求通過的氣體流量盡可能的穩定。為了保證流量控制的穩定,我們采用PID調節來控制氣路閥門的開度。

1、硬件設計

我們采用的流量計為氣體質量流量計,采用熱式原理,輸出0-5VDC的信號。該流量計如下:

鑒於該流量計的特性,我們設計如下的采集電路來完成流量數據的采集,具體原理圖如下:

 

對於流量控制閥我們選擇了電動比例調節閥,該閥給的電壓不一樣時,其開度是不一樣的,所以可以通過PWM來控制其在0-100%的范圍內開關,從而獲得我們需要的流量。

 

關於PWM部分的電路我們采用TIM定時器產生,通過響應的隔離電路產生幅值為24VDC的PWM波。具體的原理圖如下:

 

2、軟件設計

關於流量的采集與前述的模擬量的采集一致,不再多說。我們主要實驗PID控制以及PWM輸出等部分。

(1)PID控制

PID是控制中最為常見的控制器,其由比例、積分、微分等部分組成,器常見的結構框圖如下所示:

 

這次我們要實現PID控制器,采用增量型算法,具有變積分,梯形積分和抗積分飽和功能,具體的軟件流程圖如下:

 

根據上述流程圖,我們很容易實現PID控制器:

  1 /* PID初始化操作,需在對vPID對象的值進行修改前完成                             */
  2 /* CLASSICPID vPID,通用PID對象變量,實現數據交換與保存                       */
  3 /* float vMax,float vMin,過程變量的最大最小值(量程范圍)                    */
  4 void PIDParaInitialization(CLASSICPID vPID,float vMax,float vMin)
  5 {
  6   vPID->maximum=vMax;                /*輸出值上限*/
  7   vPID->minimum=vMin;                /*輸出值下限*/
  8 
  9   vPID->setpoint=vMin;               /*設定值*/
 10   vPID->kp=0.6;                      /*比例系數*/
 11   vPID->ki=0.03;                     /*積分系數*/
 12   vPID->kd=0.01;                     /*微分系數*/
 13 
 14   vPID->lasterror=0.0;              /*前一拍偏差*/
 15   vPID->preerror=0.0;               /*前兩拍偏差*/
 16   vPID->result=vMin;                /*PID控制器結果*/
 17   vPID->output=0.0;                 /*輸出值*/
 18 
 19   vPID->errorabsmax=(vMax-vMin)*0.8;
 20   vPID->errorabsmin=(vMax-vMin)*0.2;
 21 
 22   vPID->deadband=(vMax-vMin)*0.005;               /*死區*/
 23   vPID->alpha=0.2;                  /*不完全微分系數*/
 24   vPID->deltadiff=0.0;
 25 
 26   vPID->integralValue=0.0;
 27 }
 28 
 29 /* 通用PID控制器,采用增量型算法,具有變積分,梯形積分和抗積分飽和功能         */
 30 /* 微分項采用不完全微分,一階濾波,alpha值越大濾波作用越強                    */
 31 /* CLASSICPID vPID,PID對象變量,實現數據交換與保存                           */
 32 /* float pv,過程測量值,對象響應的測量數據,用於控制反饋                     */
 33 void PIDRegulator(CLASSICPID vPID,float pv)
 34 {
 35   float thisError;
 36   float result;
 37   float factor;
 38   float increment;
 39   float pError,dError,iError;
 40 
 41   thisError=vPID->setpoint-processValue; //得到偏差值
 42   result=vPID->result;
 43   if (ABS(thisError)>vPID->deadband)
 44   {
 45     pError=thisError-vPID->lasterror;
 46     iError=(thisError+vPID->lasterror)/2.0;
 47     dError=thisError-2*(vPID->lasterror)+vPID->preerror;
 48 
 49     //變積分系數獲取
 50     factor=VariableIntegralCoefficient(thisError,vPID->errorabsmax,vPID->errorabsmin);
 51 
 52     //計算微分項增量帶不完全微分
 53     vPID->deltadiff=kd*(1-vPID->alpha)*dError+vPID->alpha*vPID->deltadiff;
 54 
 55     increment=vPID->kp*pError+vPID->ki*factor*iError+vPID->deltadiff;   //增量計算
 56   }
 57   else
 58   {
 59     if((abs(vPID->setpoint-vPID->minimum)<vPID->deadband)&&(abs(pv-vPID->minimum)<vPID->deadband))
 60     {
 61       result=vPID->minimum;
 62     }
 63     increment=0.0;
 64   }
 65 
 66   result=result+increment;
 67 
 68   /*對輸出限值,避免超調和積分飽和問題*/
 69   if(result>=vPID->maximum)
 70   {
 71     result=vPID->maximum;
 72   }
 73   if(result<=vPID->minimum)
 74   {
 75     result=vPID->minimum;
 76   } 
 77 
 78   vPID->preerror=vPID->lasterror;  //存放偏差用於下次運算
 79   vPID->lasterror=thisError;
 80   vPID->result=result;
 81   vPID->output=((result-vPID->minimum)/(vPID->maximum-vPID->minimum))*100.0;
 82 }
 83 
 84 /*變積分系數處理函數,實現一個輸出0和1之間的分段線性函數                    */
 85 /* 當偏差的絕對值小於最小值時,輸出為1;當偏差的絕對值大於最大值時,輸出為0   */
 86 /* 當偏差的絕對值介於最大值和最小值之間時,輸出在0和1之間現行變化             */
 87 /* float error,當前輸入的偏差值                                              */
 88 /* float absmax,偏差絕對值的最大值                                           */
 89 /* float absmin,偏差絕對值的最小值                                           */
 90 static float VariableIntegralCoefficient(float error,float absmax,float absmin)
 91 {
 92   float factor=0.0;
 93 
 94   if(abs(error)<=absmin)
 95   {
 96     factor=1.0;
 97   }
 98   else if(abs(error)>absmax)
 99   {
100     factor=0.0;
101   }
102   else
103   {
104     factor=(absmax-abs(error))/(absmax-absmin);
105   }
106 
107   return factor;
108 }

(2)PWM輸出

PWM輸出較為簡單,關於TIM配置等網上有很多,在此不再多說。根據PID控制器的輸出,我們計算PWM的占空比,通過占空比來調節閥門的開度,從而控制流量大小。

 1 *閥門控制調節*/
 2 void ControlProcess(void)
 3 {
 4   uint16_t TimerPeriod = 0;
 5   uint16_t PWMPulse = 0;
 6   float dutyfactor=0.0;//定義占空比
 7 
 8   vPID.setpoint=aPara.phyPara.flowSetPoint;
 9   PIDRegulation(&vPID, aPara.phyPara.flowMeasuredValue);
10   dutyfactor=vPID.result/ADC1HighRange;
11 
12   /*計算頻率和占空比*/
13   TimerPeriod = PWMTimePeriod;//計算用於設置ARR寄存器的值使產生信號的頻率為17.57 Khz
14   PWMPulse = (uint16_t) ((TimerPeriod - 1)*dutyfactor);//計算CCR1寄存器的值在通道1和1N產生50%占空比,用於TIM1
15 
16   HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//停止PWM
17   PWM_TIM_Configuration(TimerPeriod,PWMPulse);
18   HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//啟動PWM
19 }

3、測試結果

軟件編寫完成,硬件連接好后,運行並在線監控。PID控制器的調節速度還是比較快的,流量也比較穩定。如果進行細致的參數整定應該可以進一步提高控制效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM