PID算法(2) PID算法的应用

先根据上一个章节的结论PID原理的详细推导

1. PID的基本定义

PID,就是比例(proportional)、积分(integral)、微分(derivative),是一种很常见的 控制 算法,常见的PID算法有位置PID、增量PID、串级PID等待。

1.1 场景模拟

我现在有一个这样的需求,需要把加热棒加热稳定到25℃,通过这个场景来理解和应用PID算法,分别使用位置式PID增量式PID来解决这个问题。
假设采样时间是固定的不会动。

2 位置式PID

公式:

u k = P e k + I ∑ k = 1 k e k + D ( e k − e k − 1 ) u_k = Pe_k+I\sum_{k = 1}^k{e_k} + D(e_k - e_{k-1}) uk=Pek+Ik=1kek+D(ekek1)
为了方便后续的理解和代码编写,换一下系数的名称。
u k = K p e k + K i ∑ k = 1 k e k + K d ( e k − e k − 1 ) u_k = K_pe_k+K_i\sum_{k = 1}^k{e_k} + K_d(e_k - e_{k-1}) uk=Kpek+Kik=1kek+Kd(ekek1)
u k u_k uk输入
K p K_p Kp比例增益,是调适参数;
K i K_i Ki积分增益,是调适参数;
K d K_d Kd微分增益,是调适参数;
e k e_k ek误差
∑ k = 1 k e k \sum_{k = 1}^k{e_k} k=1kek误差的积分
( e k − e k − 1 ) (e_k - e_{k-1}) (ekek1)连续两次误差的变化

2.1(比例)P的作用

比例环节可以成比例地反应控制系统的偏差信号,即输出与输入偏差成正比,可以用来减小系统的偏差。此环节的公式如下:
u k = K p e k u_k = K_pe_k uk=Kpek

在这里插入图片描述

根据上面的图,偏差 e k e_k ek 越大则输出 u k u_k uk 越大。由此可见,在比例环节中,比例系数 K p K_p Kp 和偏差 e k e_k ek 越大,则系统消除偏差的时间越短,
K p K_p Kp越大时,蓝色曲线达到目标值的时间就越短,但是蓝色曲线出现的超调和震荡比红色曲线严重,这会使得系统的稳定性下降。所以,我们在设置比例系数的时候,并不是越大越好。

  • 超调 :封顶值与目标值之间的差值
  • 振荡 :系统输出在试图达到期望值时出现来回摆动的现象

2.2 积分(I)的作用

理论上,这样能减小系统的误差,但是实际使用过程中,还有其他的外界影响,摩檫力、温度等待的影响,只有比例项是没有办法满足要求的。

比如说我现在的环境比较冷,环境对加热棒有一个降温的过程。假设 u k u_k uk调节到了20℃,环境对加热棒的影响3分钟降了5℃,那么我PID在调节的过程中,最后阶段输出也是3分钟升了5℃,那么 u k u_k uk的输出刚好被外界的影响所抵消,始终会有一个误差,这个误差会一直存在,所以现在会出现一个情况叫 静态误差

在这里插入图片描述

如果要解决静态误差的影响,那么就需要加入积分项I

在这里插入图片描述

积分环节可以对偏差 e e e 进行积分,只要存在偏差,积分环节就会不断起作用,主要用于消除静态误差,提高系统的无差度。引入积分环节后,比例+积分 环节的公式如下:
u k = K p e + K i ∑ k = 1 k e k u_k = K_pe+K_i\sum_{k = 1}^k{e_k} uk=Kpe+Kik=1kek
从上述公式中可以得知,当积分系数 K i K_i Ki 或者累计偏差越大时,输出就越大,系统消除静态误差的时间就越短

  • 积分分离
    注意!:这个情况需要做积分分离,积分项的选择是动态的,在误差小于20%左右的时候才加入积分项,这样就不会让积分项的超调比较小
  • 积分限幅
    积分限幅是为了限制积分项的值有一个最大值。

积分限幅和积分分离都是为了让积分项不超过一个很大的值。一般来说积分分离和积分限幅选择一个就行了。

2.3 微分(D)的作用

在这里插入图片描述

微分环节的作用是反应系统偏差的一个变化趋势,也可以说是变化率,可以在误差来临之前提前引入一个有效的修正信号,有利于提高输出响应的快速性, 减小被控量的超调和增加系统的稳定性。引入微分环节后,比例+积分+微分环节的公式如下:
u k = K p e + K i ∑ k = 1 k e k + K d ( e k − e k − 1 ) u_k = K_pe+K_i\sum_{k = 1}^k{e_k}+K_d(e_k-e_{k-1}) uk=Kpe+Kik=1kek+Kd(ekek1)

