简介
PID 是 Proportional(比例)、Integral(积分)、Differential(微分)的首字母缩写,它是一种结合比例、积分和微分三个环节于一体的闭环控制算法。
本质:根据输入的偏差值,按照比例、积分、微分的函数关系进行运算,运算结果用以控制输出。
比例系数
成比例地反应控制系统的偏差信号,即输出u与输入偏差e成正比,可以用来减小系统的偏差。
u:输出
e:偏差值(输出值和实际值的偏差)
Kp :比例系数
1 、Kp越大,系统响应越快,越快达到目标值。
2 、Kp过大会使系统产生较大的超调和振荡,导致系统的鲁棒性差。
3 、仅有比例环节无法消除静态误差。
静态误差
系统控制过程趋于稳定时,目标值与实测值之间的偏差。
产生静差原因:输出u被外部影响抵消
所以我们举个例子:当需要调整大棚温度为30°,但外部温度为20°,设置固定时间散失1°
设置Kp为0.5
第一次调温0.510=5°,散失后,为升温4°,25°
第二次调温0.55=2.5°,散失后,为升温1.5°,26.5°
第三次调温0.53.5=1.75°,散失后,为升温0.75°,27.25°
第四次调温0.52.75=1.35°·························
所以加到28°后就上不去了,永远不可能达到目标值
消除静差方法:引入积分环节
积分系数
对输入偏差e进行积分,只要存在偏差,积分环节就会不断起作用,主要用于消除静态误差。
u :输出
e :偏差值
Kp :比例系数
Ki :积分系数
前面的例子,我们还是设置为Kp=0.5,Ki= 0.3。
第一次,误差为10 比例部分 Kp10=5,积分部分为Ki10=3,u为8,温度达到28°,散失为27°
第二次,误差为3,比例部分Kp3=1.5,积分部分Kp(10+3)=3.9 ,温度为28+1.5+3.9-1=30.9°
如果这样一直下去,最终会到达一个稳定值。
1、 Ki越大,消除静态误差的时间越短,越快达到目标值。
2、 Ki过大会使系统产生较大的超调和振荡,导致系统的鲁棒性差。
3、对于惯性较大的系统,积分环节动态响应较差,容易产生超调、振荡。
微分系数
反应偏差量的变化趋势,根据偏差的变化量提前作出相应控制,减小超调,克服振荡。
1、Kd或者变化趋势越大,微分环节作用越强,对超调和振荡的抑制越强。
2、 Kd过大会引起系统的不稳定,容易引入高频噪声(由于Kd的增大,控制器对误差信号的变化率变得非常敏感,这可能导致系统对测量值中的噪声(特别是高频噪声)也非常敏感。当系统尝试对这些噪声进行响应时,它可能会产生不必要的、快速的输出变化,从而引入高频噪声到系统中)。
PID离散公式
位置式PID公式
1、 u_k直接对应对象的输出(位置),如果计算出现异常,对系统影响很大。
2、全量计算,要对偏差 e 进行累加,计算量大,即为全量式PID,因为它的每一次输出量都与过去的状态有关系。
3、在不带积分部件的对象中可以得到很好效果,例如电液伺服阀、温控设备等。
增量式PID控制
1、增量式PID计算的是相对上一次输出的增量,即u_k= u_k−1+ ∆u_k 。
2、增量只与近3次的偏差有关,计算出现异常对系统工作影响较小。
3、计算量少,实时性相对较好。
总结
代码
PID结构体
typedef struct
{
__IO float SetPoint; /* 目标值 */
__IO float ActualValue; /* 期望值 */
__IO float SumError; /* 偏差累计 */
__IO float Proportion; /* 比例常数 P */
__IO float Integral; /* 积分常数 I */
__IO float Derivative; /* 微分常数 D */
__IO float Error; /* Error[1] */
__IO float LastError; /* Error[-1] */
__IO float PrevError; /* Error[-2] */
} PID_TypeDef;
算法代码
int32_t increment_pid_ctrl(PID_TypeDef *PID,float Feedback_value)
{
PID->Error = (float)(PID->SetPoint - Feedback_value); /* 计算偏差 */
#if INCR_LOCT_SELECT /* 增量式PID */
PID->ActualValue += (PID->Proportion * (PID->Error - PID->LastError)) /* 比例项 */
+ (PID->Integral * PID->Error) /* 积分项 */
+ (PID->Derivative * (PID->Error - 2 * PID->LastError + PID->PrevError)); /* 微分项 */
PID->PrevError = PID->LastError; /* 存储偏差,用于下次计算 */
PID->LastError = PID->Error;
#else /* 位置式PID */
PID->SumError += PID->Error; /* 偏差e累加求和 */
PID->ActualValue = (PID->Proportion * PID->Error) /* 比例项 */
+ (PID->Integral * PID->SumError) /* 积分项 */
+ (PID->Derivative * (PID->Error - PID->LastError)); /* 微分项 */
PID->LastError = PID->Error; /* 存储偏差,用于下次计算 */
#endif
return ((int32_t)(PID->ActualValue)); /* 返回计算后输出的期望值 */
}
函数传入形参2为测量的实际值,计算偏差,可以选择两种pid,注意增量式PID是+=,即ActualValue =ActualValue +(PID->Proportion * (PID->Error - PID->LastError)) + (PID->Integral * PID->Error) + (PID->Derivative * (PID->Error - 2 * PID->LastError + PID->PrevError)),计算的是上一次+这次的变化量。
实验演示部分
在原子哥演示中,以下演示了比例加积分
可以看到这里积分系数比较小,也没有出现超调。
看到这里调整为10,会出现超调
所以需要根据实际去调整pid,不同电机对pid系数的敏感程度不同