3、PID控制基础:比例、积分、微分环节的物理意义、PID参数整定方法(Ziegler-Nichols)、数字PID实现

各位同学,欢迎来到纵向控制的核心环节——PID控制。

说实话,PID这东西,搞控制的没人不知道。但你真的理解它吗?我见过太多人把PID调成“玄学”,靠运气试参数。今天咱们就把这层窗户纸捅破,从物理意义讲到工程实现。

3.1 比例、积分、微分——三个“打工人”的分工

先问个问题:你开车时,怎么控制油门让车速稳定在60km/h?

你眼睛看仪表盘(反馈),发现车速慢了,就踩深一点油门(比例作用)。如果一直有上坡,车速总差一点,你就再补一脚(积分作用)。看到前面是下坡,你提前松点油门(微分作用)。

嗯,这就是PID的直觉。

3.1.1 比例环节(P)—— 当下误差的“直接反应”

物理意义: 输出与当前误差成正比。误差越大,控制力越强。

公式很简单:u(t) = Kp * e(t)

我在项目中遇到过一个问题:只用P控制,系统永远有静差。比如你调温控,设定50度,P控制可能稳定在48度就下不去了。为什么?因为误差小到一定程度,P的输出不足以克服阻力。

核心特点:
  • 响应快,立竿见影
  • 有静差(稳态误差)
  • Kp太大容易震荡

3.1.2 积分环节(I)—— 历史的“记账本”

物理意义: 对过去所有误差进行累加。只要误差存在,积分项就会一直增长,直到误差消除。

公式:u(t) = Ki * ∫e(t)dt

说白了,积分就是“秋后算账”。你想想看,P控制有静差,积分项就慢慢累积,最终把那个48度推到50度。

我曾经踩过的坑: 积分饱和。有一次做电机控制,启动时误差很大,积分项疯狂累积。等实际值接近目标时,积分项已经“撑爆”了,导致严重超调。后来加了抗积分饱和(Anti-windup)才解决。
个人习惯: 我一般先给积分限幅,再考虑是否用条件积分(误差大时暂停积分)。

3.1.3 微分环节(D)—— 未来的“预言家”

物理意义: 根据误差的变化趋势提前调整。误差变化越快,微分作用越强。

公式:u(t) = Kd * de(t)/dt

微分的作用是“刹车”。当误差快速减小时,微分项输出负值,抑制超调。但要注意,微分对噪声极其敏感。我在做激光雷达纵向控制时,信号稍微抖一下,微分项就炸了。

避坑指南:
  • 微分项必须配合滤波使用
  • 实际工程中常用“微分先行”或“不完全微分”
  • 噪声大的系统,宁可不加D,也别乱加

3.2 Ziegler-Nichols 参数整定——老司机的“三板斧”

参数怎么调?新手靠蒙,老手靠方法。Ziegler-Nichols(ZN)法就是最经典的整定方法,没有之一。

3.2.1 临界比例度法(闭环整定)

步骤很简单:

  1. 先把Ki和Kd设为0,只保留Kp
  2. 逐渐增大Kp,直到系统出现等幅震荡
  3. 记录此时的临界增益Ku和震荡周期Tu
  4. 按下面表格计算参数
控制器类型 Kp Ki Kd
P 0.5 * Ku - -
PI 0.45 * Ku 1.2 * Kp / Tu -
PID 0.6 * Ku 2 * Kp / Tu Kp * Tu / 8
我的经验: ZN法给出的参数通常偏激进。实际使用时,我会把Kp再乘以0.7~0.8,作为安全余量。尤其是做自动驾驶纵向控制,安全第一。

3.2.2 反应曲线法(开环整定)

适用于开环稳定的系统。给系统一个阶跃输入,记录响应曲线,提取两个关键参数:

  • 滞后时间 L:从输入变化到输出开始变化的时间
  • 时间常数 T:输出达到63.2%稳态值所需时间

然后查表计算。这个方法我用的不多,因为很多系统不允许开环测试。

3.3 数字PID实现——从理论到代码

模拟PID是连续的,但计算机是离散的。所以我们要把公式离散化。

3.3.1 位置式PID

直接模拟连续PID的离散形式:

// 位置式PID
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;
}
注意: 位置式PID的输出是绝对值。如果执行器有饱和限制,必须做限幅。否则积分项会一直累积,导致积分饱和。

3.3.2 增量式PID

输出的是控制量的增量,而不是绝对值。公式推导如下:

// 增量式PID
float pid_incremental(float error) {
    float delta_u = Kp * (error - prev_error) 
                  + Ki * error * dt 
                  + Kd * (error - 2*prev_error + prev_prev_error) / dt;
    
    prev_prev_error = prev_error;
    prev_error = error;
    
    return delta_u;
}
增量式的优点:
  • 输出是增量,不会出现积分饱和
  • 手动/自动切换时冲击小
  • 计算量小,适合嵌入式

3.3.3 工程中的几个关键细节

代码写完了,但离真正能用还差几步:

  • 采样时间 dt 必须固定:用定时器中断,不要用延时
  • 微分项加滤波:一阶低通滤波,截止频率设为采样频率的1/10
  • 积分分离:误差大时停止积分,防止超调
  • 输出限幅:保护执行器
我个人习惯: 在代码里加一个调试模式,可以实时打印P、I、D三个分量。调参时一眼就能看出哪个分量在“捣乱”。

3.4 知识体系总览

下面这张图,把PID的核心逻辑串起来了:

PID控制核心知识体系 比例环节 P Kp * e(t) — 当下误差 积分环节 I Ki * ∫e(t)dt — 历史累积 微分环节 D Kd * de/dt — 未来趋势 控制输出 u(t) Ziegler-Nichols 整定 数字PID实现(位置式/增量式) 三个环节加权求和 → 输出控制量 → 被控对象

这张图很直观:P、I、D三个环节各自独立,又协同工作。整定方法和数字实现是落地的关键。

好了,PID的基础就讲到这里。记住一句话:P是现在,I是过去,D是未来。理解了这个,调参就不再是玄学。

课后思考: 如果被控对象是纯积分环节(比如电机速度),只用P控制会有什么问题?试试看。

公众号:蓝海资料掘金营,微信deep3321