~~~~ 最近研究智能小车这个方面,发现这个课题貌似已经被研究透了,仅仅在CSDN中就能搜索到无数的相关博文。但我查看一些博文的时候,隐隐感觉出作者君似乎也仅仅处于似懂非懂的阶段,又或者他用的是春秋笔法所以模糊了一些关键点?为了记录下自己看过的博文并且自我总结一些相关方面,在此提笔记录一下自己的研究过程。
PID是什么?
工业过程中广泛采用的三作用控制器,也称PID控制器(PID controller).
P: (Proportional)比例;
I : (Integral)积分;
D:(Derivative)微分;
时域输出方程:
u ( t ) = K P ∗ e ( t ) + K I ∗ ∫ e ( t ) + K D ∗ d e ( t ) d t u(t)=K_P*e(t) +K_I*\int e(t)+K_D*\frac{de(t)}{dt} u(t)=KP∗e(t)+KI∗∫e(t)+KD∗dtde(t)
编程中我们更多用到的是这个方程的数字式:
U [ k ] = K P ∗ e r r [ k ] + K I ∗ ∑ e r r [ k ] + K D ∗ ( e r r [ k ] − e r r [ k − 1 ] ) U[k]=K_P*err[k]+K_I*\sum err[k]+K_D*(err[k]-err[k-1]) U[k]=KP∗err[k]+KI∗∑err[k]+KD∗(err[k]−err[k−1])
由基本的自控知识可得到传递函数:
G c ( s ) = U ( s ) E ( s ) = K P + K I s + K D ∗ s Gc(s)=\frac{U(s)}{E(s)}=K_P+\frac{K_I}{s}+K_D*s Gc(s)=E(s)U(s)=KP+sKI+KD∗s
其中可调的三个参数就是:
K P K_P KP:比例增益 Proportional gain
K I K_I KI :积分增益 Integral gain
K D K_D KD:微分增益 Derivative gain
在工业中,更多采用传统的PID控制器:
u ( t ) = 100 P ( e ( t ) + 1 T 1 ∫ e ( t ) d t + T D d e ( t ) d t ) ~~~~~~~u(t)=\frac{100}{P}(e(t)+\frac{1}{T_1}\int e(t)dt+T_D\frac{de(t)}{dt}) u(t)=P100(e(t)+T11∫e(t)dt+TDdtde(t))
其中:
P : 比例带(%)
T 1 T_1 T1 :积分时间(s)
T D T_D TD:微分时间(s/min)
对比之前的公式,我们得到:
K P = 100 P K_P = \frac{100}{P} KP=P100
K I = 100 P ∗ 1 T 1 K_I = \frac{100}{P}*\frac{1}{T_1} KI=P100∗T11
K D = 100 P ∗ T D K_D=\frac{100}{P}*T_D KD=P100∗TD
~~~~ 在工业的高精度要求与复杂处理环境下,我们对微积分时间的关注度更高。但在平时的小设计没有必要采用这一套体系。
~~~~ 在实际应用中,反馈测量信号往往混杂高频噪声,微分处理则会放大这些噪声,所以这里我们需要滤波来去除高频噪声。
~~~~ 所以这里我们的微分项在实际实现是采用:
G d ( s ) = K D s τ d s + 1 ~~~~~G_d(s)=\frac{K_Ds}{\tau_d s+1} Gd(s)=τds+1KDs
其中:
τ d \tau_d τd 作为滤波时间常数,远远小于过程本身的时间,可以忽略。
位置式PID与增量式PID区别浅析:参考博文原址
P : e ( k ) = 设 定 值 − 当 前 状 态 值 P: e(k) = 设定值 - 当前状态值 P:e(k)=设定值−当前状态值
I : ∑ e ( i ) = 误 差 的 累 加 I : \sum e(i) = 误差的累加 I:∑e(i)=误差的累加
D : e ( k ) − e ( k − 1 ) = 本 次 误 差 − 上 一 次 的 误 差 D: e(k) - e(k-1) = 本次误差 - 上一次的误差 D:e(k)−e(k−1)=本次误差−上一次的误差
位置式PID是对:当前系统的实际位置与你预期位置的偏差 进行PID控制。
通常PD控制器就可以满足位置式PID:
因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系,用到了误差的累加值;(误差e会有误差累加),输出的u(k)对应的是执行机构的实际位置,,一旦控制输出出错(控制对象的当前的状态值出现问题 ),u(k)的大幅变化会引起系统的大幅变化
并且位置式PID在积分项达到饱和时,误差仍然会在积分作用下继续累积,一旦误差开始反向变化,系统需要一定时间从饱和区退出,所以在u(k)达到最大和最小时,要停止积分作用,并且要有积分限幅和输出限幅。
所以在使用位置式PID时,一般我们直接使用PD控制
而位置式 PID 适用于执行机构不带积分部件的对象,如舵机和平衡小车的直立和温控系统的控制
typedef struct PID
{
float P,I,D,limit;
}PID;
typedef struct Error
{
float Current_Error;//当前误差
float Last_Error;//上一次误差
float Previous_Error;//上上次误差
}Error;
/*!
* @brief 位置式PID
* @since v1.0
* *sptr :误差参数
* *pid: PID参数
* NowPlace:当前位置
* Point: 预期位置
*/
// 位置式PID控制
float PID_Realize(Error *sptr,PID *pid, int32 NowPlace, float Point)
{
int32 iError, // 当前误差
Realize; //实际输出
iError = Point - NowPlace; // 计算当前误差
sptr->Current_Error += pid->I * iError; // 误差积分
sptr->Current_Error = sptr->Current_Error > pid->limit?pid->limit:sptr->Current_Error;//积分限幅
sptr->Current_Error = sptr->Current_Error <-pid->limit?-pid->limit:sptr->Current_Error;
Realize = pid->P * iError //比例P
+ sptr->Current_Error //积分I
+ pid->D * (iError - sptr->Last_Error); //微分D
sptr->Last_Error = iError; // 更新上次误差
return Realize; // 返回实际值
}
Δ u [ k ] = u [ k ] − u [ k − 1 ] \Delta u[k] = u[k]-u[k-1] Δu[k]=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 ] ] =K_P[e[k]-e[k-1]]+K_Ie(k)+K_D[e[k]-2e[k-1]+e[k-2]] =KP[e[k]−e[k−1]]+KIe(k)+KD[e[k]−2e[k−1]+e[k−2]]
P : e ( k ) − e ( k − 1 ) = P: e(k)-e(k-1)= P:e(k)−e(k−1)= 本次误差 - 上一次的误差
I : e ( i ) = I : e(i) = I:e(i)= 误差
D : e [ k ] − 2 e [ k − 1 ] + e [ k − 2 ] ¥ D: e[k]-2e[k-1]+e[k-2]¥ D:e[k]−2e[k−1]+e[k−2]¥ = 本次误差 - 2*上一次的误差+上上次误差
增量式PID的控制量 Δ u ( k ) \Delta u(k) Δu(k)是最近几次误差的增量,而不是实际的误差,没有误差累加
所以增量式PID不需要累加,只需要最近的相邻三次误差就可以通过加权获得比较好的控制效果,而系统出问题时这种PID不会严重影响系统工作。
总结:增量型 PID,是对位置型 PID 取增量,这时控制器输出的是相邻两次采样时刻所计算的位置值之差,得到的结果是增量,即在上一次的控制量的基础上需要增加(负值意味减少)控制量。
typedef struct PID
{
float P,I,D,limit;
}PID;
typedef struct Error
{
float Current_Error;//当前误差
float Last_Error;//上一次误差
float Previous_Error;//上上次误差
}Error;
/*!
* @brief 增量式PID
* @since v1.0
* *sptr :误差参数
* *pid: PID参数
* NowPlace:实际值
* Point: 期望值
*/
// 增量式PID电机控制
int32 PID_Increase(Error *sptr, PID *pid, int32 NowPlace, int32 Point)
{
int32 iError, //当前误差
Increase; //最后得出的实际增量
iError = Point - NowPlace; // 计算当前误差
Increase = pid->P * (iError - sptr->Last_Error) //比例P
+ pid->I * iError //积分I
+ pid->D * (iError - 2 * sptr->Last_Error + sptr->Previous_Error); //微分D
sptr->Previous_Error = sptr->Last_Error; // 更新前次误差
sptr->Last_Error = iError; // 更新上次误差
return Increase; // 返回增量
}
辨析:
增量式与位置式区别:
1。增量式算法不需要做累加,控制量增量的确定仅与最近几次偏差采样值有关,计算误差对控制 量计算的影响较小。而位置式算法要用到过去偏差的累加值,容易产生较大的累加误差。
2。增量式算法得出的是控制量的增量,例如在阀门控制中,只输出阀门开度的变化部分,误动作 影响小,必要时还可通过逻辑判断限制或禁止本次输出,不会严重影响系统的工作。 而位置式的输出直接对应对象的输出,因此对系统影响较大。
3。增量式PID控制输出的是控制量增量,并无积分作用,因此该方法适用于执行机构带积分部件的对象,如步进电机等,而位置式PID适用于执行机构不带积分部件的对象,如电液伺服阀。
4。在进行PID控制时,位置式PID需要有积分限幅和输出限幅,而增量式PID只需输出限幅
位置式PID优缺点:
优点:
①位置式PID是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k)的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构不带积分部件的对象中可以很好应用
缺点:
①每次输出均与过去的状态有关,计算时要对e(k)进行累加,运算工作量大。
增量式PID优缺点:
优点:
①误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。
②手动/自动切换时冲击小,便于实现无扰动切换。当计算机故障时,仍能保持原值。
③算式中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关。
缺点:
①积分截断效应大,有稳态误差;
②溢出的影响大。有的被控对象用增量式则不太好;
G c ( s ) = K P + K I s + K D s = K D s 2 + K P s + K I s = K D ( S 2 + a s + b ) s = K D ( s + z 1 ) ( s + z 2 ) s G_c(s)=K_P+ \frac{K_I}{s}+K_Ds =\frac{K_Ds^2+K_Ps+K_I}{s}\\ =\frac{K_D(S^2+as+b)}{s}=\frac{K_D(s+z_1)(s+z_2)}{s} Gc(s)=KP+sKI+KDs=sKDs2+KPs+KI=sKD(S2+as+b)=sKD(s+z1)(s+z2)
根据数学知识可得:
a = K P K D , b = K I K D a=\frac{K_P}{K_D},b=\frac{K_I}{K_D} a=KDKP,b=KDKI
所以我们可以得知,引用PID会为系统带来一个纯积分环节和两个零点。
原点处的极点可以提高系统的型数,改善稳态性能
两个零点理论上可以在任何位于左半S平面的任意位置
对于有数学模型的系统,自然可以仿真完成整定,但对于一个实际系统,我们可以通过实验来标定。
1.手动标定
1.系统闭环,采取P控制器,设置Ki = 0, Kd = 0, Kp取一个较小的数,
满足系统稳定即可
2.逐渐增加Kp,每次改变控制器参数,都要观察一段时间系统输出量、控
制量,直到闭环系统达到临界稳定,输出量产生等幅度、等周期的持续震荡
记录此时的Kp
3.将Kp减少一半,继续采用P控制器,逐步减少Kp,直到获得4:1衰减震荡
4.固定Kp,设置Kd = 0,采用PI控制器,将Ki从0开始逐渐增大,每次改变
控制器参数,都要观察一段时间系统输出、控制量,直到闭环系统对扰动
的抑制 和/或 对设定值的阶跃响应 达到最佳。
5.固定Kp和Ki,采用PID控制器,将Kd从0开始逐渐增大,每次改变控制器参数
观察系统输出、控制量,直到闭环系统对扰动的抑制 和/或 对设定值的阶跃
相应达到最佳
6.采用PID控制器,在已获得的Kp,Ki,Kd附近,进一步精调控制器参数,直到
得到最满意的系统响应
对于PID的三个参数,对系统阶跃相应的影响:
PID增益 | 百分比超调量 | 调整时间 | 稳态误差 |
---|---|---|---|
增大Kp | 增大 | 影响很小 | 减小 |
增大Ki | 增大 | 增大 | 为0 |
增大Kd | 减小 | 减小 | 没有影响 |
上表仅为参考,现实中情况错综复杂,一定要积极变通。
2.临界比例带法:Z-N法(Zigler-Nichols)
闭环:
这是一套实验得出的方法,目标是使得闭环系统得到4:1衰减振荡的阶跃相应,闭环相应速度较快、振荡适中、扰动抑制能力强。
1.设置Ki = 0, Kd = 0, 采用纯P控制器
2.增大Kp,观测输入、输出,直到系统达到临界稳定,产生幅值和周期不变
的持续振荡
3.记录Kp,成为临界增益Ku;振荡周期称为临界振荡周期Tu
4.选定控制器类型,按闭环Z-N整定规则计算PID各个增益
整定规则:
控制器类型 | Kp | Ki | Kd |
---|---|---|---|
P Gc(s)=Kp | 0.5Ku - | - | |
PI Gc(s)=Kp+Ki/s | 0.45Ku | 0.54Ku/tu | - |
PID Gc(s)=Kp+Ki/s+Kds | 0.6Ku | 1.2Ku/Tu | 0.6KuTu/8 |
其实还有一种开环Z-N手段,这里不再赘述
3.经验法:
1.P控制器:Ki = 0, Kd = 0,选择初始Kp, 观测扰动曲线或设定值响应曲线,
增大或减小Kp,观测曲线是否有所改善,若改善,则继续按此方向整定Kp,
反之,反向整定Kp,直到得到较好的曲线
2.Kp减小0.8倍,从0开始增大Ki,观测曲线,得到较好的响应曲线
3.固定Ki,精调Kp,增大或减小Kp,直到得到较好的响应曲线
4.同里,精调Ki
5.由此得到较好的Kp、Ki
6.若增加微分,则采用类似方法,从0开始整定Kp,并进一步精调Kp、Ki、Kd
也可按照以下初始试凑范围设定PID控制器初始值,然后精调
系统类型 | P(%) | Ti(s) | Td(s) |
---|---|---|---|
温度 | 20-60 | 180-600 | 30-180 |
流量 | 40-100 | 6-60 | - |
压力 | 30-70 | 124-180 | |
液压 | 20-80 |