一节滤波分析

2 阅读2分钟

一阶滤波(通常指一阶低通滤波)是信号处理中最基础且实用的算法之一。它的核心思想是:本次输出 = α×\alpha \times 本次采样值 + (1α)×(1 - \alpha) \times 上次输出值

这种滤波器能有效滤除高频噪声,保留信号的低频趋势。


1. 数学模型

一阶低通滤波的差分方程为:

y(n)=αx(n)+(1α)y(n1)y(n) = \alpha \cdot x(n) + (1 - \alpha) \cdot y(n-1)

其中:

  • x(n)x(n):当前输入采样值
  • y(n)y(n):当前滤波输出值
  • y(n1)y(n-1):上次滤波输出值
  • α\alpha:滤波系数,范围为 [0,1][0, 1]α\alpha 越小,平滑效果越强,但相位滞后(延迟)也越大。

如何评估α\alpha 对于数据滞后影响我们可以通过以下公式来评估(时域): 在离散系统中,如果采样周期为 TT(即 1/fs1/f_s),滤波系数为 α\alpha

τT(1α)α\tau \approx \frac{T \cdot (1 - \alpha)}{\alpha}

  • 直观理解:如果你的 α\alpha 越小,τ\tau 就越大,意味着滤波器“记性”越好,反应越慢,滞后越明显。

2. MATLAB 实现

其实所有的滤波算法可以提前通过matlab实现仿真,这样更能直观体现算法和系数的优缺点。

Matlab

fs = 1000;              % 采样频率
t = 0:1/fs:1;           % 时间轴
alpha = 0.1;            % 滤波系数

% 生成信号:5Hz正弦波 + 高频噪声
raw_signal = sin(2*pi*5*t) + 0.5*randn(size(t));

% 滤波处理
filtered_signal = zeros(size(raw_signal));
filtered_signal(1) = raw_signal(1); % 初始化

for n = 2:length(raw_signal)
    filtered_signal(n) = alpha * raw_signal(n) + (1 - alpha) * filtered_signal(n-1);
end

% 绘图对比
figure;
plot(t, raw_signal, 'Color', [0.8, 0.8, 0.8], 'DisplayName', '原始噪声信号');
hold on;
plot(t, filtered_signal, 'r', 'LineWidth', 1.5, 'DisplayName', '一阶滤波后');
legend;
title(['一阶低通滤波 (alpha = ', num2str(alpha), ')']);
grid on;

image.png


3. C 语言实现

在嵌入式系统中(如mcu),通常使用结构体或静态变量来维护滤波器的状态。

基础模板如下

C

//********************滤波参数结构体
typedef struct 
{
    float alpha;
    float output;
} FirstOrderFilter;

//********************滤波初始化 (alpha 的设定 和 历史数据清理)
void Filter_Init(FirstOrderFilter *f, float alpha) 
{
    f->alpha = alpha;
    f->output = 0.0f;
}

//********************滤波工作函数
float Filter_Update(FirstOrderFilter *f, float input) 
{
    f->output = f->alpha * input + (1.0f - f->alpha) * f->output;
    return f->output;
}

int main() 
{
    FirstOrderFilter myFilter;
    Filter_Init(&myFilter, 0.1f); // 滤波系数设为0.1

    float test_data[] = {10.0, 12.5, 11.0, 25.0, 13.0}; // 模拟采样输入
    
    for(int i = 0; i < 5; i++) 
    {
        float result = Filter_Update(&myFilter, test_data[i]);
        printf("Input: %.2f -> Output: %.2f\n", test_data[i], result);
    }
    return 0;
}

如果你的 MCU 没有硬件浮点单元(FPU),建议将 α\alpha 放大成整数进行运算。

例如:Output = (AlphaInt * Input + (1024 - AlphaInt) * LastOutput) >> 10;(这里使用 210=10242^{10}=1024 作为基数)。


4. 如何选择 α\alpha

α\alpha 的选取通常取决于采样频率 fsf_s 和你想要的截止频率 fcf_c

公式推导如下:

α=2πfcΔt2πfcΔt+12πfc/fs\alpha = \frac{2\pi f_c \Delta t}{2\pi f_c \Delta t + 1} \approx 2\pi f_c / f_s

  • 如果你想滤掉大部分抖动,减小 α\alpha
  • 如果你发现系统响应太慢(信号慢半拍),增大 α\alpha

具体α\alpha选取不仅考虑滤波最终效果,还要考虑对于系统实时性的把控。