基础知识点
场景:
速度信息可以以m/s为单位,或者也可以转换成转速 r/s,而电机的转速是由PWM脉冲宽度来控制的,如何根据速度信息量化成合适的PWM值呢?
比如:现有一辆行驶中的无人车,要求将车速调整至100KM/h,那么应该如何向电机输出PWM值?或换言之,如何控制油门?
调速实现策略由多种,PID其中较为常用。
PID简介
PID算法是一种经典、简单、高效的动态速度调节方式,P代表比例,I代表积分,D代表微分。
PID控制原理框架图:
模拟式PID公式如下:
- e(t)作为 PID 控制的输入;
- u(t)作为 PID 控制器的输出和被控对象的输入;
- Kp 控制器的比例系数;
- Ki控制器的积分时间,也称积分系数;
- Kd控制器的微分时间,也称微分系数。
位置式PID公式如下:
- Kp,Ki,Kd为比例,积分,微分的三个重要参数
- k是采样序列号,k=0,1,2,3…
- Uk第k次采样时刻控制器输出值,直接对应执行机构的输出值
- ek第k次采样时刻偏差,e(k-1)第k-1次采样偏差值,e(k-2)第k-2次采样偏差值
- 位置式pid控制器的输入为系统的偏差值,输出为uk,即偏差的组合
位置式PID是根据编码器的脉冲累加测量电机的位置信息,并与目标值进行比较,得到控制偏差,然后通过对偏差的比例、积分、微信进行控制,使偏差趋向于零的过程。
1.P(比例)——尽快的到达目标值(狠)
如果实现上述场景中的车速控制,一种简单的实现方式是: 确定目标速度,获取当前速度,使用(目标速度-当前速度)*某一系数 计算结果为输出的PWM,再获取当前速度,使用(目标速度-当前速度)*某一系数 计算结果为输出的PWM并输出...如此循环在上述模型中,调速实现是一个闭环,每一次循环都会根据当前时速与目标时速的差值,再乘以以固定系数,计算出需要输出的PWM值,这其中的系数,称之为比例。
2.I(积分)——大限度的接近目标值(准)
上述模型算法中,最终速度与预期速度存在稳态误差,这意味着最终结果可能永远无法达成预期,解决的方法就是使用积分I。每次调速时,输出的PWM还要累加根据积分I计算的结果,以消除静态误差。
①每次循环执行P运算时,会累加运算的结果
②基本算法:I*(误差1+误差2+……)
3.D(微分)——控制目标值的波动范围(稳)
当I值设置的过大时,可能会出先"超速"的情况,超速之后可能需要多次调整,产生系统震荡,解决这种情况可以使用D微分,当速度越是接近目标速度时,D就会越施加反方向力,减弱P的控制,起到类似”阻尼“的作用。通过D的使用可以减小系统震荡。
- 每次循环执行P和I后,都会累加D的运算结果
- 基本算法:D*(本次误差-上次误差)
综上,PID闭环控制实现是结合了比例、积分和微分的一种控制机制,通过P可以以比例的方式计算输出,通过I可以消除稳态误差,通过D可以减小系统震荡,三者相结合,最终是要快速、精准且稳定的达成预期结果,而要实现该结果,还需要对这三个数值反复测试、调整……
PID调试技巧:
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再专把微分加
曲线振属荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢。微分时间应加长
理想曲线两个波,前高后低4比1
一看二调多分析,调节质量不会低
变量区:
FUNCTION_BLOCK PID_INC
VAR_INPUT
MeasurePoint :REAL;(*测量值*)//现在的位置
SetPoint :REAL;(*目标值*)//目标的位置
P :REAL;
I :REAL;
D :REAL;
Ramp :WORD;(*控制周期*)
(*PAR_ZengLiangMax :WORD;(*增量最大值*)*)
PAR_ControlMAX :DINT;(*控制最大值,用于保护被控对象*)
Reset :BOOL;(*停止PID*)
encoderDaoZhuang:BOOL;
END_VAR
VAR_OUTPUT
Control :DINT;(*输出量*)//速度
ZengLiang :INT;(*PID增量*)
END_VAR
VAR
E :REAL :=0;(*当前误差*)
E1 :REAL :=0;(*上次误差*)
E2 :REAL :=0;(*上上次误差*)
INTEGRAL:REAL:=0;(*误差积分*)
count :WORD :=0;(*用于计时*)
PID_Y :DINT :=0;
PIDMax :REAL :=0;
out: INT;
END_VAR
代码区:
IF Reset THEN
E :=0;
E1 :=0;
E2 :=0;
count :=0;
PID_Y:=0;
Control:=0;
INTEGRAL:=0;
ELSE
IF(count >= Ramp)THEN (*Ramp就是控制周期,用count进行循环计时*)
E := -SetPoint + MeasurePoint;
IF encoderDaoZhuang THEN // MeasurePoint 与 SetPoint 输反了 TRUE
E:=-E;
END_IF
INTEGRAL:=E1+E2+E;//积分项为偏差的累计
PID_Y:=REAL_TO_INT( E*P + INTEGRAL*I+((E-E1)*D)) ;(*位置式*)
E2 := E1;
E1 := E;
IF(PID_Y > PAR_ControlMAX)THEN
PID_Y := PAR_ControlMAX;
END_IF
IF(PID_Y < -PAR_ControlMAX)THEN
PID_Y := -PAR_ControlMAX;
END_IF
Control:=PID_Y;
count := 0;
ELSE
count := count + 1;
END_IF
END_IF
调用:
No1PID(
MeasurePoint:=DINT_TO_REAL(g_No1Signedposition) ,
SetPoint:=DINT_TO_REAL(g_Motor.No1Screw.No1SetPositionNormValue),
P:=g_No1MotorPID.KP,
I:=g_No1MotorPID.KI,
D:=g_No1MotorPID.KD,
Ramp:=10,
PAR_ControlMAX:=100000,
Reset:=Reset_PID ,
encoderDaoZhuang:=TRUE,
Control=>No1PIDOUT
);
视频总结:
偏差量从传感器而来,执行量要给传感器,两个不同设备之间的单位不同,数值范围可能会存在差异,可以通过比例系数 p 放大或缩小两者的关系,最后把比例 P 给执行量即可实现比例环节。
偏差量是有正负的,如果偏差量不断朝一个方向出现,说明小球的位置一直达不到目标值,说明比例P小了。
比例P过小,由增幅器I补充;比例P过大,由抑制器削减。
如果比例P小了,偏差量会不断朝一个方向,这时积分I就会不断累加到一个很大的值,来影响执行量,从而对P进行补充;如果在目标附近抖动,偏差量一会正一会负,累加到积分I时,积分I就会不断趋近于0,积分项就不会产生效果了。
增幅器I需要限制,因为如果系统出现意外或者错误,增幅器可能会累加到无线大,会使系统无法运行。
抑制器D: 下一次的偏差量 = 当前偏差量 - 上一次的偏差量,一般经过P的调节后,小球位置会不断接近目标量,所以偏差通常会越来越小,所以,当前偏差量 <上一次的偏差量,即下一次的偏差量常为负值。因此用下一次的偏差量提前参与到计算中,可以防止P过大产生超出目标的问题。
一般开始时P项为正的,D项为负的,调节时,如果小球位置超过目标位置(超调),导致P项为负的,则D项就会变成正的。
P、I 同向,D项相反?
超调是指控制系统在初始阶段产生的超出目标值的响应。
P项和I项过大都会导致系统超调
当P增益设置得过高时,控制器的输出会迅速增大,以尽快减小误差。然而,由于系统的惯性和延迟,过大的输出信号可能会导致系统产生过冲。系统会超过目标值,然后再逐渐回到稳定状态。
当I增益设置过大时,即使系统存在较小的误差,控制器也会累积大量的误差积分。随着时间的推移,误差积分项会趋向于无限增大,这可能导致控制器输出超出合理范围,进而引起系统的超调。
同时,如果系统具有较大的反馈延迟,而I增益设置过大时,控制器对误差的积分响应会滞后于实际需求。当控制器试图通过增加输出来消除误差时,由于滞后效应,控制器可能会过度积累误差,导致系统产生超调。
PID参数调节方式:
为了防止系统产生超调,P一开始要小一点,然后不断调大,把Kp调到某一程度后,会发现实际值不断接近目标值,但一直到不了目标值,存在稳态误差,这时候调节I项,消除稳态误差,I项大一点,消除误差的效果好一点。如果对系统的响应时间有要求(快速响应),则可以适当增大I项。
如果系统出现了超调,导致系统震荡,调节D项,让震荡减弱。但D项不能太大,否则会加大系统的响应时间。
一般的系统用P I就可以了,D只用在震荡明显的系统。
举例1
小车运动到目标位置(100m) 后停止
假设一个控制周期为 1s
如果小车的期望的目标位置为100,现在的实际位置为0,则偏差E=100-0=100,若调节P=0.1,则P控制器输出 P*E=0.1*100=10m/s 的速度给电机,小车向前运动10m;
如果小车的期望的目标位置为100,现在的实际位置为10,则偏差E=100-10=90,若调节P=0.1,则P控制器输出 P*E=0.1*90=9m/s 的速度给电机,小车又向前运动9m;
如果小车的期望的目标位置为100,现在的实际位置为50,则偏差E=100-50=50,若调节P=0.1,则P控制器输出 P*E=0.1*50=5m/s 的速度给电机,小车又向前运动5m;
若希望小车快速的运动到目标位置,则增大p,增加速度。
举例2
无人机悬停高度调节
假设无人机悬停时,4个螺旋桨的转速为100rpm
刚开始时,调节P,开始时偏差E=100-0,若 p=1, 则P控制器输出 P*E=1*100=100rpm 的速度给螺旋桨,此时飞机会在0m悬停。
为了使飞机上升,令p=2,偏差E=100-0,P控制器输出 P*E=2*100=200rpm 的速度给螺旋桨,飞机上升。当上升到P*E=100时,飞机再次悬停。此时E=50,飞机的实际高度为100-50=50m;
当p=100时,偏差E=100-实际位置,P控制器输出 P*(100-实际位置)rpm 的速度给螺旋桨,飞机上升。当上升到P*E=100时,飞机再次悬停。此时E=1,飞机的实际高度为100-1=99m;
可以发现,为了使飞机能够悬停,即 P*(100-实际位置)=100成立,则(100-实际位置)不可能为0,所以只调节 P 飞机悬停的实际高度永远达不到100,系统存在稳态误差。
因此,需要引入 I 项,消除稳态误差。
当 P=100 时,只使用 P 项,飞机最终会悬停在 99m 处,此时系统的偏差 E=1 ,系统的输出P*E=100,如果再引入 I 项,用 I 项将之前的偏差E累加起来,此时系统的输出为 ,大于100rpm,使得飞机再次上升。
当飞机飞到100m时,P*E项=0,P项不起作用了。虽然悬停后偏差E=100-100=0,但 I 项由于也累加了悬停前的偏差E,所以 I 项不是0,悬停的工作就交给了I项。
若P=100,刚开始时E=100-0=100,P*E=10000,飞机会飞的巨快,同理积分项累计的偏差E也会很大(100 90 80 70····),可能会导致飞机飞的超过100m,出现超调。
此时,再引入D项,下一次的偏差量=当前偏差量 - 上一次的偏差量,90-100=-10,80-90,70-80,为负值,微分项 D*(E2-E1)<0,调节D即可消除超调,阻碍无人机的飞行速度。