微分环节有助于系统减小超调,克服振荡,加快系统的响应速度,减小调节时间,从而改善了系统的动态性能,但微分时间常数过大,会使系统出现不稳定。微分控制作用一个很大的缺陷是容易引入高频噪声,所有在干扰信号比较严重的流量控制系统中不宜引入微分控制作用。

注意!

不是所有系统都需要比例、积分、微分三个系统,又一些系统需要比例和微风,有一些系统是只要比例,PID的算法怎么使用,应该是根据系统的需求来。

3 增量式 PID公式

  • 思想
    Δ u = u k − u k − 1 \Delta{u} = u_k-u_{k-1} Δu=ukuk1
    • u k = K p e k + K i ∑ k = 1 k e k + K d ( e k − e k − 1 ) u_k = K_pe_k+K_i\sum_{k = 1}^k{e_k}+K_d(e_k-e_{k-1}) uk=Kpek+Kik=1kek+Kd(ekek1)
    • u k − 1 = K p e k − 1 + K i ∑ k = 1 k − 1 e k − 1 + K d ( e k − 1 − e k − 2 ) u_{k-1} = K_pe_{k-1}+K_i\sum_{k = 1}^{k-1}{e_{k-1}}+K_d(e_{k-1}-e_{k-2}) uk1=Kpek1+Kik=1k1ek1+Kd(ek1ek2)
    • u k − u k − 1 = K p ( e k − e k − 1 ) + K i e k + K d ( e k − 2 e k − 1 + e k − 2 ) u_k - u_{k-1} = K_p(e_k-e_{k-1})+K_ie_k+K_d(e_k-2e_{k-1}+e_{k-2}) ukuk1=Kp(ekek1)+Kiek+Kd(ek2ek1+ek2)
  • 公式就为
    Δ u = K p ( e k − e k − 1 ) + K i e k + K d ( e k − 2 e k − 1 + e k − 2 ) \Delta{u} = K_p(e_k-e_{k-1})+K_ie_k+K_d(e_k-2e_{k-1}+e_{k-2}) Δu=Kp(ekek1)+Kiek+Kd(ek2ek1+ek2)

    K p K_p Kp : 比例增益
    K i K_i Ki : 积分增益
    K d K_d Kd : 微分增益
    e k e_k ek : 当前误差
    e k − 1 e_{k-1} ek1 : 上一次误差
    e k − 2 e_{k-2} ek2 : 上上次误差
    u k u_k uk:增量

  • 输出就为:
    u k = u k − 1 + Δ u u_k = u_{k-1}+\Delta{u} uk=uk1+Δu
    u k u_k uk:输出

3.1 位置式PID和增量式PID的不同点

对比项位置式增量式
输出全量输出仅输出增量
偏差一直累计误差只考虑最近3次的偏差
积分作用
限幅需要进行输出和积分限幅只需要进行输出限幅

3.2 位置式PID和增量式PID的优缺点

  • 位置式
    优点:位置式 PID 是一种非递推式算法,可直接控制执行机构(如平衡小车), u k u_k uk 的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构不带积分部件的对象中可以很好应用;
    缺点: 每次输出均与过去的状态有关,计算时要对 e k e_k ek 进行累加,运算工作量大
  • 增量式
    优点:只输出增量,计算错误影响小;不需要累计偏差,运算量少,实时性相对较好。
    缺点:积分截断效应大,有稳态误差;溢出的影响大。有的被控对象用增量式则不太好;

4 PID算法的其他改进

4.1 积分限幅

举例 :使用P和I项进行控制,无人机在地面准备起飞,期望高度是100m。此时一个人摁住无人机,那么误差值一直为100m,控制器P项输出保持不变,控制器I项输出是线性增长的,
一段时间后,那个人突然不摁了,此时控制器I项输出可能非常大,再加上控制器P项输出,控制器给电机的输出非常大,那么无人机速度就非常快并且飞的非常高。对于这种情况,我们对积分限幅,I项增加到一定值时就不再增了,如下图所示,那么无人机在上面这种情况下就不至于飞的很快很高,这就是积分限幅的作用。

4.2 积分分离

举例 :当无人机期望高度为100m而此时也到达了100m的位置,那么误差值为0,控制器P项的输出值为0,由控制器的I项来保持无人机的悬停,由于此时没有误差,因此I项的误差也不再累计,此时如果给无人机一个新的期望高度1000m,那么误差值为900m突然变得很大,导致控制器积分项I也突然变得很大,如下图所示,再加上P项,可能导致无人机最后严重超调一直震荡
这种情况下,我们使用积分分离,对误差进行一个条件判断,例如如果无人机误差超过500m,我们就让积分项I等于0,如果无人机误差低于500m,我们再使用I项,这样I项就不会像前面增长的那么快,使系统可以快速跟随且不至于严重超调
也可以当高度到达设定值的70%以上使用I项,否则使I项等于0。

4.3 微分先行

在这里插入图片描述

