跳转至

PID 控制

PID 是工业界使用最广泛的控制算法,没有之一。超过 90% 的工业控制回路都在用 PID 或其变体。


一、PID 是什么

PID 控制器根据误差 \(e(t) = r(t) - y(t)\)(目标值 − 实际值)来计算控制量,由三项组成:

\[ u(t) = K_p \, e(t) + K_i \int_0^t e(\tau)\,d\tau + K_d \, \frac{de(t)}{dt} \]

\(s\) 域中:

\[ C(s) = K_p + \frac{K_i}{s} + K_d s \]
graph LR
    R["目标值 r"] --> SUM((+/-))
    SUM -->|误差 e| P["P: 比例<br>Kp × e"]
    SUM -->|误差 e| I["I: 积分<br>Ki × ∫e dt"]
    SUM -->|误差 e| D["D: 微分<br>Kd × de/dt"]
    P --> ADD((Σ))
    I --> ADD
    D --> ADD
    ADD -->|控制量 u| PLANT["被控对象"]
    PLANT -->|输出 y| OUT["输出"]
    OUT --> SUM

二、P / I / D 各项的物理意义

2.1 比例项(P)

\[ u_P = K_p \cdot e(t) \]
  • 做什么:误差越大,输出越大。就像弹簧——你拉得越远,回复力越大。
  • 效果:提高响应速度,减小稳态误差。
  • 问题单纯的 P 控制无法消除稳态误差

为什么 P 控制有稳态误差?

假设控制一个水箱水位。水位低于目标 → 打开阀门进水。水位越接近目标 → 阀门开度越小 → 进水流量越小。

当进水流量 = 出水流量时,系统达到平衡,但此时水位并没有完全到达目标——因为如果误差 = 0,控制量也 = 0,没有动力维持水位。

这个残余误差就是 \(e_{ss} = \frac{1}{1 + K_p}\)(对于一个 0 型系统)。\(K_p\) 越大,误差越小,但永远不为零

2.2 积分项(I)

\[ u_I = K_i \int_0^t e(\tau)\,d\tau \]
  • 做什么:累积历史误差。即使当前误差很小,只要一直存在,积分就会持续增长,产生越来越大的控制输出。
  • 效果消除稳态误差(这是 I 项存在的核心意义)。
  • 问题:引入相位滞后,可能导致超调和振荡。

积分消除稳态误差的直觉

还是水箱例子。加了 I 项后,即使水位差只有一点点,积分项也会随时间持续累积,不断增大阀门开度,直到水位完全到达目标值。此时误差 = 0,积分不再增长,输出维持在一个恒定值——恰好补偿出水流量。

2.3 微分项(D)

\[ u_D = K_d \cdot \frac{de(t)}{dt} \]
  • 做什么:关注误差的变化速率。误差在快速减小 → 提前减小控制量;误差在增大 → 立刻加大控制量。
  • 效果:预测未来趋势,抑制超调,增加阻尼。
  • 问题:对噪声极其敏感(噪声的导数很大)。

D 项的直觉

类比开车刹车:你不会等到距前车 0 距离才踩刹车,而是看到距离在快速减小时就提前减速。D 项就是这个"提前量"。


三、P / I / D 参数效果总结

增大参数 响应速度 超调量 稳态误差 稳定性
\(K_p\) ⬆ 加快 ⬆ 增大 ⬇ 减小(但不消除) ⬇ 变差
\(K_i\) ⬆ 加快 ⬆ 增大 消除 ⬇ 变差
\(K_d\) — 轻微影响 ⬇ 减小 — 无影响 ⬆ 变好(适度时)

不是所有情况都要用完整 PID

  • P 控制:简单场景,允许一定稳态误差
  • PI 控制:最常见组合,消除稳态误差(温度控制、流量控制)
  • PD 控制:需要快速响应,不关心稳态误差(某些位置伺服)
  • PID 控制:需要兼顾精度和动态性能

四、离散化 PID

在嵌入式系统中,PID 必须用离散形式实现。采样周期为 \(T\)

4.1 位置式 PID

