在单片机控制程序中,经常能看到下面这种一阶低通滤波器:
c
y += alpha * (x - y);
它也可以写成离散差分方程:
yk=(1−α)yk−1+αxk
其中:
- xk 是当前采样值;
- yk 是当前滤波输出;
- α 是滤波系数,通常满足 0<α≤1。
α 越小,滤波越强,但响应越慢; α=1 时输出完全等于输入,相当于没有滤波。
工程中常见两种根据截止频率计算 α 的方法:
- 指数映射法,即精确匹配连续系统的时间常数;
- 后向欧拉法,即将连续微分方程做数值离散化。
两种方法都来自同一个连续一阶低通模型,只是离散化方式不同。
1. 连续一阶低通模型
模拟RC低通滤波器满足:
τdtdy+y=x
整理为:
dtdy=τx−y
其中 τ 是滤波器时间常数。时间常数与截止频率的关系为:
τ=2πfc1
这里 fc 的单位是Hz。公式中出现 2π,是因为微分方程使用角频率:
ωc=2πfc
采样周期和采样频率的关系为:
Ts=fs1
2. 方法一:指数映射法
假设一个采样周期内输入 x 保持不变,定义输入与输出之间的误差:
e=x−y
一阶系统的误差会按照指数规律衰减:
e(t+Ts)=e(t)e−Ts/τ
因此,一个采样周期后的输出为:
yk=xk+(yk−1−xk)e−Ts/τ
整理得到:
yk=yk−1+(1−e−Ts/τ)(xk−yk−1)
与标准代码形式对比:
c
y += alpha * (x - y);
可以得到:
α=1−e−Ts/τ
代入 Ts=1/fs 和 τ=1/(2πfc):
α=1−e−2πfc/fs
从极点角度理解
连续一阶低通的极点是:
s=−2πfc
经过采样后,连续极点映射到离散域:
z=esTs=e−2πfc/fs
而差分方程的离散极点是 z=1−α,所以:
1−α=e−2πfc/fs
最终仍然得到相同结果。
这种方法精确保持了连续系统的极点和时间常数,因此也常被称为精确极点映射或零阶保持离散化。
3. 方法二:后向欧拉法
从同一个连续微分方程出发:
dtdy=τx−y
使用后向差分近似导数:
Tsyk−yk−1=τxk−yk
注意右侧使用的是当前输出 yk,这正是"后向欧拉"名称的来源。
整理方程:
yk=Ts+ττyk−1+Ts+τTsxk
写成标准滤波形式:
yk=yk−1+α(xk−yk−1)
得到:
α=Ts+τTs
代入采样频率和截止频率:
α=fs+2πfc2πfc
也可以定义:
r=fs2πfc
于是:
α=1+rr
后向欧拉法属于近似离散化,但它有一个重要优点:对于正的时间常数,计算得到的 α 始终处于0到1之间,数值稳定性很好。
4. 两种方法为什么很接近
令:
r=fs2πfc
指数映射法为:
αexp=1−e−r
后向欧拉法为:
αBE=1+rr
当截止频率远低于采样频率,即 r≪1 时,可以做级数展开:
1−e−r=r−2r2+⋯
1+rr=r−r2+⋯
两者的一阶项完全相同:
α≈fs2πfc
所以,当 fc 远低于 fs 时,两种方法的实际差别很小。截止频率越接近采样频率,两种离散化方法的差别才会逐渐明显。
5. 数值计算示例
假设:
fs=20000 Hz,fc=100 Hz
指数映射法
αexp=1−e−2π×100/20000≈0.03093
后向欧拉法
αBE=20000+2π×1002π×100≈0.03046
两者相差约1.5%,在大多数电机控制滤波场景中几乎没有明显区别。
6. 20kHz采样时的参数对比
| 截止频率 | 指数映射法 | 后向欧拉法 | 相对差异 |
|---|---|---|---|
| 20Hz | 0.006263 | 0.006244 | 0.31% |
| 23.5Hz | 0.007356 | 0.007329 | 0.37% |
| 30Hz | 0.009381 | 0.009337 | 0.47% |
| 50Hz | 0.015585 | 0.015465 | 0.77% |
| 100Hz | 0.030928 | 0.030459 | 1.51% |
| 200Hz | 0.060899 | 0.059117 | 2.92% |
| 500Hz | 0.145364 | 0.135755 | 6.61% |
| 1kHz | 0.269597 | 0.239057 | 11.33% |
可以看到,在20kHz采样、几十到几百赫兹截止频率的情况下,两种方法结果非常接近。
7. C语言实现
c
#include <math.h>
#define PI_F 3.14159265358979323846f
/* 方法一:指数映射,精确匹配连续时间常数 */
static float lpf_alpha_exponential(float cutoff_hz, float sample_hz)
{
return 1.0f - expf(-2.0f * PI_F * cutoff_hz / sample_hz);
}
/* 方法二:后向欧拉,计算简单且稳定 */
static float lpf_alpha_backward_euler(float cutoff_hz, float sample_hz)
{
float r = 2.0f * PI_F * cutoff_hz / sample_hz;
return r / (1.0f + r);
}
/* 一阶低通滤波器 */
static float lpf_update(float input, float previous_output, float alpha)
{
return previous_output + alpha * (input - previous_output);
}
alpha 应在初始化阶段计算一次,不建议在高频中断中反复调用 expf()。
如果采样频率和截止频率都是固定常量,也可以提前计算好系数:
c
#define CURRENT_LPF_ALPHA 0.03093f /* fs=20kHz, fc=100Hz, 指数映射 */
8. 应该选择哪一种
优先选择指数映射法的情况
- 希望准确保持连续系统的时间常数;
- 希望连续极点和离散极点严格对应;
- 参数在初始化阶段计算,计算量不是问题。
公式为:
α=1−e−2πfc/fs
可以选择后向欧拉法的情况
- 希望计算形式简单;
- 需要始终保证 0<α<1;
- 截止频率远低于采样频率;
- 希望沿用常见的数字RC滤波写法。
公式为:
α=fs+2πfc2πfc
复刻既有控制器时
如果目标是复刻原控制器,应优先保留原始系数。例如YKD3505M中的滤波系数:
α=32768241=0.0073547
在20kHz采样频率下,按照指数映射反算,对应时间常数频率约为23.5Hz。此时应先保持原系数验证整体算法,再根据新硬件和电机响应调整。
9. 一个容易忽略的严谨性问题
上面两种公式的 fc 都来自连续RC模型。指数映射法精确保持连续系统的时间常数,后向欧拉法近似保持连续系统的动态特性。
当 fc≪fs 时,离散滤波器实际的-3dB频率与目标值几乎一致;当截止频率已经接近采样频率时,这种近似会出现明显偏差。此时如果必须精确控制数字域的-3dB频率,应按照离散频率响应直接求系数,或者使用双线性变换设计IIR滤波器,而不应继续使用低频近似。
总结
两种系数计算方法并不矛盾:
α=1−e−2πfc/fs
来自连续一阶系统的精确指数响应;
α=fs+2πfc2πfc
来自后向欧拉离散化。
当截止频率远低于采样频率时,两者都近似为:
α≈fs2πfc
在常见的电机控制场景中,只要明确采样频率、截止频率和使用的离散化方法,两种公式都可以可靠使用。