PID控制器原理:P、I、D三个环节的作用、公式推导、常见PID变体
说实话,PID控制器是飞控的灵魂。不管你用多好的传感器、多强的处理器,如果PID没调好,飞机照样乱晃。我见过太多人一上来就调参数,结果越调越乱——其实根本原因是不理解P、I、D各自在干什么。
这一章,咱们把PID拆开揉碎了讲。不搞玄学,只讲实战。
2.1 三个环节的作用——用直觉理解
先别急着看公式。咱们用个场景来理解:你用手托着一杯水,想让它保持水平。
- P(比例):杯子歪了,你立刻往反方向推。歪得越狠,推得越猛。这就是P——根据当前误差大小,给出正比的控制量。
- I(积分):如果杯子一直往一边偏,说明有持续的外力(比如风)。P只能对抗瞬时偏差,但对抗不了持续偏差。这时候I就起作用了——它把过去的误差累积起来,慢慢增加修正力,直到偏差消失。
- D(微分):杯子正在快速往一边倒,你提前预判到趋势,提前用力往回拉。这就是D——根据误差的变化率,提前给出阻尼力,抑制震荡。
我在项目中遇到过一架四轴,悬停时总是低频晃动。P调大了晃得更厉害,调小了又回中慢。后来发现是D太小,阻尼不够。加上D之后,飞机像换了个人似的,稳得一批。
一句话总结:
- P决定响应速度——越大越快,但容易超调
- I消除稳态误差——越大越能消除静差,但容易积分饱和
- D抑制震荡——越大越稳,但会放大噪声
2.2 PID公式推导——从离散到连续
标准PID公式长这样:
u(t) = Kp * e(t) + Ki * ∫e(τ)dτ + Kd * de(t)/dt
其中:
- e(t) = 期望值 - 实际值(误差)
- Kp、Ki、Kd 分别是比例、积分、微分系数
- u(t) 是控制输出
但在飞控里,我们用的是离散形式。因为单片机只能处理离散采样,不能处理连续积分。离散化之后:
u(k) = Kp * e(k) + Ki * Σe(i)*Δt + Kd * (e(k) - e(k-1))/Δt
这里:
- k 是当前采样时刻
- Δt 是采样周期(飞控里通常是 1ms 或 4ms)
- Σe(i) 是从开始到现在的误差累加
嗯,这里要注意:积分项里的 Σe(i)*Δt 其实就是矩形法求积分。采样周期越短,积分越精确。但采样周期太短,计算量又上去了。我个人习惯用 1ms 的采样周期,兼顾精度和性能。
实战小技巧: 很多飞控代码里会把 Ki 写成 Ki = Kp / Ti,其中 Ti 是积分时间常数。这样调参时更容易理解——Ti 越大,积分作用越弱。我习惯用 Ti 而不是直接用 Ki,因为物理意义更直观。
2.3 常见PID变体——飞控里真正用的
实际飞控里,没人用纯PID。为什么?因为纯PID有太多坑。下面是我在项目中踩过的几个变体:
2.3.1 位置式PID vs 增量式PID
| 类型 | 输出含义 | 优点 | 缺点 |
|---|---|---|---|
| 位置式 | 直接输出控制量(如油门值) | 直观,容易理解 | 积分饱和严重,容易超调 |
| 增量式 | 输出控制量的增量(Δu) | 无积分饱和,抗积分饱和能力强 | 需要额外累加,有累积误差 |
我在做固定翼飞控时,高度环用的是位置式PID,因为需要精确控制油门位置。但角速率环我全用增量式,因为响应快、不容易饱和。你想想看,角速率环如果积分饱和了,飞机会直接翻过去——那可不是闹着玩的。
2.3.2 串级PID——飞控标配
串级PID是飞控里最常用的结构。外环(角度环)输出作为内环(角速率环)的期望值。说白了就是:外环告诉内环“你应该转多快”,内环负责执行。
// 伪代码示例:串级PID
// 外环:角度环
angle_error = target_angle - current_angle;
rate_target = Kp_angle * angle_error + Kd_angle * angle_error_dot;
// 内环:角速率环
rate_error = rate_target - current_rate;
output = Kp_rate * rate_error + Ki_rate * rate_error_integral + Kd_rate * rate_error_dot;
我曾经调试一架六轴,外环P给得太大,内环根本追不上,结果飞机像抽风一样抖。后来把外环P减半,内环P加倍,飞机立刻稳了。记住:内环要快,外环要稳。
2.3.3 抗积分饱和(Anti-Windup)
积分饱和是PID最隐蔽的坑。当执行器饱和(比如油门已经100%了),误差还在累积,积分项会变得巨大。等误差反向时,积分项需要很长时间才能退回来——这就是“饱和”。
我曾经在调试一台植保机时,遇到下降时高度过冲。查了半天,发现是积分饱和。解决方案很简单:
- 积分限幅:给积分项设个上限,比如 ±油门最大值的30%
- 积分冻结:当执行器饱和时,停止积分累加
- 反馈积分:用实际输出和期望输出的差值来修正积分
避坑指南: 我曾经在PX4代码里遇到过积分饱和导致的高度震荡。当时查了三天,最后发现是积分限幅设得太大了。把限幅从50%降到20%,问题立刻解决。所以,积分限幅不是越大越好,要根据执行器行程来定。
2.3.4 微分先行(Derivative on Measurement)
标准PID的微分项是对误差求导。但误差突变时(比如目标值突然改变),微分项会瞬间爆炸——这叫“微分冲击”。
解决办法:只对测量值求导,不对误差求导。这样目标值变化时,微分项不会跳变。
// 标准微分:容易冲击
d_term = Kd * (error - last_error);
// 微分先行:只对测量值求导
d_term = Kd * (last_measurement - measurement);
我习惯在角速率环里用微分先行,因为遥控器打杆时目标值变化很快,标准微分会导致电机瞬间猛转,听着都吓人。
2.4 PID知识体系总览
下面这张图把PID的核心逻辑串起来了。我建议你保存下来,调参时对照着看。
2.5 调参顺序——我的实战经验
很多新手拿到飞控,上来就三个参数一起调。结果P大了加I,I大了加D,D大了又减P——陷入死循环。我个人的调参顺序是:
- 先调P:从小到大,直到出现轻微震荡。然后回调20%。
- 再加D:从小到大,直到震荡消失。D不要太大,否则噪声会放大。
- 最后加I:从小到大,直到稳态误差消失。I不要太大,否则积分饱和。
记住:P和D是搭档,I是最后才上的。我见过有人先调I,结果飞机一直晃,还以为是P不够大——其实I已经饱和了。
一个小技巧: 调参时用手轻轻推一下飞机,看它回中的速度和超调量。如果回中慢,加P;如果回中后还在晃,加D;如果回中后停歪了,加I。这个方法比看曲线直观多了。