某些给定值频繁且大幅变化的场合,微分项常常会引起系统的振荡。为了适应这种给定值频繁变化的场合,人们设计了微分先行算法。微分先行由于微分部分只对测量值起作用所以可以消除设定值突变的影响,还可以引入低通滤波,甚至在必要时将比例作用也可进行相应的改进。其实用于设定值会频繁改变的过程对象,防止设定值的频繁波动造成系统的不稳定。该控制对于改善系统的动态特性是有好处的,但势必影响响应的速度,需全面考虑。
这是一个单独的算法,本章节不说

5 PID算法的C语言实现



typedef enum
{
	MOTOE_FORWORT = 0,
	MOTOE_RETREAT,
}MotorState_u;

typedef enum
{
	INTERSEPA_TRUE,
	INTERSEPA_FALSE,
}InterSepaState_u;

typedef struct __Motor_t
{
	float 		fSpeed;
	uint32_t	ulEncodercount;

}Motor_t;

typedef enum{
    PID_ENHAN       = 0X00U,    /*位置式*/
    PID_LOCATION,               /*增量式*/
}PID_Enhloca_e;

typedef struct _PIDConTer
{
    /* data */
    float fError;       /*本次误差*/
    float fLastError;   /*上一次误差*/
    float fPrevError;   /*上上一次误差*/
    float fError_num;   /*误差和*/
    float fK_p;         /*比例系数*/
    float fK_i;         /*积分系数*/
    float fK_d;         /*微风系数*/
    float fTar_Value;   /*目标值*/
    float fOutValue;    /*PID输出值*/
    float fMaxout_Value;/*输出限幅值*/
    float fMinout_Value;/*输出限幅值*/
    float fPropOut;     /*比例输出*/
    float fIntegrOut;   /*积分输出*/
    float fMaxIntegr;   /*积分上限幅值*/
    float fMinIntegr;   /*积分下限幅值*/
    float fDifferOut;   /*微分输出*/
    float fIntTegpro;   /*积分限幅比例*/
  InterSepaState_u xInteSepaState;/*积分分离标志位*/
}PID_t;



float PID_Limit(float IN,float max,float min)
{
    float OUT = IN;
    if(OUT>max) OUT = max;
    if(OUT<min) OUT = min;
    return OUT;
}

PID_t pid;
void PIN_INIT()
{
    pid.fK_p = 0.00249373700650421;
    pid.fK_i = 0.0498747401300842;
    pid.fK_d = 0;
    pid.fMaxIntegr = 8400-1;
    pid.fMinIntegr = 0;
    pid.fMaxout_Value = 8400-1;
    pid.fMinout_Value = 0;
    pid.fTar_Value = 1000;
    pid.fIntTegpro = 0.4;
    pid.xInteSepaState = INTERSEPA_FALSE;
}

uint32_t PID_Algor(PID_t *pxPID,int Value,PID_Enhloca_e e_Flag)
{
//    static float  vInterPrueK_p ;

//    static float vPropCount = 0;


    pxPID->fError = pxPID->fTar_Value - Value;
    /*位置式PID*/
    if(e_Flag == PID_ENHAN)
    {
        /*使用积分分离*/
        if(pxPID->xInteSepaState == INTERSEPA_TRUE)
        {


            if(fabs((double)Value) > fabs((double)pxPID->fTar_Value * pxPID->fIntTegpro))   /*积分限幅和积分分离*/
            {
                pxPID->fError_num += pxPID->fError;
                pxPID->fIntegrOut = pxPID->fK_i * pxPID->fError_num;
                pxPID->fIntegrOut = PID_Limit(pxPID->fIntegrOut,pxPID->fMaxout_Value,pxPID->fMinout_Value);
            }
            else
            {
                pxPID->fIntegrOut = 0;
                pxPID->fError_num = 0;
//                /*调整微分系数不要让比例一下子过快,因为比例项最后的结果要不超过积分分离的阈值*/
//                if(!vPropCount)
//                {
//										vPropCount++;
//                    vInterPrueK_p = pxPID->fK_p;
//										pxPID->fK_p = vInterPrueK_p*0.1*vPropCount;
//                }
//                else if(vPropCount>=10)
//                {
//                    vPropCount = 0;
//                    pxPID->fK_p = vInterPrueK_p;
//                    vInterPrueK_p = 0;
//                }
//                else
//                {
//                    vPropCount++;
//                    pxPID->fK_p = vInterPrueK_p*0.1*vPropCount;
//                }
            }
        }
        else
        {

            pxPID->fError_num += pxPID->fError;
            pxPID->fIntegrOut = pxPID->fK_i * pxPID->fError_num;
        }

        pxPID->fPropOut = pxPID->fK_p * pxPID->fError;
        pxPID->fDifferOut = pxPID->fK_d *( pxPID->fLastError-pxPID->fError);

        pxPID->fOutValue = pxPID->fPropOut+pxPID->fIntegrOut+pxPID->fDifferOut;
        /*输出限幅*/
        pxPID->fOutValue = PID_Limit((float)pxPID->fOutValue,(float)pxPID->fMaxIntegr,(float)pxPID->fMinIntegr);


        pxPID->fLastError = pxPID->fError;
    }
    else                                                   /*增量型PID*/
    {
        pxPID->fPropOut = (float)pxPID->fK_p * (pxPID->fError - pxPID->fLastError);

        pxPID->fIntegrOut = pxPID->fK_i * pxPID->fError;

        pxPID->fDifferOut = pxPID->fK_d * (pxPID->fError - 2 * pxPID->fLastError + pxPID->fPrevError);

        pxPID->fOutValue += pxPID->fPropOut+pxPID->fIntegrOut+pxPID->fDifferOut;
        /*输出限幅*/
        pxPID->fOutValue = PID_Limit((float)pxPID->fOutValue,(float)pxPID->fMaxIntegr,(float)pxPID->fMinIntegr);

        pxPID->fPrevError = pxPID->fLastError;
        pxPID->fLastError = pxPID->fError;
    }

    return pxPID->fOutValue;
}


