PID调节是一种广泛应用于工业控制系统的反馈控制方法,通过比例(Proportional)、积分(Integral)和微分(Derivative)三个环节的组合,根据系统的误差(即目标值与当前实际值之间的差值)来调节控制量,从而使系统输出稳定、准确地达到目标值。
以下为B站Sheik丶评论,觉得有趣且浅显易懂
桶上划条线,你手动开水龙头放水到线这么高
开环控制:桶不透明,放一会感觉差不多关了就行
闭环控制:桶透明,你在这盯着点,到线了赶紧关
反馈:超线了舀出去点
前馈:开十秒就关
p:现在水位这么低,龙头开大
d:水位涨的这么快,龙头按我说的幅度一点点慢慢关
i:还没到线呢,再打开点
各种控制方式解释:
- 开环控制(Open-loop):桶不透明,估计着放 10 秒就差不多到了。
- 优点:简单
- 缺点:环境变化大就不准了(水压变了怎么办?)
- 闭环控制(Closed-loop):桶是透明的,你可以实时看到水位。
- 根据水位实时调节水龙头大小。
- 反馈控制:超线了?你用杯子舀出去点。
- 就是反馈动作的“反作用”
- 前馈控制(Feedforward):水压我知道,我提前估好开几秒正好够。
- 不等误差出现就“预判”控制动作
- 类似你测过家里水压,知道“放 8 秒 = 一半桶”
- 在已知系统模型下非常好用,可以减少闭环负担
- PID 控制:
- P 控制:看现在差多少,就开多大水龙头
- 水位低 → 开大
- 水快到了 → 缩小点
- 特点:响应快,但可能超调(你来不及关)
- I 控制:一直到不了线,水再慢慢补上来
- 如果差了一直差(误差积累) → 再开大点水龙头
- 弥补长期偏差,让你最终能精确到线
- 特点:消除长期偏差,但可能慢或震荡
- D 控制:水位涨得太快,就提前关一点水
- 趋势判断:不是水多,是水涨太快了!
- 就像你看到水还没满,但你“预判它会满”,提前收手
- 特点:防止超调,抑制震荡
- P 控制:看现在差多少,就开多大水龙头
1. PID 的三个部分
1.1 P – 比例(Proportional)
- 根据当前误差值进行调节。
- 控制输出与误差成正比。
- 比例项大时响应快,但可能产生震荡甚至不稳定。
- 数学表达: 其中 e(t)是误差,Kp 是比例系数。
$$
P = K_p \cdot e(t)
$$
1.2 I – 积分(Integral)
- 对历史误差的累加进行调节。
- 作用是消除稳态误差,使系统长期来看输出精确。
- 积分项太大可能导致系统超调或震荡。
- 数学表达: Ki 是积分系数。
$$
I = K_i \cdot \int_0^t e(\tau) \, d\tau
$$
1.3 D – 微分(Derivative)
- 根据误差变化率进行预测性调节。
- 可以提高系统响应速度,减少超调。
- 对噪声敏感,设置要谨慎。
- 数学表达: Kd 是微分系数。
$$
D = K_d \cdot \frac{de(t)}{dt}
$$
2 PID 控制器的总输出公式:
$$
u(t) = K_p \cdot e(t) + K_i \cdot \int_0^t e(\tau)\, d\tau + K_d \cdot \frac{de(t)}{dt}
$$
PID 控制器在数字控制系统(如 MCU 或 DSP 控制器)中需要进行离散化实现,因为计算机不能处理连续时间信号。以下是标准的离散 PID 控制器公式和其实现方式。
2.1 离散 PID 控制器常用形式(位置式)
- T:采样周期
- e[k]:当前采样时刻的误差(目标值 – 实际值)
- u[k]:当前时刻的控制输出
$$
u[k] = K_p \cdot e[k] + K_i \cdot \sum_{i=0}^{k} e[i] \cdot T + K_d \cdot \frac{e[k] – e[k-1]}{T}
$$
- 关键项处理:
- 积分项:用累加和∑e(i)近似连续积分。
- 微分项:用后向差分e(k)−e(k−1)/T近似微分。
- 特点:
- 直接计算当前控制量,但需存储所有历史误差(积分项),计算量大。
- 可能发生积分饱和(输出超出实际需求)。
2.2 常用的增量式离散 PID
$$
\Delta u[k] = K_p \cdot (e[k] – e[k-1]) + K_i \cdot e[k] \cdot T + K_d \cdot \frac{e[k] – 2e[k-1] + e[k-2]}{T}\
u[k]=u[k−1]+Δu[k]
$$
- 只需要保存 当前误差 e[k]、前一次误差 e[k-1] 和 再前一次误差 e[k-2],计算量小。
- 增量式不会累计积分误差溢出,更适合嵌入式系统。
- 对噪声更敏感(因微分项涉及高阶差分)。
3. PID控制代码
3.1 位置式PID
float error = 0;
float last_error = 0;
float integral = 0;
float T_set = 50.0; // 设定值
float Kp = 1.0, Ki = 0.5, Kd = 0.1;
float T = 0.1; // 采样周期,单位:秒
// === PID 位置式控制函数 ===
uint8_t pid_position(float T_cur) {
error = T_set - T_cur;
integral += error * T;
float derivative = (error - last_error) / T;
float output = Kp * error + Ki * integral + Kd * derivative;
last_error = error;
if (output > 100) output = 100;
if (output < 0) output = 0;
return (uint8_t)output;
}
3.2 增量式PID
float e_k = 0, e_k_1 = 0, e_k_2 = 0;
float output = 0;
float T_set = 50.0;
float Kp = 1.0, Ki = 0.5, Kd = 0.1;
float T = 1.0; // 采样周期
// === PID 增量式控制函数 ===
uint8_t pid_incremental(float T_cur) {
e_k = T_set - T_cur;
float delta_u =
Kp * (e_k - e_k_1) +
Ki * T * e_k +
Kd * (e_k - 2 * e_k_1 + e_k_2) / T;
output += delta_u;
e_k_2 = e_k_1;
e_k_1 = e_k;
if (output > 100) output = 100;
if (output < 0) output = 0;
return (uint8_t)output;
}
4. PID的参数整定
调整PID 三个参数,以达到快速响应、不超调、无震荡、稳态误差为零。
- Kp:提高响应速度,缩小误差
- Ki:消除稳态误差
- Kd:抑制震荡,提高稳定性
4.1 经验法(手动调参)
调参步骤:
- 先设 Ki = 0,Kd = 0,只调 Kp
- 增大 Kp 直到系统开始震荡(临界比例增益)
- 稍微减小一点,保留快速响应但不震荡
- 加入 Ki 消除稳态误差
- 从很小的值开始增大,直到系统能回到目标值
- 若系统震荡或响应变慢,稍微减小
- 加入 Kd 抑制震荡、提升响应
- 逐步增大,看系统是否变得更平稳
- 过大可能导致响应延迟或噪声放大
典型值比例参考(仅供启发):
参数 | 作用 | 初始估值 |
---|---|---|
Kp | 快速收敛 | 从 1 开始逐步调大 |
Ki | 消除稳态误差 | Kp / 10 |
Kd | 减少超调/震荡 | Kp * 10 |
4.2 Ziegler-Nichols 方法
一个经典的工程调参法,适合第一次设置初始 PID。
调参步骤:
- 设置 Ki = 0, Kd = 0
- 慢慢增大 Kp,直到输出出现持续震荡
- 记录此时的 Kp = Ku、震荡周期 Tu
- 用如下经验公式计算 PID 参数:
控制类型 | Kp | Ki (转为 Ki = Kp / Ti ) | Kd |
---|---|---|---|
P | 0.5 Ku | — | — |
PI | 0.45 Ku | 1.2 Ku / Tu | — |
PID | 0.6 Ku | 2 Ku / Tu | KuTu / 8 |