我们已经设计了PID控制器,并根据实际使用的情况对器进行了诸多的改进。在这一篇中我们将讨论如何改进PID控制器超调的问题。

1、问题提出

  在前面的文章中,我们曾推导过增量式PID控制器的公式,并且对其进行了离散化以适用于程序实现,具体的离散化公式如下:

  以这个公式为基础,我们实现的增量式PID控制器,只需要根据偏差计算增量并调整输出就能实现自动调节了。但是我们分析一下就会发现,如果参数设置的不合适,或者偏差的数值比较大,那么计算得到的增量值就会很大,这样输出的变化就会很大,这种情况下就容易出现超调的问题。
超调一旦出现,可能需要较长时间才能让系统稳定,严重的甚至会造成振荡。这自然不是我们想要的结果,所以我们希望PID控制器具有能够防止超调能力。

2、分析设计

  关于超调这个问题,我们先来分析一下什么因素能够造成超调。所谓超调我们可以理解为过度的调整反而造成了系统的不稳定。那究竟哪些情况会造成过度调整呢?一般来讲过于频繁的调节、输入信号的突然大幅度变化、输出信号的陡变以及被控对象的特性。
  对于上述情况我们来逐一分析一下应对办法。首先是过于频繁的调节,很多时候我们可能觉得调节的快可以加快系统的响应。但实际上与系统本身的特性有关。如果系统不存在滞后或者滞后的特性很小,自然是没有问题的。但很多时候,系统会存在比较大的滞后特性,那么过于频繁的调节就会快速累积输出控制从而产生超调。这种情况下我们可以增大调节周期来稳定系统。
  其次我们来看输入信号的突然大幅度变化的影响。我们这里所说的输入信号是指PID控制器的设定值。在一个稳定系统中,大幅度改变设定值会使偏差急剧增大,而大的偏差往往会造成控制器的输出快速累积,这种快速累积往往就会造成超调。这种情况下,我们可以控制设定值的变化速度来改善。一般让设定值线性缓慢变化,至于步进值则可根据系统的特性调整。
  再来看看输出信号的陡变的影响,有些时候因为参数设置与系统的匹配问题,即使偏差变化不大输出的变化也会很大。这个时候控制变量会因此而产生较大变化,这一变化会增大偏差,进一步影响输出,如此循环累积就可能产生超调。特别是一些反应比较快的系统更容易出现这种情况。一般我们可以通过限制输出的变化来防止这种现象。
  而被控对象的特性主要表现在系统的滞后特性方面,一般来说越是滞后的系统越不容易调稳,也越是容易出现超调甚至振荡。应对这一情况一般也可以采用减缓调节的方式来调整。具体方式也是前面的三种。

3、软件实现

  我们已经分析了产生超调的主要原因以及应对的办法,接下来我们就来考虑怎么改进PID控制器以达到防超调的效果。针对前述提到的几种情况我们来分别设计软件上的实现方式。
  对于调节相对频繁的问题,我们的PID控制器设计时就已考虑到采样周期是可调整的,所以我们只需根据不同的被控对象来适当地调整它就好了。而对于设定值的大幅度突变和调节输出的陡变两种情况,我们引入两个参数,一个参数用于开关设定值时平滑处理功能,一个参数用于设置输出增量限幅功能的开关。我们采用两个枚举来实现这一功能,具体定义如下:

/*定义设定值平滑枚举类型*/
typedef enum ClassicPIDSM{SMOOTH_DISABLE,       //不启用设定值平滑SMOOTH_ENABLE         //启用设定值平滑
}ClassicPIDSMType;/*定义防止输出陡变的枚举*/
typedef enum ClassicPIDPAC{PREVENT_ABRUPT_DISABLE,       //不启用输出防陡变PREVENT_ABRUPT_ENABLE         //启用输出防陡变
}ClassicPIDPACType;

  同样的我们需要在PID对象类型中增加相应的属性。我们为PID控制器对象类型添加设定值平滑参数以及输出增量限幅参数,所以我们实现PID控制器的对象类型定义如下:

/*定义PID对象类型*/
typedef struct CLASSIC
{float *pPV;                   //测量值指针float *pSV;                   //设定值指针float *pMV;                   //输出值指针uint16_t *pMA;               //手自动操作指针#if PID_PARAMETER_STYLE > (0)float *pKp;                   //比例系数指针float *pKi;                   //积分系数指针float *pKd;                   //微分系数指针
#elsefloat *pPb;                   //比例带float *pTi;                   //积分时间,单位为秒float *pTd;                   //微分时间,单位为秒float ts;                     //采样周期,单位为秒
#endiffloat setpoint;               //设定值float lasterror;              //前一拍偏差float preerror;               //前两拍偏差float deadband;               //死区float result;                 //PID控制器计算结果float output;                 //输出值0-100%float maximum;                //输出值上限float minimum;                //输出值下限float errorabsmax;            //偏差绝对值最大值float errorabsmin;            //偏差绝对值最小值float alpha;                  //不完全微分系数float deltadiff;              //微分增量float integralValue;          //积分累计量float gama;                   //微分先行滤波系数float lastPv;                 //上一拍的过程测量值float lastDeltaPv;            //上一拍的过程测量值增量ClassicPIDDRType direct;      //正反作用ClassicPIDSMType sm;          //设定值平滑ClassicPIDCSType cas;         //串级设定ClassicPIDPACType pac;        //输出防陡变
}CLASSICPID;

  修改了PID控制器对象的定义,我们还需要对PID控制器做必要的改进。我们添加设定值平滑操作,并通过设置参数sm来控制是否启用该操作。我们添加输出防陡变的操作,并通过配置参数pac来决定是否启用。具体实现如下:

void PIDRegulator(CLASSICPID *vPID)
{float thisError;float result;float factor;float increment;float pError,dError,iError;float kp,ki,kd;#if PID_PARAMETER_STYLE > (0)kp=*vPID->pKp;ki=*vPID->pKi;kd=*vPID->pKd;
#elseif((*vPID->pTi)<vPID->ts){*vPID->pTi=vPID->ts;}kp=100.0/(*vPID->pPb);ki=kp*(vPID->ts/(*vPID->pTi));kd=kp*((*vPID->pTd)/vPID->ts);
#endifif(*vPID->pMA<1)      //手动模式{vPID->output=*vPID->pMV;//设置无扰动切换vPID->result=(vPID->maximum-vPID->minimum)*vPID->output/(float)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)/(float)100.0+vPID->minimum;}else{vPID->setpoint=*vPID->pSV;}}thisError=vPID->setpoint-(*vPID->pPV); //得到偏差值result=vPID->result;if (fabsf(thisError)>vPID->deadband){pError=thisError-vPID->lasterror;iError=(thisError+vPID->lasterror)/(float)2.0;dError=thisError-2*(vPID->lasterror)+vPID->preerror;//变积分系数获取factor=VariableIntegralCoefficient(thisError,vPID->errorabsmax,vPID->errorabsmin);//计算微分项增量带不完全微分vPID->deltadiff=kd*(1-vPID->alpha)*dError+vPID->alpha*vPID->deltadiff;increment=kp*pError+ki*factor*iError+vPID->deltadiff;   //增量计算}else{if((fabsf(vPID->setpoint-vPID->minimum)<vPID->deadband)&&(fabsf((*vPID->pPV)-vPID->minimum)<vPID->deadband)){result=vPID->minimum;}increment=0.0;}//输出变化幅度if(vPID->pac==PREVENT_ABRUPT_ENABLE){increment=fabsf(increment)>fabsf(thisError)?thisError:increment;}//正反作用设定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)*(float)100.0;*vPID->pMV=vPID->output;}
}

  在这里我们将设定值平滑的步进值按量程比例固定了,但实际上设定值平滑的步进值应该根据采样周期来调整。并且在不同的被控系统中也应该做适当调整。而输出防陡变的阈值我们采用了偏差值。

4、总结

  在这一篇中,我们分析了引起超调的几点原因并思考了各自的应对策略。依据这些,我们改进了PID控制器使其具备有防超调的基本功能。我们在温度控制和流量控制中实际使用了改进过的PID控制器,对超调的抑制作用是非常明显的。但需要指出的是如果设定值平滑的步进值设置过小或是输出增量限幅的阈值过小将会使得调节过程极其缓慢。
  一般来说象温度、物位等滞后相对比较大的系统使用设定值平滑会有比较好的效果,而增加输出增量限幅则可能会调节的比较缓慢。而流量、压力等滞后相对较小的系统使用输出增量限幅会有比较好的效果,而增加设定值平滑则有可能是的调节变得缓慢。
  最后我们简单说一下调节周期的问题。调节周期的选择是一个需要认真考虑的问题。即使我们采用相同的参数整定,采用相同的防超调处理,当调节周期不同时,效果可能会有较大差异,所以调节周期必须确定好。一般来说,滞后大的系统调节周期需要设置的长一点,而滞后小的系统调节周期需要设置的短一点,具体还需要根据控制要求来设置。

