PID算法详细解读
本文章借鉴网上多位大神的博客以及野火的教程,非原创,主要为按照自己的理解整理。
PID控制算法
基本讲解
PID即:Proportional(比例)、Integral(积分)、Differential(微分)的缩写。也就是说,PID算法是结合这三种环节在一起来实现一个闭环控制。PID控制应该算是应用非常广泛的控制算法了。小到控制一个元件的温度,大到控制无人机的飞行姿态和飞行速度等等,都可以使用PID控制。
以上是一个pid的控制框图,不懂没有关系,只需要了解它的大概执行流程就好。
为什么需要PID三个环节的控制?
我们先说PID中最简单的比例控制,抛开其他两个不谈。还是用一个经典的例子吧。假设我有一个水缸,最终的控制目的是要保证水缸里的水位永远的维持在1米的高度。假设初始时刻,水缸里的水位是0.2米,那么当前时刻的水位和目标水位之间是存在一个误差的error,且error为0.8.这个时候,假设旁边站着一个人,这个人通过往缸里加水的方式来控制水位。如果单纯的用比例控制算法,就是指加入的水量u和误差error是成正比的。即 u=kp×error。
假设kp取0.5,那么t=1时(表示第1次加水,也就是第一次对系统施加控制),那么u=0.5×0.8=0.4,所以这一次加入的水量会使水位在0.2的基础上上升0.4,达到0.6。
接着,t=2时刻(第2次施加控制),当前水位是0.6,所以error是0.4。u=0.5×0.4=0.2,会使水位再次上升0.2,达到0.8。如此这么循环下去,就是比例控制算法的运行方法。可以看到,最终水位会达到我们需要的1米。
但是,单单的比例控制存在着一些不足,其中一点就是 –稳态误差!
像上述的例子,根据kp取值不同,系统最后都会达到1米,只不过kp大了到达的快,kp小了到达的慢一些。不会有稳态误差。但是,考虑另外一种情况,假设这个水缸在加水的过程中,存在漏水的情况,假设每次加水的过程,都会漏掉0.1米高度的水。仍然假设kp取0.5,那么会存在着某种情况,假设经过几次加水,水缸中的水位到0.8时,水位将不会再变换!!!因为,水位为0.8,则误差error=0.2. 所以每次往水缸中加水的量为u=0.5*0.2=0.1.同时,每次加水,缸里又会流出去0.1米的水!!!加入的水和流出的水相抵消,水位将不再变化!!也就是说,我的目标是1米,但是最后系统达到0.8米的水位就不再变化了,且系统已经达到稳定。由此产生的误差就是稳态误差了。(在实际情况中,这种类似水缸漏水的情况往往更加常见,比如控制汽车运动,摩擦阻力就相当于是“漏水”,控制机械臂、无人机的飞行,各类阻力和消耗都可以理解为本例中的“漏水”)
所以,单独的比例控制,在很多时候并不能满足要求。
P I D分别起什么作用
P(Proportional 比例环节)
比例控制算法,我感觉应该是PID算法中比较核心的部分,感觉他是整个PID中的主力,当kp值越大的时候,控制系统的响应速度就越快,但是同时也会带来更大的震荡。至于其他的像积分控制算法,和微分控制算法,是为了消除误差,减少震荡。P的具体作用见上一节介绍。
I(Integral 积分环节)
积分控制算法,就是为了消除稳态误差(在理解上可以参考积分的几何意义),由于积分是从0时刻一直积分到当前时刻 t,并且是对e(t)函数进行积分。
在只有P(比例)环节的时候,在上面我们可以看到,在理想状态下也是可以满足控制需求,但是在真实场景中无法达到。所以**引入I(积分)来消除静态误差。**在到达节点位置之前,e(t)始终是正的,也就是它的积分始终是大于0的,如果系统存在稳态误差的话,由于误差一直不变,但是积分变呀,积分会一直积下去,之前的稳态误差是中和了比例控制算法的值,现在有一个一直增长的积分,导致每次u(t)的输出也在一直的增大,从而稳态误差就被消除了。到最后,误差为零了,而此时的e(t)也为0了,积分也就固定在某一个值了。从而每次的稳态误差就都可以被消除掉。
如果到达节点位置之后了,也就是冲过了节点的指定位置,这时候误差就变为了负的,然后由于积分正负可以相减,同样可以很好的适应这种情况。
D(Differential 微分环节)
用了积分控制算法,现在可以消除稳定误差了,但是考虑下面几种情况:
1.现在的情况是不存在稳态误差,但是存在积分控制算法,那么问题就出现了,当到达了目的位置后,哪怕误差已经是0了,但是积分控制算法那里还是一个整数,导致下一次输出u(t)仍然为一个整数,而不是0,这样的话,就会越过目的位置,虽然之后误差就变成了负数,又会回落回目的位置,但是这样始终是震荡的,而不是一直稳定下去。
2.在初始状态下,如果Kp或者Ki设置的过大,则会导致u(t)的变化幅度过大。
综上,在上述情况下,加入微分控制就很有必要,其实微分控制的作用就是防止幅度过大(防止超调),导致震荡或者超调,微分就是为了在输出斜率变的太大之前,在系统中引入一个有效的早期修正信号。微分可以防止震荡,比如当控制无人机悬停到一定高度,kd的作用就是如何让他停稳。
当存在稳态误差的时候,由于微分对于常数的求导是0,故微分不能解决稳态误差的问题。单独使用意义不大,故需要与比例积分共同配合使用,构成PD或PID控制。
从时间的角度讲,比例作用是针对系统当前误差进行控制,积分作用则针对系统误差的历史,而微分作用则反映了系统误差的变化趋势,这三者的组合是“过去、现在、未来”的完美结合。同样这三个参数也不可以设置的过大,我们要找到一个平衡点(调参)。
PID的两种不同实现方式
数字 PID 控制算法因时间离散化不同,通常分为位置式 PID 控制算法和增量式 PID 控制算法。
位置式PID
也就是位置式PID是当前系统的实际位置,与你想要达到的预期位置的偏差,进行PID控制
因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系,用到了误差的累加值;(误差e会有误差累加),输出的u(k)对应的是执行机构的实际位置,,一旦控制输出出错(控制对象的当前的状态值出现问题 ),u(k)的大幅变化会引起系统的大幅变化
并且位置式PID在积分项达到饱和时,误差仍然会在积分作用下继续累积,一旦误差开始反向变化,系统需要一定时间从饱和区退出,所以在u(k)达到最大和最小时,要停止积分作用,并且要有积分限幅和输出限幅。
而位置式 PID 适用于执行机构不带积分部件的对象,如舵机和平衡小车的直立和温控系统的控制。
缺点:
1)、由于全量输出,所以每次输出均与过去状态有关,计算时要对ek进行累加,工作量大;
2)、因为计算机输出的uk对应的是执行机构的实际位置,如果计算机出现故障,输出的uk将大幅度变化,会引起执行机构的大幅度变化,有可能因此造成严重的生产事故,这在实生产际中是不允许的
3)、如果偏差一直是正的或者负的,位置式PID在积分项会一直累积,因此必须对积分项进行限幅,同时也要对输出进行限幅。当偏差开始反向变化,位置式PID在积分项需要一段时间才能从最大值减下来,造成输出的滞后。
代码实现(C语言)
//相关值结构体
typedef struct
{
int target_val; //目标值
int actual_val; //实际值
int err; //定义偏差值
int err_last; //定义上一个偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
int erradd; //定义积分值
}_pid;
//位置式pid算法实现,可以结合位置式pid算式理解
int PID_realize(uint16_t temp_val,uint16_t speed)
{
pid.target_val=temp_val;
/*计算目标值与实际值的误差*/
pid.err = pid.target_val - speed;
pid.erradd += pid.err;
/*PID算法实现*/
pid.actual_val = pid.Kp * pid.err +
pid.Ki * pid.erradd +
pid.Kd * (pid.err - pid.err_last);
/*误差传递*/
pid.err_last = pid.err;
/*返回当前实际值*/
return pid.actual_val;
}
增量式PID
1、优点
1)、根据增量式PID的表达式可以很好地看出,一旦确定了 KP、TI 、TD,只要使用前后三次测量值的偏差, 即可由公式求出控制增量。而得出的控制量▲uk对应的是近几次位置误差的增量,而不是对应与实际位置的偏差,因此没有误差累加。
2)、增量式PID中不需要累加,计算量小。控制增量Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作。
2、缺点:
1)、积分截断效应大,有稳态误差;
2)、溢出的影响大。有的被控对象用增量式则不太好;
代码实现(C语言)
typedef struct
{
float target_val; //目标值
float actual_val; //实际值
float err; //定义当前偏差值
float err_next; //定义下一个偏差值
float err_last; //定义上一个偏差值
float Kp, Ki, Kd; //定义比例、积分、微分系数
}_pid;
//算法实现
float PID_realize(float temp_val)
{
/*传入实际值*/
pid.actual_val = temp_val;
/*计算目标值与实际值的误差*/
pid.err=pid.target_val-pid.actual_val;
/*PID算法实现*/
float increment_val = pid.Kp*(pid.err - pid.err_next) + pid.Ki*pid.err + pid.Kd*(pid.err - 2 * pid.err_next + pid.err_last);
/*传递误差*/
pid.err_last = pid.err_next;
pid.err_next = pid.err;
/*返回增量值*/
return increment_val;
}
位置式PID与增量式PID对比
- 增量式算法不需要对积分项累加,控制量增量至于近几次误差有关,计算误差对控制量影响较小。而位置式算法要对近几次的偏差进行积分累加,容易产生较大的累加误差。
- 增量式算法控制输出的是控制量增量,并无积分作用,因此该方法适合用于执行机构带积分作用的对象,如步进电机。而位置式算法适合用于执行机构不带积分不见的对象。
- 增量式算法得出的是控制量的增量,例如在阀门控制中,只输出阀门开度的变化部分,误动作影响小,必要时还可通过逻辑判断限制或禁止本次输出,不会严重影响系统的工作;而位置式算法的输出直接对应对象的输出,因此对系统影响较大。
- 在进行PID控制时,位置式PID需要有积分限幅和输出限幅,而增量式只需要输出限幅。
PID 参数选取方法
各个参数特点
- 比例调节作用特点:调节作用快,系统一出现偏差,调节器立即将偏差放大输出;
- 积分调节作用特点:积分调节作用的输出变化与输入偏差的积分成正比,积分调节作用的
输出不仅取决于偏差的大小,还取决于偏差存在的时间,只要有偏差存在, 尽管偏差可能很
小,但它存在的时间越长,输出信号就越大,只有消除偏差,输出才停止变化;
- 微分调节作用特点:微分调节的输出是与被调量的变化率成正比,微分调节越大,越能提
前响应,但是也会将不必要的偏差放大;
试凑法
-
要根据设计系统的具体情况,选择合适的采样周期,多次试凑,选择性能较好的一个作为最后采样周期。早整定参数时必须要认真观察系统的相应情况,根据响应情况来调整参数。
具体方法
- 先是比例,然后积分,最后微分;
- 调试时,将PID参数置于影响最小的位置,即P最大,I最大,D最小;
- 按纯比例系统整定比例度,使其得到比较理想的调节过程曲线,然后再把比例度放大 1.2倍左右,将积分时间从大到小改变,使其得到较好的调节过程曲线;
- 最后在这个积分时间下重新改变比例度,再看调节过程曲线有无改善;
- 如有改善,可将原整定的比例度减少,改变积分时间,这样多次的反复,就可得到合适的比例度和积分时间;
- 如果在外界的干扰下系统稳定性不好,可把比例度和积分时间适当增加一些,使系统足够稳定;
- 将整定好的比例度和积分时间适当减小,加入微分作用,以得到超调量最小、调节作用时间最短的调节过程。
临界比例法
临界比例法:适用于闭环控制系统里将调节器置于纯比例的作用下,从大到小逐渐改变调节器的比例度,并且得到等幅度的震荡过程就叫做临界比例度;
- 1.将调节器的积分置于最大,微分置于 0,比例度系数适当即可平衡一段时间,把系统投放到自动运行中。
- 2.然后将比例逐渐增大,增大到产生等幅现象,并记录下等幅时的临界比例系数(δk)和两个波峰的时间间隔(Tk 单位:min)。
- 3.根据记下的比例系数和周期,采用经验公式,计算调节器的参数。
控制方法 | Kp | Ki | Kd |
---|---|---|---|
P | 2×δk | ---- | ---- |
PI | 2.2×δk | 0.85×Tk | ---- |
PD | 1.8×δk | ---- | 0.1×Tk |
PID | 1.7×δk | 0.5×Tk | 0.125×Tk |
一般调节法
一般步骤为:
a. 确定比例增益 P :确定比例增益 P 时,首先去掉 PID 的积分项和微分项,一般是令 Ti=0、Td=0(具体见 PID 的参数设定说明),使 PID 为纯比例调节。输入设定为系统允许的最大值的 60%~70%,由 0 逐渐加大比例增益 P,直至系统出现振荡;再反过来,从此时的比例增益 P 逐渐减小,直至系统振荡消失,记录此时的比例增益 P,设定 PID 的比例增益 P为当前值的 60%~70%。比例增益 P 调试完成。
b. 确定积分时间常数 Ti 比例增益 P 确定后,设定一个较大的积分时间常数 Ti 的初值,然后逐渐减小 Ti,直至系统出现振荡,之后在反过来,逐渐加大 Ti,直至系统振荡消失。记录此时的 Ti,设定 PID 的积分时间常数 Ti 为当前值的 150%~180%。积分时间常数 Ti 调试完成。
c. 确定积分时间常数 Td 积分时间常数 Td 一般不用设定,为 0 即可。若要设定,与确定 P 和 Ti 的方法相同,取不振荡时的 30%。
d. 系统空载、带载联调,再对 PID 参数进行微调,直至满足要求:理想时间两个波,前高后低 4 比 1。
[参数调整方法参考来源,感兴趣的话可以进去下载]([野火]电机应用开发实战指南-基于STM32 — 野火产品资料下载中心 文档 (embedfire.com))