4、PI 调节器原理:位置式与增量式 PI,积分饱和与抗饱和策略,我在项目中踩过的坑。

PI 调节器,说白了就是电机控制的「大脑」。你想想看,我们让电机转多快,它就得转多快,误差怎么消除?靠的就是这个比例积分。今天咱们不聊那些枯燥的数学推导,我直接结合项目经验,把位置式、增量式、积分饱和这些坑,一个一个给你讲透。

4.1 位置式 PI:最直观,但暗藏杀机

位置式 PI 的公式很简单:u(k) = Kp * e(k) + Ki * Σe(i)。输出直接等于比例项加上积分项的累加和。我在刚入行时,第一个项目用的就是它。

但这里有个大坑——积分项会无限累加。我记得有一次调试一个风机项目,启动时给定转速从 0 跳到 1500rpm,误差 e(k) 很大,积分项疯狂累积。等转速追上了,积分项已经堆了很高,导致输出严重超调,电机直接过流保护。

⚠️ 注意: 位置式 PI 的输出是绝对值,一旦积分饱和,恢复时间极长。适合对输出精度要求高、且不会频繁启停的场景。

代码实现也很直接:

// 位置式 PI 实现
float PI_Positional(float error, float Kp, float Ki) {
    static float integral = 0.0f;
    integral += error;  // 累加误差
    float output = Kp * error + Ki * integral;
    return output;
}

嗯,看着简单吧?但实际项目中,我建议你加上输出限幅,否则积分项会「飞」到天上去。

4.2 增量式 PI:我更喜欢它,原因有三

增量式 PI 的输出是增量,不是绝对值。公式是:Δu(k) = Kp * [e(k) - e(k-1)] + Ki * e(k)。最终输出是 u(k) = u(k-1) + Δu(k)

我个人习惯用增量式,原因很简单:

  • 没有积分累加问题:输出只跟最近两次误差有关,积分项不会无限膨胀。
  • 手动/自动切换无冲击:你想想看,如果从手动模式切到自动模式,位置式 PI 的输出会突变,而增量式只改变增量,平滑过渡。
  • 抗积分饱和更容易:这个后面细说。

我在一个伺服驱动器项目中,位置环用的就是增量式 PI。调试时发现,即使给定频繁变化,输出也很平滑,没有出现过冲。

// 增量式 PI 实现
float PI_Incremental(float error, float Kp, float Ki) {
    static float last_error = 0.0f;
    static float last_output = 0.0f;
    float delta = Kp * (error - last_error) + Ki * error;
    last_error = error;
    last_output += delta;
    return last_output;
}
💡 小技巧: 增量式 PI 的 Ki 和 Kp 整定方法和位置式略有不同。我一般先调 Kp 让系统响应够快,再加 Ki 消除静差。Ki 太大容易震荡,这个你调试时应该深有体会。

4.3 积分饱和:我踩过的最深的坑

积分饱和,说白了就是积分项「撑死了」。当执行器达到极限(比如 PWM 占空比 100%),误差还在,积分项继续累加。等误差反向时,积分项需要很长时间才能「吐」出来,导致系统响应迟钝。

我曾经做过一个电动工具项目,电机启动时电流限幅,积分项一直往上加。等负载突然减小,积分项释放,电流瞬间飙升,直接烧了 MOS 管。那次教训让我记住了:积分饱和不是理论问题,是会炸机的实际问题

4.4 抗饱和策略:我常用的三种方法

既然积分饱和这么坑,怎么治?我总结了三种常用策略:

策略 原理 我推荐指数
积分限幅 直接限制积分项的累加范围 ⭐⭐⭐
积分分离 误差大时停止积分,误差小时恢复 ⭐⭐⭐⭐
反计算法 输出饱和时,反向修正积分项 ⭐⭐⭐⭐⭐

积分限幅最简单,但效果一般。我试过把积分项限制在 ±1000,结果系统稳态精度变差了。

积分分离是我早期常用的。设定一个阈值,误差大于阈值时 Ki=0,小于时恢复。但阈值不好调,调小了没效果,调大了又震荡。

反计算法是我现在最推荐的。原理是:当输出饱和时,把超出部分反馈回积分项,让它「吐」出来。代码实现如下:

// 反计算抗饱和 PI
float PI_AntiWindup(float error, float Kp, float Ki, float Kc, float max_out, float min_out) {
    static float integral = 0.0f;
    static float last_output = 0.0f;
    
    float output = Kp * error + Ki * integral;
    
    // 输出限幅
    if (output > max_out) {
        output = max_out;
    } else if (output < min_out) {
        output = min_out;
    }
    
    // 反计算修正积分项
    float delta = output - last_output;
    integral += error - Kc * delta;  // Kc 是反馈增益,一般取 1/Kp
    
    last_output = output;
    return output;
}
🔑 关键点: 反计算法中的 Kc 一般取 1/Kp 到 2/Kp 之间。我习惯取 1.5/Kp,效果比较均衡。太大容易震荡,太小抗饱和效果差。

4.5 我在项目中踩过的坑——实战避坑指南

最后,我把自己踩过的坑总结一下,希望能帮你少走弯路:

  • 坑一:积分初始值——我曾经在电机启动时忘记清零积分项,结果一启动就过流。建议每次使能前,手动清零积分。
  • 坑二:Ki 和采样时间的关系——Ki 是跟采样时间 Ts 耦合的。换了一个采样频率,Ki 要重新调。我习惯把 Ki 写成 Ki = Ki_raw * Ts,这样换频率时只改 Ts 就行。
  • 坑三:浮点运算精度——在低端 MCU 上,浮点运算慢,积分项累加误差大。我建议用定点数或者 Q 格式,比如把 Ki 放大 1000 倍,最后再除回来。
  • 坑四:手动/自动切换——增量式 PI 切换时,记得把 last_output 赋值为当前实际输出值,否则会有跳变。

嗯,PI 调节器看似简单,但真正用好,需要你在项目中反复调试。我个人建议:新手用增量式 + 反计算抗饱和,这是最稳妥的组合。等你经验丰富了,再根据场景灵活选择。

下一章,咱们聊聊电流环的 PI 参数整定,那才是真正考验功力的时候。