2. PID控制基础理论:比例(P)、积分(I)、微分(D)的物理意义与数学模型

各位好,欢迎来到第二章。说实话,PID 这三个字母,搞嵌入式的没人不认识。但你真的理解它背后的物理意义吗?

我见过不少同事,调参全靠“试”,拧一下比例,转一下积分,波形抖了就降,响应慢了就加。运气好能调出来,运气不好就原地打转。其实,理解 P、I、D 各自在干什么,调试效率能翻一倍。

这一章,咱们就把 PID 的底裤扒干净。从物理意义到数学模型,再到离散化实现,一步到位。

2.1 比例控制(P)—— 当下的误差,当下的响应

比例控制是最直观的。说白了,就是“误差有多大,我就推多大力”。

数学上很简单:

u(t) = Kp * e(t)

其中 e(t) 是当前误差,Kp 是比例增益。

物理意义呢?你想想看,一个弹簧。你拉得越长,它往回弹的力就越大。比例控制就是这个弹簧。

核心特点:

  • 响应快:误差一出现,立即输出控制量
  • 有静差:纯比例控制无法消除稳态误差
  • Kp 越大:响应越快,但容易超调、振荡

我在项目中遇到过一个问题:一个直流电机速度环,只用 P 控制,空载时转速很稳,但一加载,转速就掉下来,永远回不到设定值。这就是静差。比例控制需要误差存在才能输出,所以它永远“差一口气”。

调试小技巧:

我个人习惯先调 P,让系统稳定下来,不振荡。然后看稳态误差有多大,再决定要不要加 I。

2.2 积分控制(I)—— 过去的积累,消除静差

积分控制解决的就是 P 留下的“那口气”。它把过去的误差全部累加起来,只要还有误差,积分项就会一直增长,直到误差归零。

数学形式:

u(t) = Ki * ∫ e(t) dt

物理意义?像一个不断注水的水桶。误差是水流,积分项是水位。只要还在漏水(有误差),水位就会一直上升,直到把漏洞堵住。

核心特点:

  • 消除静差:这是 I 的唯一使命
  • 引入滞后:积分需要时间积累,响应变慢
  • 积分饱和:这是个大坑,后面会讲

我曾经吃过积分饱和的亏。一个温控系统,启动时误差很大,积分项疯狂累加,等温度到了设定值,积分项已经积累了一大堆,导致温度冲过头,来回振荡了好几次才稳定下来。后来加了抗积分饱和,问题才解决。

避坑指南:

积分项不是越大越好。Ki 太大,系统会振荡;Ki 太小,消除静差的速度太慢。我一般从 Ki = Kp / 100 开始试,再根据响应曲线微调。

2.3 微分控制(D)—— 未来的预测,抑制超调

微分控制看的是误差的变化趋势。误差在变大,它就反向输出,阻止它继续变大;误差在变小,它就“收油”,防止冲过头。

数学形式:

u(t) = Kd * de(t)/dt

物理意义?像一个“阻尼器”。你推门的时候,门后面有个阻尼器,你推得越快,它阻力越大。微分项就是干这个的。

核心特点:

  • 抑制超调:提前“刹车”,让系统更平稳
  • 对噪声敏感:微分放大高频噪声,这是它的致命伤
  • 不能单独使用:D 必须配合 P 或 PI 使用

嗯,这里要注意。微分项在实际工程中很容易引入噪声。我做过一个伺服电机位置环,加了 D 之后,波形反而更抖了。后来一查,是编码器信号有毛刺,微分项把这些毛刺放大了。解决办法是加一个低通滤波器,或者用不完全微分。

实用建议:

如果系统本身惯性很大(比如大负载的电机),D 的效果很明显。如果系统噪声大,建议先做信号滤波,再考虑加 D。

2.4 PID 控制器传递函数

把 P、I、D 合在一起,就是完整的 PID 控制器。在连续域(s 域)中,它的传递函数长这样:

G(s) = Kp + Ki/s + Kd * s

或者写成更标准的形式:

G(s) = Kp * (1 + 1/(Ti * s) + Td * s)

其中:

  • Ti = Kp / Ki:积分时间常数
  • Td = Kd / Kp:微分时间常数

这两种形式在工程中都会用到。我个人更喜欢用 Kp、Ki、Kd 的形式,因为调试时直接调这三个值,更直观。

传递函数有什么用?它让我们可以用频域分析工具(比如波特图)来研究系统的稳定性。不过在实际嵌入式调试中,我们更多是看时域响应曲线。

2.5 数字 PID 离散化方法

好了,理论讲完了。但我们的单片机是数字系统,它不认识连续的积分和微分。所以,必须把 PID 算法离散化,变成单片机能跑的代码。

离散化的核心思想:

  • 积分 → 累加:把连续的积分变成离散的求和
  • 微分 → 差分:把连续的微分变成相邻采样点的差值

常用的离散化方法有三种:

方法 积分近似 微分近似 特点
前向欧拉 e[k] * T (e[k+1] - e[k]) / T 实现简单,但稳定性稍差
后向欧拉 e[k] * T (e[k] - e[k-1]) / T 最常用,稳定,推荐
双线性变换 (e[k] + e[k-1]) * T / 2 2 * (e[k] - e[k-1]) / T - 前值 精度最高,计算量大

其中 T 是采样周期。采样周期怎么选?我一般遵循“采样频率是系统带宽的 10 倍以上”这个原则。比如电机电流环带宽 1kHz,采样频率至少 10kHz。

下面给出最常用的位置式 PID 离散化公式(后向欧拉法):

u[k] = Kp * e[k] + Ki * Σ(e[i] * T) + Kd * (e[k] - e[k-1]) / T

对应的 C 代码实现:

float pid_update(float setpoint, float measurement) {
    float error = setpoint - measurement;
    
    // 比例项
    float p_out = Kp * error;
    
    // 积分项(累加)
    integral += error * dt;
    float i_out = Ki * integral;
    
    // 微分项(差分)
    float derivative = (error - prev_error) / dt;
    float d_out = Kd * derivative;
    
    // 保存当前误差供下次使用
    prev_error = error;
    
    // 总输出
    return p_out + i_out + d_out;
}

重要提醒:

上面的代码只是教学示例。实际工程中,你还需要考虑:

  • 输出限幅(防止积分饱和)
  • 积分分离(误差大时停止积分)
  • 微分滤波(对微分项做一阶低通滤波)

这些内容我们会在后面的章节详细展开。

2.6 知识体系总览

最后,我用一张图把本章的核心内容串起来。这张图展示了 PID 从物理意义到数学建模,再到离散化实现的完整链路。

PID 控制基础理论体系 比例 (P) 当下误差,当下响应 积分 (I) 过去积累,消除静差 微分 (D) 未来预测,抑制超调 连续域数学模型 u(t) = Kp·e(t) + Ki·∫e(t)dt + Kd·de(t)/dt 传递函数 (s域) G(s) = Kp + Ki/s + Kd·s 数字离散化方法 前向欧拉 | 后向欧拉(推荐) | 双线性变换 嵌入式 C 代码实现 物理意义 → 数学模型 → 传递函数 → 离散化 → 代码实现

这张图把本章的知识链路完整呈现出来了。从顶层的 P、I、D 物理意义,到底层的 C 代码实现,每一步都有明确的对应关系。你调试的时候,遇到问题可以反向追溯:是 P 太强了?还是 I 饱和了?还是 D 引入了噪声?