Chinaunix首页 | 论坛 | 博客
  • 博客访问: 624702
  • 博文数量: 194
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 884
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-21 16:48
文章分类

全部博文(194)

文章存档

2023年(1)

2022年(3)

2021年(16)

2020年(4)

2019年(5)

2018年(10)

2017年(72)

2016年(36)

2015年(47)

我的朋友

分类: 嵌入式

2021-09-25 09:18:23

转:https://www.cnblogs.com/foxclever/p/7709372.html

在气体检测仪使用过程中,为了力求分析结果的准确性,一般要求通过的气体流量尽可能的稳定。为了保证流量控制的稳定,我们采用PID调节来控制气路阀门的开度。

1、硬件设计
我们采用的流量计为气体质量流量计,采用热式原理,输出0-5VDC的信号。该流量计如下:

鉴于该流量计的特性,我们设计如下的采集电路来完成流量数据的采集,具体原理图如下:


对于流量控制阀我们选择了电动比例调节阀,该阀给的电压不一样时,其开度是不一样的,所以可以通过PWM来控制其在0-100%的范围内开关,从而获得我们需要的流量。


关于PWM部分的电路我们采用TIM定时器产生,通过响应的隔离电路产生幅值为24VDC的PWM波。具体的原理图如下:

2、软件设计
关于流量的采集与前述的模拟量的采集一致,不再多说。我们主要实验PID控制以及PWM输出等部分。
(1)PID控制
PID是控制中最为常见的控制器,其由比例、积分、微分等部分组成,器常见的结构框图如下所示:


这次我们要实现PID控制器,采用增量型算法,具有变积分,梯形积分和抗积分饱和功能,具体的软件流程图如下:


根据上述流程图,我们很容易实现PID控制器:

点击(此处)折叠或打开

  1. /* 通用PID控制器,采用增量型算法,具有变积分,梯形积分和抗积分饱和功能 */
  2. /* 微分项采用不完全微分,一阶滤波,alpha值越大滤波作用越强 */
  3. /* CLASSICPID vPID,PID对象变量,实现数据交换与保存 */
  4. /* float pv,过程测量值,对象响应的测量数据,用于控制反馈 */
  5. void PIDRegulator(CLASSICPID vPID,float pv)
  6. {
  7.   float thisError;
  8.   float result;
  9.   float factor;
  10.   float increment;
  11.   float pError,dError,iError;

  12.   thisError=vPID->setpoint-processValue; //得到偏差值
  13.   result=vPID->result;
  14.   if (ABS(thisError)>vPID->deadband)
  15.   {
  16.     pError=thisError-vPID->lasterror;
  17.     iError=(thisError+vPID->lasterror)/2.0;
  18.     dError=thisError-2*(vPID->lasterror)+vPID->preerror;

  19.     //变积分系数获取
  20.     factor=VariableIntegralCoefficient(thisError,vPID->errorabsmax,vPID->errorabsmin);

  21.     //计算微分项增量带不完全微分
  22.     vPID->deltadiff=vPID->kd*(1-vPID->alpha)*dError+vPID->alpha*vPID->deltadiff;

  23.     increment=vPID->kp*pError+vPID->ki*factor*iError+vPID->deltadiff; //增量计算
  24.   }
  25.   else
  26.   {
  27.     if((abs(vPID->setpoint-vPID->minimum)<vPID->deadband)&&(abs(pv-vPID->minimum)<vPID->deadband))
  28.     {
  29.       result=vPID->minimum;
  30.     }
  31.     increment=0.0;
  32.   }

  33.   result=result+increment;

  34.   /*对输出限值,避免超调和积分饱和问题*/
  35.   if(result>=vPID->maximum)
  36.   {
  37.     result=vPID->maximum;
  38.   }
  39.   if(result<=vPID->minimum)
  40.   {
  41.     result=vPID->minimum;
  42.   }

  43.   vPID->preerror=vPID->lasterror; //存放偏差用于下次运算
  44.   vPID->lasterror=thisError;
  45.   vPID->result=result;
  46.   vPID->output=((result-vPID->minimum)/(vPID->maximum-vPID->minimum))*100.0;
  47. }

  48. /*变积分系数处理函数,实现一个输出0和1之间的分段线性函数 */
  49. /* 当偏差的绝对值小于最小值时,输出为1;当偏差的绝对值大于最大值时,输出为0 */
  50. /* 当偏差的绝对值介于最大值和最小值之间时,输出在0和1之间现行变化 */
  51. /* float error,当前输入的偏差值 */
  52. /* float absmax,偏差绝对值的最大值 */
  53. /* float absmin,偏差绝对值的最小值 */
  54. static float VariableIntegralCoefficient(float error,float absmax,float absmin)
  55. {
  56.   float factor=0.0;

  57.   if(abs(error)<=absmin)
  58.   {
  59.     factor=1.0;
  60.   }
  61.   else if(abs(error)>absmax)
  62.   {
  63.     factor=0.0;
  64.   }
  65.   else
  66.   {
  67.     factor=(absmax-abs(error))/(absmax-absmin);
  68.   }

  69.   return factor;
  70. }

(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.   vPID.setpoint=aPara.phyPara.flowSetPoint;
  8.   PIDRegulation(&vPID, aPara.phyPara.flowMeasuredValue);
  9.   dutyfactor=vPID.result/ADC1HighRange;

  10.   /*计算频率和占空比*/
  11.   TimerPeriod = PWMTimePeriod;//计算用于设置ARR寄存器的值使产生信号的频率为17.57 Khz
  12.   PWMPulse = (uint16_t) ((TimerPeriod - 1)*dutyfactor);//计算CCR1寄存器的值在通道1和1N产生50%占空比,用于TIM1

  13.   HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//停止PWM
  14.   PWM_TIM_Configuration(TimerPeriod,PWMPulse);
  15.   HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//启动PWM
  16. }


3、测试结果
软件编写完成,硬件连接好后,运行并在线监控。PID控制器的调节速度还是比较快的,流量也比较稳定。如果进行细致的参数整定应该可以进一步提高控制效果。
阅读(837) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~