PID 算法:从理论公式到 C 语言实现

Evek Golden Lv4

PID(比例-积分-微分)控制器占据了工业控制的 90% 以上。无论是无人机的姿态控制、3D 打印机的加热头温度,还是平衡车的直立,核心都是 PID。

1. 核心公式拆解

$$ u(t) = K_p e(t) + K_i \int e(t) dt + K_d \frac{de(t)}{dt} $$

  • P (Proportional) 比例:基于当前的误差。误差越大,输出修正力越大。“现在错了多少?”
  • I (Integral) 积分:基于过去的累积误差。用于消除稳态误差,“过去欠了多少?”。
  • D (Derivative) 微分:基于误差的变化率。预测未来,阻尼振荡,“将来会错多少?”。

2. 离散化与 C 实现

在 MCU 中,我们处理的是离散时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
typedef struct {
float Kp, Ki, Kd;
float prevError;
float integral;
float outMax, outMin; // 输出限幅
} PID_Controller;

float PID_Update(PID_Controller *pid, float setPoint, float measure) {
float error = setPoint - measure;

// P
float pOut = pid->Kp * error;

// I (带抗饱和)
pid->integral += error * DT;
float iOut = pid->Ki * pid->integral;

// D (后向差分)
float derivative = (error - pid->prevError) / DT;
float dOut = pid->Kd * derivative;

pid->prevError = error;

float output = pOut + iOut + dOut;

// 输出限幅 (Clamping)
if (output > pid->outMax) output = pid->outMax;
if (output < pid->outMin) output = pid->outMin;

return output;
}

3. 进阶技巧

3.1 积分抗饱和 (Anti-windup)

当执行机构(如电机 PWM)达到最大值(100%)时,误差仍然存在,积分项会持续累加到一个巨大的数值。一旦误差反向,系统需要很长时间才能“退饱和”。

  • 解法:当 output 达到限幅且 erroroutput 同向时,停止累加积分。

3.2 微分先行 (Derivative on Measurement)

如果你改变目标值(SetPoint),误差会瞬间突变,导致 D 项产生巨大的尖峰冲击。

  • 解法:对测量值(Measure)求导,而不是对误差求导。D = -Kd * d(Measure)/dt。此特性称为“微分先行”或“测量微分”。

3.3 滤波

传感器数据通常由噪点。直接求 D 会放大噪声。

  • 解法:对测量值 measure 进行低通滤波(如一阶 RC 数字滤波)后再送入 PID。

4. 调参口诀 (Ziegler-Nichols 简化版)

  1. 置 I、D 为 0,加大 P 直到系统开始等幅振荡。
  2. 取此时 P 的 0.6 倍作为系统的 Kp。
  3. 加大 I 以消除静差,减小 D 以抑制超调。
  • Title: PID 算法:从理论公式到 C 语言实现
  • Author: Evek Golden
  • Created at : 2025-11-03 20:30:02
  • Updated at : 2026-06-12 08:57:02
  • Link: https://blog.cocodemo.uno/posts/pid3k9j/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments