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

  我们已经设计了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;                   //微分系数指针
#else
    float *pPb;                   //比例带
    float *pTi;                   //积分时间,单位为秒
    float *pTd;                   //微分时间,单位为秒
    float ts;                     //采样周期,单位为秒
#endif

    float 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;
#else
    if((*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);
#endif
    
    if(*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控制器,对超调的抑制作用是非常明显的。但需要指出的是如果设定值平滑的步进值设置过小或是输出增量限幅的阈值过小将会使得调节过程极其缓慢。
  一般来说象温度、物位等滞后相对比较大的系统使用设定值平滑会有比较好的效果,而增加输出增量限幅则可能会调节的比较缓慢。而流量、压力等滞后相对较小的系统使用输出增量限幅会有比较好的效果,而增加设定值平滑则有可能是的调节变得缓慢。
  最后我们简单说一下调节周期的问题。调节周期的选择是一个需要认真考虑的问题。即使我们采用相同的参数整定,采用相同的防超调处理,当调节周期不同时,效果可能会有较大差异,所以调节周期必须确定好。一般来说,滞后大的系统调节周期需要设置的长一点,而滞后小的系统调节周期需要设置的短一点,具体还需要根据控制要求来设置。

欢迎关注:

  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
常用的温度检测元件主要有热电偶、热电阻、热敏电阻等。热电偶主要是利用两种不同金属的热电效应,产生接触电势随温度变化而变化,从而达到测温的目的。测量准确,价格适中测温范围宽,线性度较好。但其输出电压受冷端温度影响,需要进行冷端温度补偿,使电路变得复杂,在本题中并非最佳方案。 热敏电阻由金属氧化物或半导体材料成,灵敏度高、热惰性小、寿命长、价格便宜。但其测量的稳定性和复现性差,测量精度无法满足本题发挥部分0.2℃的要求。而且线性度差,需要进行查表线性拟合,大大浪费控的资源,因此不能选用。 热电阻是利用金属的电阻率随温度变化而变化的特性,将温度量转化成电阻量。其优点是准确度高,稳定性高,性能可靠,热惯性小、复现性好,价格适中。但电阻值与温度是非线性关系,Pt100热电阻,当0℃<t<850℃时可用下式表示: 其中A=3.9083╳10-3 /℃;B=-5.775╳10-7 /℃;由此可见,温度越高非线性误差越大,本题目要求温控范围是40℃~90℃,温度较低。经计算当温度为90℃时,非线性误差为0.34%,运用最小二乘法适当的进行零点和增益的调整,还可使此误差降低一倍,而本题要求精度为,0.2/90=0.22%,因此在本题中可以选用Pt100热电阻,并可近似将其电阻值与温度看作线性关系。 2、 放大电路 热电阻所测得的是电阻量,需要转化为电压量才能被控采集。最基本的电阻-电压转换电路是将其与另一固定电阻串联,但这种方法,当温度为量程下限时输出不为零,这样不利于小信号的放大和提高A/D转换的精度。因此,本作品采用桥路测量,电路如图2所示: 其中R1R2为10kΩ固定电阻,Rt为热电阻,Rw2为调零电阻,由于 ,因此上下两支路电流相等,并保持恒定不变,输出电压 ,可调整Rt0=Rw2,使得 由于在桥路中R1很大,使得输出量uo变化很小,当Rt从0到100℃变化时,输出仅有十几毫伏,因此还需要进行小信号放大。本作品所用低频增益可调放大电路如图3: 其中Rw1为增益电阻,用于调整测量满量程,运放采用低噪声NE5532,令R1=R2,R3=R4,R5=R6,则该放大电路总增益为 ,当Rw1从0到50kΩ变化时,Av的变化范围为150至+∞,满足所需增益要求。 3、 A/D转换 题目所要求测量度精度为0.2℃,测温的范围应该为室温到要求的最高温度,即20~90℃,这就决定了A/D转换的最低分辨率不低于0.2/(90-20)=1/350,而普通八位A/D转换芯片只能达到1/256,不能满足要求。而如果选用更高位的芯片,将大大增加成本。温度是一种变化时间常数较大的物理量,对A/D转换速度要求不高,因此,在设计中选用了压控振荡,先将电压信号转化为频率量,再通过控的计数功能转化为数字信号,这样可以大大提高精度,节约成本。 压控振荡如图4所示: 电容C1充电周期为 ,放电周期为 ,由于 所以 ,所以其振荡频率可近似看作与输入电压Ui成正比。但当频率较高时,仍有较大(约为5%)非线性误差,不能满足题目要求。因此,在作品中利用FPGA的优点,该测频率为测正脉冲宽度,再通过单片机求倒数,这样即可完全消除非线性误差。 4、 控 对水温的反馈偏差控,就必然用到经典控理论中的PID(Proportional Integral and Derivative比例积分微分)控,控可有多种选择,如模拟电路、单片机、逻辑件等。 模拟电路控可对偏差变化进行连续的控,技术成熟,性能较稳定。但其缺点是不便于显示,调整PID参数需更换元件,易受到外界干扰等,在现在这个数字化高度发展的时代已趋于淘汰。 单片机作为微型计算机的一个分支,已有二十多年的发展,在各控领域都有广泛的应用。而近年以FPGA(现场可编程门阵列)为代表的可编程逻辑件异军突起,其优异的性能大大弥补了单片机响应速度慢、中断源少的缺点。但FPGA的运算能力有限,因此,在我们的设计中采用FPGA与单片机相结合的控方式,二者优势互补,性能大大提高。 在本作品中,FPGA主要负责接收压控振荡的信号,通过测量其正脉宽而获得电压量;单片机接收FPGA发送的数据,进行显示、PID运算,和输出。 5、 输出驱动电路 控将其PID运算的结果转化为不同占空比的脉冲信号输出,该信号作用于执行机构还需要经过驱动电路。 本作品中采用交流调功电路,即将负载与交流电源接通几个周波,再断开几个周波,通过改变开通与断开周波的比值来调节负载所消耗的平均功率。具体实现电路如图5。 将220V/50Hz的市电,经电阻分压到5V以下,输入运放的同相输入端,运放作为过零比较,当市电过零时,产生跳变,运放输出送到D触发的时钟端,D触发输入接单片机输出的脉冲信号,输出接双向晶闸管的门极。这样,只有当交流电过零时,单片机的输出信号才对晶闸管产生作用,也就是说,只有当交流电过零时,晶闸管才能开通或关断。这样可以大大减小开通关断过程中对晶闸管的冲击,减少开通关断损耗。 二、 控软件设计 1、 FPGA程序设计 在本作品中,FPGA的主要功能是测量压控振荡输出高脉宽的时间。由于压控振荡的频率较低(0,则输出脉冲的占空比增加1%,反之减小1% 为了确定PID参数,根据容加热、传热的公式,列出加热容的微分方程,经拉氏变换后得到一个一阶滞后环节,其传递函数约为 ,对整个控回路用Matlab中的Simulink工具箱进行方针,其框图如图8 图中step为输入阶跃给定信号,step1为干扰量,A中存储输出占空比,scope显示输出波形(图9a),scope1显示占空比值(图9b)。 图9a 图9b 当t=10时刻,给定值输入阶跃量,t=100时刻,输入干扰阶跃量。由此可见,本系统可以以较小的超调和较短的调节时间达到稳定状态,并对于干扰有较好的控作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值