一阶低通滤波:从连续模型到离散实现(含工程代码)

在电机控制、传感器信号处理和嵌入式系统中,一阶低通滤波(First-Order Low-Pass Filter, LPF)几乎是最常用、也是最容易被误用的基础模块之一。


1. 为什么需要一阶低通滤波?

在实际系统中,我们经常会遇到以下问题:

  • 编码器角度差分得到的速度噪声很大
  • ADC 采样存在抖动和高频干扰
  • 控制环(PI / PID)对高频噪声极其敏感

低通滤波的目的只有一个:

抑制高频噪声,只保留系统真实的低频动态。


2. 连续时间的一阶低通模型

最经典的一阶低通模型来自 RC 电路,其微分方程为:

\[\tau \frac{dy(t)}{dt} + y(t) = x(t) \]

等价写成:

\[\frac{dy(t)}{dt} = \frac{1}{\tau}\big(x(t) - y(t)\big) \]

其中:

  • \(x(t)\):输入信号
  • \(y(t)\):滤波后输出
  • \(\tau\):时间常数(决定滤波强度)

3. 离散化的前提条件

在嵌入式系统中,信号是周期性采样的:

  • 采样周期:\(dt\)
  • 只在 \(t = k \cdot dt\) 进行一次计算

同时我们做一个关键假设(工程默认):

在一个采样周期内,输入信号保持不变(ZOH)


4. 从连续到离散:前向欧拉法

对导数项进行离散近似:

\[\frac{dy}{dt} \approx \frac{y[k] - y[k-1]}{dt} \]

代入连续方程:

\[\frac{y[k] - y[k-1]}{dt} = \frac{1}{\tau}\big(x[k] - y[k-1]\big) \]

整理得到:

\[y[k] = y[k-1] + \frac{dt}{\tau}\big(x[k] - y[k-1]\big) \]


5. 标准离散形式(指数平滑)

引入参数:

\[\alpha = \frac{dt}{\tau} \]

即可得到工程中最常见的一阶低通公式:

\[y[k] = y[k-1] + \alpha \big(x[k] - y[k-1]\big) \]

这个公式的直觉含义是:

每个采样周期,输出只向输入靠近一小步。


6. 更稳定的工程写法(推荐)

严格来说,前向欧拉在 \(dt\) 较大时存在误差。利用连续系统的精确解,可以得到更稳定的参数形式。

连续系统在一个采样周期内的精确解:

\[y[k] = x[k] + (y[k-1] - x[k])e^{-dt/\tau} \]

整理后仍然是同一形式:

\[y[k] = y[k-1] + \alpha (x[k] - y[k-1]) \]

其中参数 \(\alpha\) 推荐定义为:

\[\alpha = 1 - e^{-dt/\tau} \]


7. 离散实现中的“因果性”问题

注意公式中使用的是 \(x[k] - y[k-1]\) 而不是 \(x[k] - y[k]\)

原因很简单:在计算时刻 \(k\)\(y[k]\) 还不存在,系统只能使用上一次的状态 \(y[k-1]\)。这保证了滤波器是一个因果、可实时实现的系统


8. 代码实现(C / MCU 风格)

typedef struct {
    float y;      // 滤波输出
    float alpha;  // 滤波系数
} LPF1_t;

/**
 * @brief 一阶低通滤波更新函数
 * @param f 滤波器结构体指针
 * @param x 当前输入值
 */
void LPF1_Update(LPF1_t *f, float x)
{
    // y(k) = y(k-1) + alpha * (x(k) - y(k-1))
    f->y += f->alpha * (x - f->y);
}
posted @ 2026-01-16 10:29  阿坦  阅读(6)  评论(0)    收藏  举报