4、PI 调节器原理:位置式与增量式 PI,积分饱和与抗饱和策略,我在项目中踩过的坑。
PI 调节器,说白了就是电机控制的「大脑」。你想想看,我们让电机转多快,它就得转多快,误差怎么消除?靠的就是这个比例积分。今天咱们不聊那些枯燥的数学推导,我直接结合项目经验,把位置式、增量式、积分饱和这些坑,一个一个给你讲透。
4.1 位置式 PI:最直观,但暗藏杀机
位置式 PI 的公式很简单:u(k) = Kp * e(k) + Ki * Σe(i)。输出直接等于比例项加上积分项的累加和。我在刚入行时,第一个项目用的就是它。
但这里有个大坑——积分项会无限累加。我记得有一次调试一个风机项目,启动时给定转速从 0 跳到 1500rpm,误差 e(k) 很大,积分项疯狂累积。等转速追上了,积分项已经堆了很高,导致输出严重超调,电机直接过流保护。
代码实现也很直接:
// 位置式 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;
}
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;
}
4.5 我在项目中踩过的坑——实战避坑指南
最后,我把自己踩过的坑总结一下,希望能帮你少走弯路:
- 坑一:积分初始值——我曾经在电机启动时忘记清零积分项,结果一启动就过流。建议每次使能前,手动清零积分。
- 坑二:Ki 和采样时间的关系——Ki 是跟采样时间 Ts 耦合的。换了一个采样频率,Ki 要重新调。我习惯把 Ki 写成
Ki = Ki_raw * Ts,这样换频率时只改 Ts 就行。 - 坑三:浮点运算精度——在低端 MCU 上,浮点运算慢,积分项累加误差大。我建议用定点数或者 Q 格式,比如把 Ki 放大 1000 倍,最后再除回来。
- 坑四:手动/自动切换——增量式 PI 切换时,记得把 last_output 赋值为当前实际输出值,否则会有跳变。
嗯,PI 调节器看似简单,但真正用好,需要你在项目中反复调试。我个人建议:新手用增量式 + 反计算抗饱和,这是最稳妥的组合。等你经验丰富了,再根据场景灵活选择。
下一章,咱们聊聊电流环的 PI 参数整定,那才是真正考验功力的时候。