一阶低通滤波器(LPF):从模拟RC到数字实现
做电机控制这些年,我遇到最多的一个问题就是:怎么把传感器信号里的高频毛刺去掉,又不影响控制带宽?
答案其实很简单——一阶低通滤波器。但很多人用不好它。要么滤波效果太弱,要么把有用的信号也滤没了。今天我就把这块彻底讲透。
模拟RC低通:理解本质
先看模拟电路。一个电阻R串联,一个电容C对地并联,这就是最经典的RC低通滤波器。
它的传递函数长这样:
H(s) = 1 / (1 + s * R * C)
这里有个关键参数——时间常数 τ = R * C。τ越大,滤波越强,但响应越慢。
我刚开始做电机电流采样滤波时,就吃过这个亏。选了个很大的电容,结果电流环带宽直接掉了一半,电机跑起来嗡嗡响。嗯,这就是滤波过度了。
截止频率的计算
截止频率 f_c 是滤波器的分水岭。低于这个频率的信号基本保留,高于的会被衰减。
计算公式:
f_c = 1 / (2 * π * R * C)
举个例子:R=1kΩ,C=1μF
f_c = 1 / (2 * 3.14 * 1000 * 0.000001) ≈ 159 Hz
这意味着159Hz以上的信号会被逐渐削弱。在电机控制里,我一般把电流采样滤波的截止频率设在开关频率的1/10到1/20之间。比如10kHz的PWM,f_c取500Hz到1kHz比较合适。
从模拟到数字:一阶后向差分法
模拟滤波器好用,但我们的控制器是数字的。怎么办?离散化。
最常用的方法是一阶后向差分。说白了,就是用差分方程近似微分方程。
模拟域的传递函数:
Y(s) / X(s) = 1 / (1 + s * τ)
写成微分方程:
τ * dy/dt + y = x
用后向差分近似导数:
dy/dt ≈ (y[n] - y[n-1]) / T
其中T是采样周期。代入整理后得到:
y[n] = α * x[n] + (1 - α) * y[n-1]
这里的α是关键:
α = T / (τ + T) = T / (1/(2πf_c) + T)
你看,这个公式多简洁。当前输出 = 当前输入乘以α + 上次输出乘以(1-α)。
代码实现:C语言版
直接上代码。这是我常用的结构体实现:
typedef struct {
float alpha; // 滤波系数
float y_prev; // 上一次输出值
float y; // 当前输出值
} LPF_1stOrder;
// 初始化
void LPF_Init(LPF_1stOrder *lpf, float fc, float Ts) {
float tau = 1.0f / (2.0f * 3.14159f * fc);
lpf->alpha = Ts / (tau + Ts);
lpf->y_prev = 0.0f;
lpf->y = 0.0f;
}
// 滤波计算
float LPF_Process(LPF_1stOrder *lpf, float x) {
lpf->y = lpf->alpha * x + (1.0f - lpf->alpha) * lpf->y_prev;
lpf->y_prev = lpf->y;
return lpf->y;
}
使用示例:
LPF_1stOrder current_filter;
LPF_Init(¤t_filter, 500.0f, 0.0001f); // fc=500Hz, Ts=100μs
while(1) {
float raw_current = ADC_GetValue();
float filtered_current = LPF_Process(¤t_filter, raw_current);
// 用filtered_current做控制
}
参数调优:实战经验
调参数这事,光看公式不行。我总结了几条实战经验:
| 场景 | 推荐截止频率 | 注意事项 |
|---|---|---|
| 电流采样滤波 | 开关频率/10 ~ 开关频率/20 | 太大会引入延迟,影响电流环带宽 |
| 速度计算滤波 | 速度环带宽的2~5倍 | 速度信号本身延迟大,滤波不要太强 |
| 位置信号滤波 | 1~10Hz | 位置信号低频为主,滤波可以狠一点 |
| 编码器信号去毛刺 | 500Hz~2kHz | 主要滤除机械振动引起的高频抖动 |
离散化公式的另一种形式
有时候你会看到这样的写法:
y[n] = y[n-1] + α * (x[n] - y[n-1])
这和前面的公式是等价的。我个人更喜欢这种写法,因为它更直观——每次只把输入和输出的差值的一部分加进去。α就是那个「一部分」的比例。
举个例子:如果α=0.1,每次只修正10%的误差。这样滤波就很平滑,但需要10个采样周期才能接近目标值的63%。
知识体系总览
下面这张图把一阶低通滤波器的核心逻辑串起来了:
几个实用技巧
- 初始化要小心: 第一次滤波时,y_prev最好赋值为当前输入值,而不是0。否则第一个输出会从0跳变到输入,产生冲击。
- 定点数实现: 在低端MCU上,用定点数代替浮点数。α用Q15格式表示,乘法用移位实现,速度能快好几倍。
- 变系数滤波: 启动时用大α快速跟踪,稳态后用小α平滑滤波。我做过一个自适应方案,效果比固定系数好很多。
- 注意采样周期: α依赖于采样周期T。如果T变化(比如任务调度不稳定),滤波效果会飘。这时候要用定时器固定采样间隔。
一阶低通滤波器看似简单,但用好了能解决很多实际问题。记住:滤波不是越强越好,关键是在噪声抑制和信号保真度之间找到平衡点。下次遇到传感器信号毛刺多的时候,先别急着加复杂的滤波器,试试一阶低通,说不定就搞定了。
公众号:蓝海资料掘金营,微信deep3321