6 PID调参

6.1 一般调节法

  • 方法:这种方法针对一般的 PID 控制系统所以称之为一般调节法。
  • 步骤:
    ① 首先将积分、微分系数置零,使系统为纯比例控制。控制对象的值设定为系统允许的最大值的 60%~70%,接着逐渐增大比例系数,直至系统出现振荡;此时再逐渐减小比例系数,直至系统振荡消失,然后记录此时的比例系数,并设定系统的比例系数为当前值的 60%~70%。
     
    ② 确定比例系数后,设定一个较小的积分系数,然后逐渐增大积分系数,直至系统出现振荡;此时在逐渐减小积分系数,直至系统振荡消失,然后记录此时的积分系数,并设定系统的积分系数为当前值的 55%~65%。
     
    ③ 微分系数一般不用设定,为 0 即可。若系统出现小幅度振荡,并且通过 PI 环节无法优化,这可以采用与确定比例、积分系数相同的方法,微分系数取系统不振荡时的 30%左右。
     
    ④ 系统空载、带载联调,再对 PID 参数进行微调,直至满足要求。

 
PID算法的参数调试是指通过调整控制参数(比例增益、积分增益/时间、微分增益/时间)让系统达到最佳的控制效果。

调试中稳定性(不会有发散性的震荡)是首要条件,此外,不同系统有不同的行为,不同的应用其需求也不同,而且这些需求还可能会互相冲突。下面大概有一个图
在这里插入图片描述

PID算法只有三个参数,在原理上容易说明,但PID算法参数调试是一个困难的工作,因为要符合一些特别的判据,而且PID控制有其限制存在。

6.2 各种方法对比

方法优点缺点
人工调试不需要教学需要有精要的工程师
齐格勒 - 尼科尔斯方法被证实有效的方法,可以在线调试会影响制程,需要试误,得到的参数可能使响应太快
软件工具调试的一致性,可以配合计算机自动设计,包括感测器的分析,可以进行模拟需要成本和训练
Cohen-Coon好的程序模型需要一些教学,只对一阶系统有良好的效果

6.3 调整PID参数对系统的影响

调整方式到达时间超调量安定时间稳态误差稳定性
K p K_p Kp减小↓增加↑小幅增加 ↗ \nearrow 减少↓变差↓
K d K_d Kd小幅减小 ↘ \searrow 增加↑增加↑大幅减少 ⇓ \Downarrow 变差变差↓
K i K_i Ki小幅减小 ↘ \searrow 减少↓减少↓变动不大 → \rightarrow 变好↑

7 串级PID

   三环 PID 控制就是将三个 PID 控制系统(例如:转向环节、直立环以及速度环)串联起来,对 转向系统 的输出进行偏差计算,计算结果作为 直立环系统 的输入,然后 直立环 的偏差计算作为输入,计算结果作为 速度环 的输入。
总的来说,就是对前一个系统(外环)的输出进行偏差的计算,计算结果作为后一个系统(内环)的输入

注意:平衡小车之家的代码实现使用的是并级PID不是串级PID

  • 举例
    使用平衡小车作为例子,小车需要直立,并且速度可以控制,而且还可以转向,平衡小车的PID控制框图如下图。

在这里插入图片描述

  • 外环------->内环
    • 脉冲数越来越大
    • 响应速度越来越开

注意:这里的比较都是脉冲数进行比较


文章是自己总结而记录,有些知识点没说明白的,请各位看官多多提意见,多多交流,欢迎大家留言
如果技术交流可以加以下群,方便沟通

  • 22
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

^Lim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值