一. 定义
PID(比例-积分-微分):是一种广泛应用的工程控制技术,通过比例、积分、微分三种控制方式对系统误差进行调节,以实现精确控制。
二. 三个字母的物理意义
| 字母 | 名称 | 数学表达 | 物理作用 | 形象比喻 |
|---|---|---|---|---|
| P | 比例 | Kp⋅e(t)K_p \cdot e(t)Kp⋅e(t) | 现在:误差越大,输出越强 | 弹簧——拉得越远,反弹力越大 |
| I | 积分 | Ki⋅∫e(t)dtK_i \cdot \int e(t)dtKi⋅∫e(t)dt | 过去:消除累积误差 | 记忆——记住过去的偏差,持续修正 |
| D | 微分 | Kd⋅de(t)dtK_d \cdot \frac{de(t)}{dt}Kd⋅dtde(t) | 未来:预测误差趋势 | 阻尼——速度越快,阻力越大 |
三. 公式
数字公式(连续域)

离散化形式(实际代码使用)

四.代码实现
typedef struct {
float Kp, Ki, Kd; // PID参数
float integral; // 积分累积
float last_error; // 上次误差
float output_max; // 输出限幅(抗饱和)
float output_min;
float Ts; // 采样周期
} PID_Controller;
// PID计算函数(位置式)
float PID_Calculate(PID_Controller *pid, float setpoint, float feedback) {
float error = setpoint - feedback;
// 1. 比例项 P
float P = pid->Kp * error;
// 2. 积分项 I(带抗饱和)
pid->integral += error * pid->Ts;
if(pid->integral > pid->output_max) pid->integral = pid->output_max;
if(pid->integral < pid->output_min) pid->integral = pid->output_min;
float I = pid->Ki * pid->integral;
// 3. 微分项 D(用差分近似)
float d_error = (error - pid->last_error) / pid->Ts;
float D = pid->Kd * d_error;
// 4. 输出合成
float output = P + I + D;
// 5. 输出限幅(必须!)
if(output > pid->output_max) output = pid->output_max;
if(output < pid->output_min) output = pid->output_min;
pid->last_error = error;
return output;
}
// PID计算函数(增量式) 防积分饱和更好
float PID_Incremental(PID_Controller *pid, float setpoint, float feedback) {
float error = setpoint - feedback;
float delta_u = pid->Kp * (error - pid->last_error)
+ pid->Ki * error
+ pid->Kd * (error - 2*pid->last_error + pid->prev_error);
pid->prev_error = pid->last_error;
pid->last_error = error;
return delta_u; // 输出变化量,需累加得到实际控制量
}
五. 位置式 VS 增量式
| 特性 | 位置式PID | 增量式PID |
|---|---|---|
| 输出 | 控制量的绝对值 | 控制量的变化量 |
| 公式 | u(k)=P+I+Du(k) = P+I+Du(k)=P+I+D | Δu(k)=Kp[e(k)−e(k−1)]+Kie(k)+Kd[e(k)−2e(k−1)+e(k−2)]\Delta u(k) = K_p[e(k)-e(k-1)] + K_i e(k) + K_d[e(k)-2e(k-1)+e(k-2)]Δu(k)=Kp[e(k)−e(k−1)]+Kie(k)+Kd[e(k)−2e(k−1)+e(k−2)] |
| 优点 | 直观,适合直接控制 | 无积分累积,无冲击 |
| 缺点 | 积分饱和风险 | 需额外积分得到最终输出 |
| 适用场景 | 电流环、温度控制 | 位置环、步进电机 |
六. 调参方法
口诀:先 P 后 I,D 看情况补。
原理:
-
P 值增大可以加快响应速度。P 调到曲线轻微波动时,再回调80%。P不能过大,否则会出现来回震荡。P 也不能太小,否则响应太慢。纯 P 控制很难调好控制,会有两个坑,要么出现输出不稳(超调),要么出现输出与预期输出永远差一点(静态误差)。
-
积分调节 I,I 值增大能更快消除静态误差。如果输出一直差一点到不了目标,比如说温度控制目标75℃,但始终停在50℃,这时 I 就像慢慢加火,把累计的小温差彻底抵消。
-
微分调节 D,用于预测温度未来趋势,提前调整,可以减少系统超调和震荡。
PID调参过程:
- 第一步:先调 P,把 I 设为 0,D 设为 0,慢慢加大 P 的数值,直到输出开始轻微波动,然后把 P 值回调到波动消失时的 70%-80%。
这一步是让系统能够快速接近目标输出。



-
第二步:慢慢加大 I 的数值,直到输出的残留误差消失。注意,I 太大容易让输出震荡加剧,所以宁小误大。
这一步是让系统精准稳定。

-
第三步:最后微调 D 的数值,目的是减少超调和波动,让输出上升更平滑。D 值不能太大,否则会导致输出抖动。

调参三大坑:
- 1.三个参数一起调。
- 必须按照 P->I->D 的顺序,一个一个来。控制变量才是调参的真理。
- 2.P值设置太大。
- 稳定性 > 速度。宁可慢一点,也要稳一点。
- 3.忽略硬件问题。
- 调不通时先检测硬件能力。
**PID 组合拳:**在使用 PID 的时候,单独只使用一个参数是没有意义的,至少使用两个参数,大多数情况下 PID 三个参数并不是都使用上的,一般会选择其中两个来组合使用。
- 1.单 P 控制:没有意义,有误差。
- 2.PI 组合:用于追求稳定的系统。(如水温)
- 3.PD 组合:用于追求快速响应的系统。(如舵机)
- 4.PID 全开:用于既追求稳定又追求快速响应的系统。(难调)
Ziegler-Nichols 法
-
- 纯P控制:设 Ki = 0,Kd = 0 ,逐渐增大 Kp 直至系统等幅振荡。
-
- 记录临界增益 Ku 和振荡周期 Tu。
-
- 按表设置:
| 控制器类型 | KpK_pKp | KiK_iKi | KdK_dKd |
| :------ | :-------- | :------------ | :------------- |
| P | 0.5Ku0.5K_u0.5Ku | - | - |
| PI | 0.45Ku0.45K_u0.45Ku | 0.54Ku/Tu0.54K_u/T_u0.54Ku/Tu | - |
| PID | 0.6Ku0.6K_u0.6Ku | 1.2Ku/Tu1.2K_u/T_u1.2Ku/Tu | 0.075KuTu0.075K_u T_u0.075KuTu |
- 按表设置:
工程经验(FOC电机控制)
- 电流环:Kp 大、Ki 小 带宽 > 1kHz,不用 D。
- 速度环:Kp 中、Ki 中 带宽 100 - 500Hz。
- 位置环:Kp 小、Ki 小 带宽 < 100Hz。
抗积分饱和(Anti-Windup)
问题:当执行器饱和(如PWM占空比100%),积分项继续累积,导致退出饱和时产生巨大超调。
解决方案:
// 方法1:积分限幅(最简单)
if(pid->integral > MAX) pid->integral = MAX;
if(pid->integral < MIN) pid->integral = MIN;
// 方法2:积分分离(误差大时不积分)
if(fabs(error) < THRESHOLD) {
pid->integral += error * pid->Ts;
}
// 方法3:输出反馈限幅(高级)
if(output > pid->output_max || output < pid->output_min) {
pid->integral -= error * pid->Ts; // 回退积分
}
552

被折叠的 条评论
为什么被折叠?