\[ u(k) = K_p \, e(k) + K_i \, T \sum_{j=0}^{k} e(j) + K_d \, \frac{e(k) - e(k-1)}{T} \]

特点:输出是控制量的绝对值。积分项需要保存所有历史误差的累积。

4.2 增量式 PID

\[ \Delta u(k) = K_p [e(k) - e(k-1)] + K_i \, T \, e(k) + K_d \frac{e(k) - 2e(k-1) + e(k-2)}{T} \]
\[ u(k) = u(k-1) + \Delta u(k) \]

特点:输出是控制量的增量。不需要累积历史,更适合嵌入式实现。

位置式 vs 增量式

位置式 增量式
输出 绝对控制量 控制量增量
积分饱和 容易出现 天然避免
无扰切换 困难 容易
适用场景 阀门开度等绝对量 电机 PWM 等增量式执行器

五、PID 调参方法

5.1 手动调参经验法

这是最常用的工程方法,按以下顺序:

调参三步法

第一步:只调 P

  1. \(K_i = 0\)\(K_d = 0\)
  2. 从小到大增大 \(K_p\)
  3. 观察阶跃响应:响应快但开始出现明显振荡时,记下此时的 \(K_p\)
  4. \(K_p\) 为该值的 60%~70%

第二步:加入 I

  1. 保持 \(K_p\) 不变,从小到大增大 \(K_i\)
  2. 观察稳态误差是否被消除
  3. 如果超调变大、振荡加剧,减小 \(K_i\)
  4. 找到一个消除稳态误差但超调可接受的值

第三步:加入 D

  1. 如果超调仍然太大,从小到大增大 \(K_d\)
  2. \(K_d\) 能抑制超调,但太大会导致高频振荡(噪声放大)
  3. 通常 \(K_d\) 远小于 \(K_p\)

5.2 Ziegler-Nichols 整定法

一种经典的半经验方法:

临界比例法:

  1. \(K_i = 0\), \(K_d = 0\)
  2. 增大 \(K_p\) 直到系统出现等幅持续振荡
  3. 记录此时的 \(K_p = K_u\)(临界增益)和振荡周期 \(T_u\)
控制器类型 \(K_p\) \(K_i\) \(K_d\)
P \(0.5 K_u\)
PI \(0.45 K_u\) \(\frac{0.54 K_u}{T_u}\)
PID \(0.6 K_u\) \(\frac{1.2 K_u}{T_u}\) \(\frac{0.075 K_u \cdot T_u}{1}\)

Ziegler-Nichols 的局限

  • 需要让系统达到临界振荡,在实际系统中可能有风险
  • 调出的参数通常超调较大(约 25%),需要后续微调
  • 更适合作为起点,而非最终参数

5.3 软件辅助调参

在嵌入式开发中,常用方法:

  1. 串口/CAN 实时调参:运行时通过上位机动态修改 PID 参数
  2. 示波器观察:用 DAC 或串口输出目标值和实际值的曲线
  3. MATLAB/Simulink 仿真:建立电机模型,先在仿真中整定参数

六、工程中的 PID 改进

6.1 积分抗饱和(Anti-Windup)

问题:当执行器输出饱和(如 PWM 已达 100%),误差仍在累积积分项,导致积分项膨胀到很大的值。当误差方向反转时,需要很长时间才能消化掉积分量——造成严重超调。

解决方案

integral += error * dt;
if (integral > INTEGRAL_MAX) integral = INTEGRAL_MAX;
if (integral < INTEGRAL_MIN) integral = INTEGRAL_MIN;
// 只在误差较小时启用积分
if (fabs(error) < ERROR_THRESHOLD) {
    integral += error * dt;
}
// 当输出饱和时,反向修正积分项
u_raw = Kp * error + Ki * integral + Kd * deriv;
u_sat = clamp(u_raw, U_MIN, U_MAX);
integral += (u_sat - u_raw) / Ka * dt; // Ka 为反算增益

6.2 微分滤波

D 项对噪声敏感,实践中几乎不会直接用纯微分。常用方法:

一阶低通滤波:

\[ D_{\text{filtered}}(s) = \frac{K_d s}{1 + \frac{K_d}{N} s} \]

其中 \(N\) 是滤波系数,通常取 8~20。这等价于在微分后加一个截止频率为 \(\frac{N}{K_d}\) 的低通滤波器。

// 离散实现
derivative = (error - prev_error) / dt;
filtered_derivative = alpha * filtered_derivative + (1 - alpha) * derivative;
// alpha = tau / (tau + dt), tau 为滤波时间常数

6.3 微分先行(Derivative on Measurement)

问题:当目标值突变(阶跃输入)时,误差的导数会出现脉冲,导致控制量瞬间冲击。

解决方案:对测量值而非误差做微分:

\[ u_D = -K_d \frac{dy(t)}{dt} \quad \text{(注意负号)} \]

目标值的突变不会引起微分冲击,但仍然能对输出的变化做出反应。

6.4 前馈补偿

PID 是反馈控制——必须先产生误差,才能修正。前馈在误差产生之前就施加补偿。

\[ u = u_{\text{PID}} + u_{\text{FF}} \]

前馈的例子

控制机械臂的关节角度。已知关节受重力影响,可以用逆动力学模型直接计算需要的力矩作为前馈量 \(u_{\text{FF}} = \tau_{\text{gravity}}\),PID 只负责补偿剩余的小误差。


七、PID 参数整定的完整思维导图

graph TB
    START["开始调参"] --> P["1. 只用 P 控制"]
    P --> P_Q{"响应够快?"}
    P_Q -->|慢| P_UP["增大 Kp"]
    P_UP --> P
    P_Q -->|振荡| P_DOWN["减小 Kp 到 60%~70%"]
    P_DOWN --> I["2. 加入 I"]
    P_Q -->|合适| I
    I --> I_Q{"稳态误差消除?"}
    I_Q -->|有余差| I_UP["增大 Ki"]
    I_UP --> I
    I_Q -->|超调大| I_DOWN["减小 Ki"]
    I_DOWN --> D
    I_Q -->|合适| D["3. 加入 D"]
    D --> D_Q{"超调可接受?"}
    D_Q -->|超调大| D_UP["增大 Kd"]
    D_UP --> D
    D_Q -->|高频振荡| D_DOWN["减小 Kd,加滤波"]
    D_DOWN --> DONE["调参完成 ✅"]
    D_Q -->|合适| DONE

八、一段完整的嵌入式 PID 代码

typedef struct {
    float Kp, Ki, Kd;
    float integral;
    float prev_error;
    float prev_derivative;  // 用于微分滤波
    float output_min, output_max;
    float integral_min, integral_max;
    float dt;
    float alpha;  // 微分滤波系数
} PID_Controller;

float PID_Update(PID_Controller *pid, float setpoint, float measurement) {
    // 1. 计算误差
    float error = setpoint - measurement;

    // 2. 比例项
    float P = pid->Kp * error;

    // 3. 积分项(带抗饱和)
    pid->integral += error * pid->dt;
    if (pid->integral > pid->integral_max) pid->integral = pid->integral_max;
    if (pid->integral < pid->integral_min) pid->integral = pid->integral_min;
    float I = pid->Ki * pid->integral;

    // 4. 微分项(对测量值微分 + 低通滤波)
    float raw_derivative = -(measurement - pid->prev_error) / pid->dt; // 微分先行
    float D_filtered = pid->alpha * pid->prev_derivative
                     + (1.0f - pid->alpha) * raw_derivative;
    float D = pid->Kd * D_filtered;

    // 5. 输出限幅
    float output = P + I + D;
    if (output > pid->output_max) output = pid->output_max;
    if (output < pid->output_min) output = pid->output_min;

    // 6. 保存状态
    pid->prev_error = measurement;  // 注意:微分先行时保存的是测量值
    pid->prev_derivative = D_filtered;

    return output;
}

代码要点

  • 积分限幅防止 windup
  • 微分先行避免目标值突变引起冲击
  • 低通滤波抑制噪声
  • 输出限幅保护执行器