目录
前言
本篇文章仅为个人笔记,不是教程
本文所参考的文章
【基础知识】PID(比例微分积分)控制
改进的PID算法
PID控制器算法系列
PID算法简单分类(改进PID之间可以结合使用)
- 基础PID
- 位置式PID算法
- 增量式PID算法
- 带死区的PID算法
- 积分改进PID
- 积分分离PID算法
- 抗积分饱和PID算法
- 梯形积分PID算法
- 变速积分PID算法
- 微分改进PID
- 不完全微分PID算法
- 微分先行PID算法
连续型PID算法
输入量为rin(t),输出量为rout(t),偏差为err(t)=rin(t)-rout(t)。
U
(
t
)
=
k
p
(
e
r
r
(
t
)
+
1
T
I
∫
e
r
r
(
t
)
d
t
+
T
D
d
e
r
r
(
t
)
d
t
)
U(t)=k_p\bigl( err(t)+\frac 1{T_I}\int err(t)dt+ T_D\frac {derr(t)}{dt} \bigr)
U(t)=kp(err(t)+TI1∫err(t)dt+TDdtderr(t))
其中Kp为比例带,TI为积分时间,TD为微分时间。
离散型PID算法
输入量为rin(k),输出量为rout(k),偏差为err(k)=rin(k)-rout(k)。
位置式PID算法
基本公式
U
(
k
)
=
K
p
(
e
r
r
(
k
)
+
T
T
I
∑
j
=
0
k
e
r
r
(
j
)
+
T
D
T
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
)
U(k)=K_p \Bigl (err(k)+\frac T{T_I}\sum_{j=0}^{k} err(j)+\frac {T_ D}T\bigl (err(k)-err(k-1)\bigr ) \Bigr)
U(k)=Kp(err(k)+TITj=0∑kerr(j)+TTD(err(k)−err(k−1)))
其中T为系统采样周期时间,K表示第K个采样周期。
也可以简写为:
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
K
d
∗
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
U(k)=K_p*err(k)+K_i\sum_{j=0}^{k} err(j)+K_d*\big (err(k)-err(k-1)\big )
U(k)=Kp∗err(k)+Kij=0∑kerr(j)+Kd∗(err(k)−err(k−1))
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;}
特点
- 位置型PID控制的输出与整个过去的状态有关,用到了偏差的累加值,容易产生累积偏差。
- 位置型PID适用于执行机构不带积分部件的对象。
- 位置型的输出直接对应对象的输出,对系统的影响比较大。
增量式PID算法
基本公式
Δ
U
(
k
)
=
U
(
k
)
−
U
(
k
−
1
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
e
r
r
(
k
)
+
K
d
(
e
r
r
(
k
)
−
2
∗
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
\begin{aligned} \Delta U(k) &= U(k)-U(k-1)\\ &=K_p\big (err(k)-err(k-1)\big )\\&+K_i*err(k)\\&+K_d\big (err(k)-2*err(k-1)+err(k-2)\big) \end{aligned}
ΔU(k)=U(k)−U(k−1)=Kp(err(k)−err(k−1))+Ki∗err(k)+Kd(err(k)−2∗err(k−1)+err(k−2))
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 增量型PID算法不需要做累加,控制量增量的确定仅与最近几次偏差值有关,计算偏差的影响较小。
- 增量型PID算法得出的是控制量的增量,对系统的影响相对较小。
- 采用增量型PID算法易于实现手动到自动的无扰动切换。
积分分离PID算法
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
β
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
K
d
∗
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
U(k)=K_p*err(k)+\beta K_i\sum_{j=0}^{k} err(j)+K_d*\big (err(k)-err(k-1)\big )
U(k)=Kp∗err(k)+βKij=0∑kerr(j)+Kd∗(err(k)−err(k−1))
其中β称为积分开关系数,其取值范围为:
β
=
{
0
∣
e
r
r
(
k
)
∣
>
ξ
1
∣
e
r
r
(
k
)
∣
≤
ξ
\beta= \begin{cases} 0& \vert err(k) \vert\gt\xi\\1& \vert err(k) \vert\leq\xi\end{cases}
β={01∣err(k)∣>ξ∣err(k)∣≤ξ
根据实际情况,设定一个阈值
ξ
\xi
ξ;当偏差大于阈值时,消除积分仅用PD控制;当偏差小于等于阈值时,引入积分采用PID控制。
简单实现
staticuint16_tBetaGeneration(float error,float epsilon){uint16_t beta=0;if(abs(error)<= epsilon){
beta=1;}return beta;}typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值float epsilon;//偏差检测阈值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;uint16_t beta=BetaGeneration(error,vPID->epsilon);if(beta>0){
vPID->result=vPID->proportiongain*thisError+
vPID->derivativegain*(thisError-vPID->lasterror);}else{
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);}
vPID->lasterror=thisError;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
β
K
i
∗
e
r
r
(
k
)
+
K
d
(
e
r
r
(
k
)
−
2
∗
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
\begin{aligned} \Delta U(k) &=K_p\big (err(k)-err(k-1)\big )\\&+\beta K_i*err(k)\\&+K_d\big (err(k)-2*err(k-1)+err(k-2)\big) \end{aligned}
ΔU(k)=Kp(err(k)−err(k−1))+βKi∗err(k)+Kd(err(k)−2∗err(k−1)+err(k−2))
其中β称为积分开关系数,其取值范围为:
β
=
{
0
∣
e
r
r
(
k
)
∣
>
ξ
1
∣
e
r
r
(
k
)
∣
≤
ξ
\beta= \begin{cases} 0& \vert err(k) \vert\gt\xi\\1& \vert err(k) \vert\leq\xi\end{cases}
β={01∣err(k)∣>ξ∣err(k)∣≤ξ
简单实现
staticuint16_tBetaGeneration(float error,float epsilon){uint16_t beta=0;if(abs(error)<= epsilon){
beta=1;}return beta;}typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值float epsilon;//偏差检测阈值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;uint16_t beta=BetaGeneration(error,vPID->epsilon);if(beta>0){
increment=vPID->proportiongain*pError+
vPID->derivativegain*dError;}else{
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;}
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 偏差值较大时,取消积分作用,以免于超调量增大。
- 偏差值较小时,引入积分作用,以便消除静差,提高控制精度。
抗积分饱和PID算法
原理
积分饱和就是指系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而扩大,从而导致控制器输出不断增大超出正常范围进入饱和区。当系统出现反响的偏差时,需要首先从饱和区退出,而不能对反向的偏差进行快速的响应。
抗积分饱和算法,其思路是在计算U(k)的时候,先判断上一时刻的控制量U(k-1)是否已经超出了限制范围。若U(k-1)>Umax,则只累加负偏差;若U(k-1)<Umin,则只累加正偏差。从而避免控制量长时间停留在饱和区。
位置式PID算法
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值float maximum;//最大值float minimum;//最小值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;
thisError=vPID->setpoint-processValue;if(vPID->result>vPID->maximum){if(thisError<=0){
vPID->integral+=thisError;}}elseif(vPID->result<vPID->minimum){if(thisError>=0){
vPID->integral+=thisError;}}else{
vPID->integral+=thisError;}
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;}
增量式PID算法
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值float maximum;//最大值float minimum;//最小值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=0;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;if(vPID->result>vPID->maximum){if(thisError<=0){
iError=thisError;}}elseif(vPID->result<vPID->minimum){if(thisError>=0){
iError=thisError;}}else{
iError=thisError;}
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 解决积分饱和的问题
梯形积分PID算法
原理
在PID控制其中,积分项的作用是消除余差,为了尽量减小余差,应提高积分项的运算精度。在积分项中,默认是按矩形方式来计算积分,将矩形积分改为梯形积分可以提高运算精度。
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
e
r
r
(
j
−
1
)
2
+
K
d
∗
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
U(k)=K_p*err(k)+K_i\sum_{j=0}^{k} \frac {err(j)+err(j-1)}2 +K_d*\big (err(k)-err(k-1)\big )
U(k)=Kp∗err(k)+Kij=0∑k2err(j)+err(j−1)+Kd∗(err(k)−err(k−1))
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;
thisError=vPID->setpoint-processValue;
vPID->integral+=(thisError+vPID->lasterror)/2;
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
U
(
k
)
−
U
(
k
−
1
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
e
r
r
(
k
)
+
e
r
r
(
k
−
1
)
2
+
K
d
(
e
r
r
(
k
)
−
2
∗
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
\begin{aligned} \Delta U(k) &= U(k)-U(k-1)\\ &=K_p\big (err(k)-err(k-1)\big )\\&+K_i*\frac {err(k)+err(k-1)}2\\&+K_d\big (err(k)-2*err(k-1)+err(k-2)\big) \end{aligned}
ΔU(k)=U(k)−U(k−1)=Kp(err(k)−err(k−1))+Ki∗2err(k)+err(k−1)+Kd(err(k)−2∗err(k−1)+err(k−2))
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=(thisError+vPID->lasterror)/2;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 梯形积分相较于矩形积分其精度有比较大的提高,所以对消除余差也就越有效
变速积分PID算法
原理
在普通的PID控制算法中,由于积分系数Ki是常数,所以在整个控制过程中,积分增量是不变的。然而,系统对于积分项的要求是,系统偏差大时,积分作用应该减弱甚至是全无,而在偏差小时,则应该加强。积分系数取大了会产生超调,甚至积分饱和,取小了又不能短时间内消除静差。
变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小相对应:偏差越大,积分越慢; 偏差越小,积分越快。
设定系数为f(err(k)),它是err(k)的函数。当|err(k)|增大时,f减小,反之增大。变积分的PID积分项表达式为:
U
i
(
k
)
=
K
i
{
f
(
e
r
r
(
k
)
)
∗
e
r
r
(
k
)
+
∑
j
=
0
k
−
1
e
r
r
(
j
)
}
U_i(k)=K_i\Big\{ f\big (err(k)\big )*err(k)+\sum_{j=0}^{k-1}err(j)\Big\}
Ui(k)=Ki{f(err(k))∗err(k)+j=0∑k−1err(j)}
其中f(err(k))与|err(k)|的函数关系可根据具体情况设定,可以是线性的也可以是非线性的,通常比较简单的设置如下:
f
(
e
r
r
(
k
)
)
=
{
1
∣
e
r
r
(
k
)
∣
>
ξ
0
∣
e
r
r
(
k
)
∣
≤
ξ
f\big(err(k)\big)=\begin{cases} 1& \vert err(k) \vert\gt\xi\\0& \vert err(k) \vert\leq\xi\end{cases}
f(err(k))={10∣err(k)∣>ξ∣err(k)∣≤ξ
f
(
e
r
r
(
k
)
)
=
{
1
∣
e
r
r
(
k
)
∣
≤
B
A
+
B
−
∣
e
r
r
t
(
k
)
∣
A
B
<
∣
e
r
r
(
k
)
∣
≤
A
+
B
0
∣
e
r
r
(
k
)
∣
>
A
+
B
f\big(err(k)\big)=\begin{cases}1 & \vert err(k)\vert\leq B \\\frac{A+B-\vert errt(k)\vert}{A} & B\lt\vert err(k)\vert\leq A+B\\0 & \vert err(k)\vert\gt A+B\end{cases}
f(err(k))=⎩⎨⎧1AA+B−∣errt(k)∣0∣err(k)∣≤BB<∣err(k)∣≤A+B∣err(k)∣>A+B
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
{
f
(
e
r
r
(
k
)
)
∗
e
r
r
(
k
)
+
∑
j
=
0
k
−
1
e
r
r
(
j
)
}
+
K
d
∗
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
U(k)=K_p*err(k)+K_i\Big\{ f\big (err(k)\big )*err(k)+\sum_{j=0}^{k-1}err(j)\Big\} +K_d*\big (err(k)-err(k-1)\big )
U(k)=Kp∗err(k)+Ki{f(err(k))∗err(k)+j=0∑k−1err(j)}+Kd∗(err(k)−err(k−1))
简单实现
staticfloatVariableIntegralCoefficient(floaterror,float absmax,float absmin){float factor=0.0;if(abs(error)<=absmin){
factor=1.0;}elseif(abs(error)>absmax){
factor=0.0;}else{
factor=(absmax-abs(error))/(absmax-absmin);}
returnfactor;}typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值float errorabsmax;//偏差绝对值最大值float errorabsmin;//偏差绝对值最小值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float factor;
thisError=vPID->setpoint-processValue;
factor=VariableIntegralCoefficient(thisError, vPID->errorabsmax,vPID->errorabsmin);
vPID->integral+= factor*thisError;
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
f
(
e
r
r
(
k
)
)
∗
e
r
r
(
k
)
+
K
d
(
e
r
r
(
k
)
−
2
∗
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
\begin{aligned} \Delta U(k) &=K_p\big (err(k)-err(k-1)\big )\\&+K_i*f\big (err(k)\big)*err(k)\\&+K_d\big (err(k)-2*err(k-1)+err(k-2)\big) \end{aligned}
ΔU(k)=Kp(err(k)−err(k−1))+Ki∗f(err(k))∗err(k)+Kd(err(k)−2∗err(k−1)+err(k−2))
简单实现
staticfloatVariableIntegralCoefficient(floaterror,float absmax,float absmin){float factor=0.0;if(abs(error)<=absmin){
factor=1.0;}elseif(abs(error)>absmax){
factor=0.0;}else{
factor=(absmax-abs(error))/(absmax-absmin);}
returnfactor;}typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值float errorabsmax;//偏差绝对值最大值float errorabsmin;//偏差绝对值最小值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;float factor;
thisError=vPID->setpoint-processValue;
factor=VariableIntegralCoefficient(thisError, vPID->errorabsmax,vPID->errorabsmin);
pError=thisError-vPID->lasterror;
iError=factor*thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
不完全微分PID算法
原理
微分项有引入高频干扰的风险,但若在控制算法中加入低通滤波器,则可使系统性能得到改善。方法之一就是在PID算法中加入一个一阶低通滤波器。这就是所谓的不完全微分。
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
U
d
(
k
)
U(k)=K_p*err(k)+K_i\sum_{j=0}^{k} err(j)+U_d(k)
U(k)=Kp∗err(k)+Kij=0∑kerr(j)+Ud(k)
U
d
(
k
)
=
K
d
(
1
−
α
)
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
α
U
d
(
k
−
1
)
U_d(k)=K_d(1-\alpha)\big(err(k)-err(k-1)\big)+\alpha U_d(k-1)
Ud(k)=Kd(1−α)(err(k)−err(k−1))+αUd(k−1)
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float lastdev;//前一拍时的微分项值float alpha;//不完全微分系数float result;//输出值float integral;//积分值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float thisDev;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;
thisDev=vPID->derivativegain*(1-vPID->alpha)*(thisError-vPID->lasterror)+
vPID->alpha*vPID->lastdev;
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
thisDev;
vPID->lasterror=thisError;
vPID->lastdev=thisDev;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
e
r
r
(
k
)
+
Δ
U
d
(
k
)
\Delta U(k) =K_p\big (err(k)-err(k-1)\big )+K_i*err(k)+\Delta U_d(k)
ΔU(k)=Kp(err(k)−err(k−1))+Ki∗err(k)+ΔUd(k)
Δ
U
d
(
k
)
=
K
d
(
1
−
α
)
(
e
r
r
(
k
)
−
2
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
+
α
Δ
U
d
(
k
−
1
)
\Delta U_d(k)=K_d(1-\alpha)\big(err(k)-2err(k-1)+err(k-2)\big)+\alpha\Delta U_d(k-1)
ΔUd(k)=Kd(1−α)(err(k)−2err(k−1)+err(k−2))+αΔUd(k−1)
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float lastdeltadev;//前一拍时的微分项增量float alpha;//不完全微分系数float result;//输出值}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float deltaDev;float pError,dError,iError;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
deltaDev=vPID->derivativegain*(1-vPID->alpha)*dError+
vPID->alpha*vPID->lastdeltadev;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
deltaDev;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->lastdeltadev=deltaDev;
vPID->result+=increment;}
特点
- 不完全微分方式在微分环节采用了低通滤波有效地提高了微分项的特性。其中α的取值是一个0~1之间的数。两个极限值,在0时其实就是没有滤波的普通微分环节;而取1时,则没有微分作用。
微分先行PID算法
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
U
d
(
k
)
U(k)=K_p*err(k)+K_i\sum_{j=0}^{k} err(j)+U_d(k)
U(k)=Kp∗err(k)+Kij=0∑kerr(j)+Ud(k)
U
d
(
k
)
=
(
γ
K
d
γ
K
d
+
K
p
)
U
d
(
k
−
1
)
+
(
K
d
+
K
p
γ
K
d
+
K
p
)
y
(
k
)
+
(
K
d
γ
K
d
+
K
p
)
y
(
k
−
1
)
U_d(k)=\Big(\frac{\gamma K_d}{\gamma K_d+K_p}\Big)U_d(k-1)+\Big(\frac{K_d+K_p}{\gamma K_d+K_p}\Big)y(k)+\Big(\frac{K_d}{\gamma K_d+K_p}\Big)y(k-1)
Ud(k)=(γKd+KpγKd)Ud(k−1)+(γKd+KpKd+Kp)y(k)+(γKd+KpKd)y(k−1)
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值float derivative;//微分项float lastPv;//前一拍的测量值float gama;//微分先行滤波系数}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float c1,c2,c3,temp;
thisError=vPID->setpoint-processValue;
vPID->integral+=thisError;
temp=vPID->gama*vPID->derivativegain+vPID->proportiongain;
c3=vPID->derivativegain/temp;
c2=(vPID->derivativegain+vPID->proportiongain)/temp;
c1=vPID->gama*c3;
vPID->derivative=c1*vPID->derivative+c2*processValue+c3*vPID->lastPv;
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivative;
vPID->lasterror=thisError;
vPID->lastPv=processValue;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
e
r
r
(
k
)
+
Δ
U
d
(
k
)
\Delta U(k) =K_p\big (err(k)-err(k-1)\big )+K_i*err(k)+\Delta U_d(k)
ΔU(k)=Kp(err(k)−err(k−1))+Ki∗err(k)+ΔUd(k)
Δ
U
d
(
k
)
=
(
γ
K
d
γ
K
d
+
K
p
)
Δ
U
d
(
k
−
1
)
+
(
K
d
+
K
p
γ
K
d
+
K
p
)
Δ
y
(
k
)
+
(
K
d
γ
K
d
+
K
p
)
Δ
y
(
k
−
1
)
\Delta U_d(k)=\Big(\frac{\gamma K_d}{\gamma K_d+K_p}\Big)\Delta U_d(k-1)+\Big(\frac{K_d+K_p}{\gamma K_d+K_p}\Big)\Delta y(k)+\Big(\frac{K_d}{\gamma K_d+K_p}\Big)\Delta y(k-1)
ΔUd(k)=(γKd+KpγKd)ΔUd(k−1)+(γKd+KpKd+Kp)Δy(k)+(γKd+KpKd)Δy(k−1)
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float lastdeltadev;//前一拍时的微分项增量float alpha;//不完全微分系数float result;//输出值float deltadiff;//微分增量float integralValue;//积分累计量float gama;//微分先行滤波系数float lastPv;//上一拍的过程测量值float lastDeltaPv;//上一拍的过程测量值增量}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,iError;float c1,c2,c3,temp;float deltaPv;
temp=vPID->gama*vPID->derivativegain+vPID->proportiongain;
c3=vPID->derivativegain/temp;
c2=(vPID->derivativegain+vPID->proportiongain)/temp;
c1=vPID->gama*c3;
deltaPv=processValue-vPID->lastDeltaPv
vPID->deltadiff=c1*vPID->deltadiff+c2*deltaPv+c3*vPID->lastDeltaPv;
thisError=vPID->setpoint-processValue;
pError=thisError-vPID->lasterror;
iError=thisError;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->deltadiff;
vPID->preerror=vPID->lasterror;
vPID->lastDeltaPv=deltaPv;
vPID->lastPv=processValue;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 微分先行由于微分部分只对测量值起作用所以可以消除设定值突变的影响,还可以引入低通滤波,甚至在必要时将比例作用也可进行相应的改进。
带死区的PID算法
位置式PID算法
基本公式
U
(
k
)
=
K
p
∗
e
r
r
(
k
)
+
K
i
∑
j
=
0
k
e
r
r
(
j
)
+
K
d
∗
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
U(k)=K_p*err(k)+K_i\sum_{j=0}^{k} err(j)+K_d*\big (err(k)-err(k-1)\big )
U(k)=Kp∗err(k)+Kij=0∑kerr(j)+Kd∗(err(k)−err(k−1))
e
r
r
(
k
)
=
{
0
∣
e
r
r
(
k
)
∣
≤
∣
e
r
r
0
∣
e
r
r
(
k
)
∣
e
r
r
(
k
)
∣
>
∣
e
r
r
0
∣
err(k)=\begin{cases}0 & \vert err(k)\vert\leq \vert err_0\vert \\err(k) & \vert err(k)\vert\gt \vert err_0\vert\end{cases}
err(k)={0err(k)∣err(k)∣≤∣err0∣∣err(k)∣>∣err0∣
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float result;//输出值float integral;//积分值float deadband;//死区}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;
thisError=vPID->setpoint-processValue;if(fabs(thisError)>vPID->deadband){
vPID->integral+=thisError;}else{
thisError=0;}
vPID->result=vPID->proportiongain*thisError+
vPID->integralgain*vPID->integral+
vPID->derivativegain*(thisError-vPID->lasterror);
vPID->lasterror=thisError;}
增量式PID算法
基本公式
Δ
U
(
k
)
=
U
(
k
)
−
U
(
k
−
1
)
=
K
p
(
e
r
r
(
k
)
−
e
r
r
(
k
−
1
)
)
+
K
i
∗
e
r
r
(
k
)
+
K
d
(
e
r
r
(
k
)
−
2
∗
e
r
r
(
k
−
1
)
+
e
r
r
(
k
−
2
)
)
\begin{aligned} \Delta U(k) &= U(k)-U(k-1)\\ &=K_p\big (err(k)-err(k-1)\big )\\&+K_i*err(k)\\&+K_d\big (err(k)-2*err(k-1)+err(k-2)\big) \end{aligned}
ΔU(k)=U(k)−U(k−1)=Kp(err(k)−err(k−1))+Ki∗err(k)+Kd(err(k)−2∗err(k−1)+err(k−2))
e
r
r
(
k
)
=
{
0
∣
e
r
r
(
k
)
∣
≤
∣
e
r
r
0
∣
e
r
r
(
k
)
∣
e
r
r
(
k
)
∣
>
∣
e
r
r
0
∣
err(k)=\begin{cases}0 & \vert err(k)\vert\leq \vert err_0\vert \\err(k) & \vert err(k)\vert\gt \vert err_0\vert\end{cases}
err(k)={0err(k)∣err(k)∣≤∣err0∣∣err(k)∣>∣err0∣
简单实现
typedefstruct{float setpoint;//设定值float proportiongain;//比例系数float integralgain;//积分系数float derivativegain;//微分系数float lasterror;//前一拍偏差float preerror;//前两拍偏差float result;//输出值float deadband;//死区}PID;voidPIDRegulation(PID *vPID,float processValue){float thisError;float increment;float pError,dError,iError;
thisError=vPID->setpoint-processValue;if(fabs(thisError)>vPID->deadband){
vPID->integral+=thisError;}else{
thisError=0;}
pError=thisError-vPID->lasterror;
iError=thisError;
dError=thisError-2*(vPID->lasterror)+vPID->preerror;
increment=vPID->proportiongain*pError+
vPID->integralgain*iError+
vPID->derivativegain*dError;
vPID->preerror=vPID->lasterror;
vPID->lasterror=thisError;
vPID->result+=increment;}
特点
- 消除稳定点附近的波动
基于前馈补偿的PID算法
不太懂,直接给链接
基于前馈补偿的PID算法
版权归原作者 图灵tuling 所有, 如有侵权,请联系我们删除。