欢迎关注:

PID控制器改进笔记之七:改进PID控制器之防超调设定相关推荐

  1. PID控制器开发笔记之七:微分先行PID控制器的实现

    前面已经实现了各种的PID算法,然而在某些给定值频繁且大幅变化的场合,微分项常常会引起系统的振荡.为了适应这种给定值频繁变化的场合,人们设计了微分先行算法. 1.微分先行算法的思想 微分先行PID控制 ...

  2. PID控制器开发笔记之一:PID算法原理及基本实现

           在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于 ...

  3. PID控制器改进笔记之五:改进PID控制器之串级设定

    前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器.这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性 ...

  4. PID控制器开发笔记之二:积分分离PID控制器的实现

    前面的文章中,我们已经讲述了PID控制器的实现,包括位置型PID控制器和增量型PID控制器.但这个实现只是最基本的实现,并没有考虑任何的干扰情况.在本节及后续的一些章节,我们就来讨论一下经典PID控制 ...

  5. PID控制器开发笔记之八:带死区的PID控制器的实现

    在计算机控制系统中,由于系统特性和计算精度等问题,致使系统偏差总是存在,系统总是频繁动作不能稳定.为了解决这种情况,我们可以引入带死区的PID算法. 1.带死区PID的基本思想 带死区的PID控制算法 ...

  6. PID控制器开发笔记(转)

    源: PID控制器开发笔记 转载于:https://www.cnblogs.com/LittleTiger/p/10499701.html

  7. PID控制器概述及python实现PID控制算法

    PID控制器简要分析 PID控制器概述 PID控制器的分类 位置式PID 增量式PID 代码实现 参数整定 PID控制器概述 PID控制器是自动控制领域一种常见的控制器,其简单易设计的结构和良好的鲁棒 ...

  8. PID控制器开发笔记之十三:单神经元PID控制器的实现

    神经网络是模拟人脑思维方式的数学模型.神经网络是智能控制的一个重要分支,人们针对控制过程提供了各种实现方式,在本节我们主要讨论一下采用单神经元实现PID控制器的方式. 1.单神经元的基本原理 单神经元 ...

  9. PID控制器开发笔记之十一:专家PID控制器的实现

    前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法,基本已经覆盖了无模型和简单模型PID控制经典算法的大部.再接下来的我们将讨论智能PID控制,智能PID控制不同于常规意义下的智能控制,是 ...

最新文章

  1. 继承和多态 3.0 -- 菱形继承
  2. 【java】【转】Java之classpath
  3. python基础===使用switch方法,减少使用if语句
  4. 分布式系统优势及衡量指标
  5. 如何从零开始开发一款嵌入式产品(20年的嵌入式经验分享学习)
  6. python单元测试的应用_单元测试pythongui应用程序的推荐方法是什么?
  7. apache axis 1.4的invoke方法设置超时_Kubernetes 网络故障常见排查方法
  8. html5画布作品,HTML5 canvas画布
  9. win8更改计算机锁屏时间,win8如何设置电脑屏保时间设置方法
  10. 2007-2018年软考高级之系统分析师真题及答案解析
  11. Power BI(十九)power pivot之常用筛选器函数
  12. 编程题(买帽子求第三便宜价格)
  13. 3、HeidiSQL数据库管理工具下载与安装
  14. 土法炼钢:怎么实现一个简单的B+Tree In-Disk
  15. maya导入模型后贴图没渲染怎么办?
  16. 前端js获取图片大小 扩展名_前端获取图片存储大小的方法
  17. PTA-整除光棍(C语言)
  18. 八爪鱼软件爬取数据的操作流程
  19. Description: A component required a bean of type ‘com.jia.dao.UserDao‘ that
  20. 高等数学A(一)第一章笔记分享

热门文章

  1. 转:曾国藩的“拙”式领导力
  2. 行远技术征程,策马求索
  3. Nginx Rewrite重写
  4. 微信小程序歌曲列表页实现
  5. 不同国家的小数点给开发者带来的困扰
  6. rectangle c语言,C语言,rectangle() ZeroMemory()这两个函数不太理解 求高人指点一下简单用法 及格式......
  7. wsdl文件转换为java代码
  8. [Mapbox GL]点的动画效果
  9. z77用m2固态_老Z97主板全部升级nvme m2固态,彻底放弃HDD
  10. python 小工具实现 windows笔记本与 ipad数据互传