zoukankan      html  css  js  c++  java
  • 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控制器的调节速度还是比较快的,流量也比较稳定。如果进行细致的参数整定应该可以进一步提高控制效果。

  • 相关阅读:
    C# 16进制字节转Int(涉及:Base64转byte数组)
    c# CRC-16 / MODBUS 校验计算方法 及 异或校验算法
    SqlSugar 用法大全
    SQL Server-聚焦NOLOCK、UPDLOCK、HOLDLOCK、READPAST你弄懂多少?
    使用 tabindex 配合 focus-within 巧妙实现父选择器
    DataX 3.0 源码解析一
    Golang必备技巧:接口型函数
    PID控制
    dockerfile,拷贝文件夹到镜像中(不是拷贝文件夹中的内容到镜像)
    什么是PKI?主要作用是什么?
  • 原文地址:https://www.cnblogs.com/foxclever/p/7709372.html
Copyright © 2011-2022 走看看