ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

一阶低通滤波器:从连续模型到数字实现的原理与工程实践

一阶低通滤波器:从连续模型到数字实现的原理与工程实践

1. 从“平滑”说起:为什么我们需要一阶低通滤波?

在信号处理、控制系统、传感器数据采集乃至音频处理等众多领域,我们常常会遇到一个看似简单却至关重要的需求:如何从混杂着噪声的数据中,提取出我们真正关心的、变化相对缓慢的趋势信号?想象一下,你用一个精度一般的温度传感器测量室温,读数可能在24.5°C到25.5°C之间快速跳动,但你知道实际的室温不可能在一秒内变化1度。这些快速的跳动就是高频噪声,而真实的室温是低频的、缓慢变化的信号。你的直觉可能是“取个平均值”,这没错,但平均值是对过去一段时间数据的“一视同仁”,而我们常常希望越新的数据越重要,越老的数据影响力越小。这种能实现“平滑”且“侧重近期”的数学工具,就是一阶低通滤波器。

一阶低通滤波器的核心思想,是建立一个简单的动态系统,其输出会“跟随”输入变化,但不会“立刻跟上”。它像一个有惯性的系统,或者一个反应迟钝的“跟班”。当输入信号快速变化(高频)时,它跟不上,输出变化很小,这部分高频成分就被“滤除”了;当输入信号缓慢变化(低频)时,它能跟得上,输出能较好地复现输入,这部分低频成分就被“通过”了。这个“跟不上”的程度,由一个关键参数决定:截止频率。它定义了滤波器“反应速度”的边界,频率高于此值的信号成分会被显著衰减。

然而,我们生活在一个数字化的世界。传感器采样得到的是离散时间点上的数据,微处理器(MCU)、数字信号处理器(DSP)或计算机程序处理的也是离散的数值序列。我们在教科书或理论推导中看到的滤波器,通常是用连续时间的微分方程或拉普拉斯变换来描述的,比如那个经典的传递函数1/(τs + 1)。但计算机无法直接解微分方程,它只能处理差分方程。因此,我们必须将连续时间的滤波器模型,转化为离散时间的形式,这个过程就是离散化。离散化不是简单的“替换”,它涉及到采样周期、数值稳定性、频率响应畸变等一系列工程实践中的核心问题。一个设计不当的离散化滤波器,可能会引入额外的相位延迟、幅度失真,甚至变得不稳定。

所以,理解一阶低通滤波,绝不仅仅是记住一个公式。它关乎如何在数字系统中,优雅地实现“平滑”与“跟随”的权衡。本文将彻底拆解一阶低通滤波器的原理,并深入探讨几种主流的离散化方法(如前向欧拉、后向欧拉、双线性变换),分析它们各自的特性、适用场景以及在特定频率点(如w处)的幅值响应,最终给出可直接嵌入代码的实用公式和避坑指南。

2. 连续时间域的一阶低通滤波器:原理与模型

在连续时间域,一个一阶低通滤波器可以用一个一阶常系数线性微分方程来描述。这是所有分析的起点。

2.1 微分方程与传递函数

最直观的模型来源于一个简单的RC电路。一个电阻R和一个电容C串联,输入电压V_in(t)加在串联组合上,输出电压V_out(t)从电容两端取出。根据基尔霍夫电压定律和电容的电流-电压关系,我们可以得到:V_in(t) = R * C * dV_out(t)/dt + V_out(t)令时间常数τ = R * C,方程简化为:τ * dV_out(t)/dt + V_out(t) = V_in(t)这就是一阶低通滤波器的时域微分方程。τ的单位是秒,它直接决定了系统的动态特性。τ越大,电容充电放电越慢,系统惯性越大,滤波效果越“强”,输出对输入的响应越迟缓。

为了在频域分析,我们对上述微分方程两边取拉普拉斯变换(假设初始条件为零)。拉普拉斯变换将微分算子d/dt转换为复变量s。于是得到:τ * s * V_out(s) + V_out(s) = V_in(s)整理后,得到传递函数H(s)H(s) = V_out(s) / V_in(s) = 1 / (τs + 1)这就是一阶低通滤波器在s域(连续频域)的标准形式。

2.2 频率响应与截止频率

传递函数H(s)描述了系统对不同频率正弦输入的稳态响应。我们将s替换为(其中j是虚数单位,ω是角频率,单位 rad/s),就得到了频率响应函数H(jω)H(jω) = 1 / (jωτ + 1)这是一个复数,其模(绝对值)表示系统对频率为ω的信号的放大(或衰减)倍数,称为幅频特性;其辐角表示输出信号相对于输入信号的相位偏移,称为相频特性

幅频特性|H(jω)|计算如下:|H(jω)| = 1 / sqrt((ωτ)^2 + 1)从这个公式我们可以清晰地看到滤波器的“低通”特性:

  • ω = 0(直流信号)时,|H(j0)| = 1,信号无衰减通过。
  • 随着ω增大,分母增大,|H(jω)|减小,高频成分被衰减。
  • ω = 1/τ时,|H(jω)| = 1 / sqrt(2) ≈ 0.707。在工程上,通常将幅度下降到直流增益的1/sqrt(2)(即-3dB点)所对应的频率定义为截止频率ω_c。因此:ω_c = 1 / τ(rad/s) 对应的普通频率f_c为:f_c = ω_c / (2π) = 1 / (2πτ)(Hz)

所以,时间常数τ直接决定了截止频率:τ越大,ω_c越小,滤波器带宽越窄,允许通过的频率成分越少,平滑效果越强。

相频特性∠H(jω) = -arctan(ωτ)。这表明低通滤波器会引入负的相位滞后(输出相位落后于输入),且频率越高,滞后越严重,在截止频率处滞后45度。

注意:这个-3dB截止频率的定义是通用的。但在一些对相位有严格要求的场合(如控制系统环路补偿),可能会使用其他定义,如幅值衰减到-1dB或相位滞后达到特定角度的频率。本文后续均采用-3dB定义。

2.3 阶跃响应:理解“惯性”

除了频域,时域的阶跃响应能让我们直观感受滤波器的“惯性”。假设输入V_in(t)是一个在t=0时刻从0跳变到1的阶跃信号。求解微分方程τ * dy/dt + y = 1(其中y=V_out),可得:y(t) = 1 - e^(-t/τ)这是一个指数上升曲线。τ是时间常数,当t = τ时,输出上升到稳态值(1)的1 - e^(-1) ≈ 63.2%τ越大,上升到63.2%所需时间越长,系统响应越慢。这个特性是我们在离散化时选择采样周期的重要依据。

3. 从连续到离散:离散化的核心方法与推导

现在进入核心环节:如何让计算机实现H(s) = 1/(τs+1)?我们需要将s域的传递函数转化为适用于数字计算的z域传递函数或差分方程。这个过程就是离散化,主要有三种经典方法:前向欧拉、后向欧拉和双线性变换(又称Tustin变换)。每种方法都是对微分算子s的一种近似。

3.1 前向欧拉法

前向欧拉法是最直观的近似。它用前向差分来近似微分:dy/dt ≈ (y[n] - y[n-1]) / T其中,y[n]表示当前时刻(第n个采样点)的输出值,y[n-1]是上一时刻的输出值,T是采样周期。在z域,延迟一个采样周期对应于乘以z^{-1}。因此,(y[n] - y[n-1])/T的z变换是(Y(z) - z^{-1}Y(z))/T = (1 - z^{-1})Y(z)/T。而dy/dt的拉普拉斯变换是sY(s)。所以,前向欧拉法建立了s与z的近似关系:s ≈ (1 - z^{-1}) / T将这个替换关系代入连续传递函数H(s) = 1/(τs+1)H(z) = 1 / ( τ * ((1 - z^{-1})/T) + 1 ) = 1 / ( (τ/T)(1 - z^{-1}) + 1 )a = τ / T,则:H(z) = 1 / ( a*(1 - z^{-1}) + 1 ) = 1 / ( a + 1 - a*z^{-1} )为了得到差分方程,我们写回时域关系。由H(z) = Y(z)/X(z),有:(a + 1 - a*z^{-1}) Y(z) = X(z)转换为时域差分方程:(a+1)y[n] - a*y[n-1] = x[n]最终得到前向欧拉法的递推公式:y[n] = (x[n] + a*y[n-1]) / (a + 1)其中,a = τ / Tx[n]是当前输入,y[n]是当前输出,y[n-1]是上一次的输出。

特点与问题

  • 优点:公式极其简单,计算量小。
  • 缺点:稳定性差。对于这个一阶系统,只有当a > 0(即τ/T > 0)时才稳定,这通常成立。但对于高阶系统或某些参数,前向欧拉法可能将稳定的连续系统映射为不稳定的离散系统。此外,其频率响应畸变较大。

3.2 后向欧拉法

后向欧拉法采用后向差分来近似微分:dy/dt ≈ (y[n] - y[n-1]) / T注意,这里微分近似用的是当前时刻和上一时刻的差分,但s域近似关系不同。实际上,后向差分对应的s与z关系是:s ≈ (1 - z^{-1}) / (T * z^{-1}) = (z - 1) / (Tz)另一种更常见的推导是从积分角度:y[n] = y[n-1] + T * f(y[n], t[n]),对于我们的方程τ * dy/dt + y = x,整理为dy/dt = (x - y)/τ,用后向欧拉(即用y[n]来近似右边的y):(y[n] - y[n-1]) / T = (x[n] - y[n]) / τ解这个方程更容易。整理上式:y[n] - y[n-1] = (T/τ) * (x[n] - y[n])y[n] + (T/τ)y[n] = y[n-1] + (T/τ)x[n]y[n] (1 + T/τ) = y[n-1] + (T/τ)x[n]α = T / (τ + T) = T / (T + τ),我们可以得到更简洁的形式。由上式:y[n] = y[n-1] * (τ/(τ+T)) + x[n] * (T/(τ+T))α = T/(τ+T),则τ/(τ+T) = 1 - α。因此,后向欧拉法的标准递推公式为:y[n] = (1 - α) * y[n-1] + α * x[n]其中,α = T / (T + τ)0 < α <= 1(当T>0, τ>0)。

特点与问题

  • 优点无条件稳定。无论采样周期T取多大(理论上),由稳定的连续系统离散化得到的离散系统也是稳定的。这是它最大的优点。
  • 缺点:频率响应在高频段有严重畸变。当实际频率接近奈奎斯特频率(f_s/2)时,后向欧拉法会将其映射到s域一个非常高的频率,导致过度衰减,这种现象称为“频率扭曲”。

3.3 双线性变换法

双线性变换是一种更精确的离散化方法,它通过将s平面的左半平面映射到z平面的单位圆内部来保证稳定性,同时通过预畸变来补偿频率扭曲。

双线性变换的公式是:s ≈ (2/T) * (1 - z^{-1}) / (1 + z^{-1})将这个关系代入H(s) = 1/(τs+1)H(z) = 1 / ( τ * (2/T) * (1 - z^{-1})/(1 + z^{-1}) + 1 )化简过程: 令K = 2τ / TH(z) = 1 / ( K * (1 - z^{-1})/(1 + z^{-1}) + 1 ) = (1 + z^{-1}) / ( K*(1 - z^{-1}) + (1 + z^{-1}) ) = (1 + z^{-1}) / ( (K+1) + (1-K)z^{-1} )现在,令β = T / (T + 2τ)。我们可以建立联系。注意到K = 2τ/T,所以K+1 = (2τ/T)+1 = (2τ+T)/T1-K = 1 - 2τ/T = (T-2τ)/T。 那么H(z)可以写为:H(z) = β * (1 + z^{-1}) / (1 - (1 - 2β) z^{-1}), 其中β = T / (T + 2τ)。 更常见的、直接可用的差分方程形式可以通过交叉相乘得到: 由H(z) = Y(z)/X(z) = (1 + z^{-1}) / ( (K+1) + (1-K)z^{-1} ),交叉相乘:[ (K+1) + (1-K)z^{-1} ] Y(z) = (1 + z^{-1}) X(z)转换为时域差分方程:(K+1) y[n] + (1-K) y[n-1] = x[n] + x[n-1]最终得到:y[n] = [ x[n] + x[n-1] - (1-K) y[n-1] ] / (K+1)其中K = 2τ / T

特点与问题

  • 优点具有频率预畸变特性,能保持频率响应的形状。它将s域的整个虚轴(轴)映射到z域的单位圆上,因此频率响应匹配较好,尤其在中低频段。并且它也是无条件稳定的。
  • 缺点:计算比前两种方法稍复杂,涉及当前输入、上一次输入和上一次输出。存在频率扭曲,但通过预畸变可以校正。对于给定的离散截止频率ω_{d},需要先通过公式ω_{a} = (2/T) * tan(ω_{d}T/2)计算出一个“预畸变”的连续频率ω_{a},然后用ω_{a}来设计连续滤波器参数τ(τ = 1/ω_{a}),这样离散化后的滤波器在ω_{d}处才会有准确的-3dB衰减。

4. 方法对比与工程选型:何时用哪种?

了解了三种方法后,我们面临一个实际问题:在工程中如何选择?

前向欧拉法:由于其潜在的稳定性问题,在滤波器设计中很少被采用。除非你能严格保证T非常小(远小于系统时间常数τ),且系统简单。一般不推荐。

后向欧拉法:这是最常用、最推荐用于一阶低通滤波的实现方法。原因如下:

  1. 无条件稳定:这是最重要的工程属性。无论代码运行在1kHz还是100Hz的采样率下,滤波器都不会发散。
  2. 公式极其简单y[n] = (1 - α) * y[n-1] + α * x[n]。只有一个系数α需要计算和存储,一次乘法一次加法,计算效率极高,非常适合资源受限的嵌入式系统。
  3. 物理意义清晰α可以理解为“新采样值的权重”。α越大(T越大或τ越小),滤波器“惯性”越小,跟踪输入越快;α越小,平滑效果越强。
  4. 参数计算方便:已知期望的截止频率f_c和采样频率f_s(T = 1/f_s),可以先计算连续时间常数τ = 1/(2πf_c),然后计算α = T / (T + τ)。或者,更直接地,利用αf_cf_s的关系:α = 2πf_cT / (2πf_cT + 1)。当2πf_cT << 1(即采样频率远高于截止频率)时,α ≈ 2πf_cT

双线性变换法:在以下场景考虑使用:

  1. 对频率响应精度要求高:例如在音频处理、数字均衡器中,需要精确控制特定频率点的增益。
  2. 滤波器阶数较高:在设计高阶IIR滤波器时,双线性变换是标准方法,因为它能保持稳定性并可通过预畸变校正频响。
  3. 作为性能基准:当你需要验证后向欧拉法在特定应用中的失真程度时,可以用双线性变换的结果作为参考。

实操心得:对于99%的嵌入式传感器数据平滑(如陀螺仪、加速度计、温度、电流采样),后向欧拉法的简单性、稳定性和足够好的性能使其成为首选。我曾在多个电机控制、无人机飞控项目中用它来滤波电流环反馈和角速度信号,从未出过问题。关键是要根据信号特性和噪声频谱合理选择α

4.1 离散化后的频率响应分析

我们更关心离散化后的滤波器在实际数字频率ω_dω_d = 2πf / f_s,范围0π)上的表现。以最常用的后向欧拉法为例,其传递函数为:H(z) = α / (1 - (1-α)z^{-1})z = e^{jω_d}代入,可以计算其幅频响应|H(e^{jω_d})|。经过推导(过程略),在ω_d较小时,其-3dB截止角频率ω_{c_d}近似满足:tan(ω_{c_d}/2) ≈ (α/(2-α)) * (ω_{c_d}/2)α很小时,近似有ω_{c_d} ≈ α。更精确的关系是:设计时,若期望的离散截止角频率为ω_{c_d},则所需的α约为α ≈ 2 sin(ω_{c_d}/2) / (cos(ω_{c_d}/2) + sin(ω_{c_d}/2))。但在工程中,更常用的方法是直接用连续频率来算:α = T/(T+τ) = 1/(1 + τ f_s)

关于“一阶低通滤波在w处幅值”:这是一个很实际的测试点。假设我们想知道离散滤波器在某个特定数字频率ω处的增益。以双线性变换法为例,由于其频率扭曲,在ω_d处的响应对应于连续频率ω_a = (2/T) tan(ω_d/2)处的响应。所以,如果你设计时没有预畸变,那么你在ω_d处测得的幅值,实际上是连续滤波器在ω_a处的幅值1/sqrt(1+(ω_a τ)^2)。这解释了为什么有时离散滤波器的截止频率看起来“偏移”了。而后向欧拉法在高频段的衰减比理论连续滤波器更剧烈。

5. 实战:从理论到代码的完整实现与调试

理论最终要落地为代码。这里以最通用的后向欧拉法为例,展示完整的实现流程和注意事项。

5.1 确定设计指标

假设我们有一个传感器,采样频率f_s = 100 Hz(T = 0.01 s)。信号中有高频噪声,我们期望滤除50Hz以上的噪声成分。因此,设定滤波器的**-3dB截止频率f_c = 5 Hz**。这是一个比较典型的设计,截止频率远低于采样频率的一半(奈奎斯特频率50Hz),以避免混叠,同时也留出了足够的过渡带。

5.2 计算滤波器系数

  1. 计算连续时间常数ττ = 1 / (2πf_c) = 1 / (2 * 3.1416 * 5) ≈ 0.03183秒。
  2. 计算权重系数αα = T / (T + τ) = 0.01 / (0.01 + 0.03183) ≈ 0.01 / 0.04183 ≈ 0.239。 或者用近似公式α ≈ 2πf_c T = 2*3.1416*5*0.01 = 0.314,这个近似值偏大,因为2πf_cT=0.314并不远小于1。在要求不高的场合可用,但精确设计建议用前一个公式。
  3. 计算(1 - α)1 - α ≈ 1 - 0.239 = 0.761

所以,我们的递推公式为:y[n] = 0.761 * y[n-1] + 0.239 * x[n]

5.3 C语言代码实现

// 一阶低通滤波器结构体 typedef struct { float alpha; // 系数 α float output_prev; // 上一次的输出值 y[n-1] } FirstOrderLPF; // 初始化滤波器 void LPF_Init(FirstOrderLPF *lpf, float cutoff_freq, float sample_freq) { float tau = 1.0f / (2.0f * 3.1415926535f * cutoff_freq); lpf->alpha = 1.0f / (1.0f + tau * sample_freq); // 因为 T = 1/sample_freq // 另一种等价计算:lpf->alpha = (1.0f/sample_freq) / ((1.0f/sample_freq) + tau); lpf->output_prev = 0.0f; // 初始输出通常设为0或第一次的输入值 } // 执行一次滤波计算 float LPF_Update(FirstOrderLPF *lpf, float input) { float output = (1.0f - lpf->alpha) * lpf->output_prev + lpf->alpha * input; lpf->output_prev = output; // 更新状态 return output; } // 使用示例 int main() { FirstOrderLPF my_filter; float sample_freq = 100.0f; // 100 Hz float cutoff_freq = 5.0f; // 5 Hz LPF_Init(&my_filter, cutoff_freq, sample_freq); // 模拟循环采样 while(1) { float raw_sensor_data = Read_Sensor(); // 假设的函数 float filtered_data = LPF_Update(&my_filter, raw_sensor_data); // 使用 filtered_data... Delay(10); // 延迟10ms,维持100Hz采样 } return 0; }

5.4 关键实现细节与避坑指南

  1. 数据类型选择:在嵌入式系统中,根据精度和速度要求选择floatfixed-point(定点数)。对于α这种介于0和1之间的小数,浮点数处理更方便。若用定点数,需仔细处理量化误差和溢出。
  2. 初始化output_prev的初始值会影响滤波器启动阶段的瞬态响应。通常有两种做法:
    • 设为0。滤波器需要一段时间(几个时间常数)才能达到稳定跟踪。
    • 设为第一次的输入值x[0]。这样输出从一开始就“跟得上”,但若第一个采样值是噪声尖峰,也会导致初始偏差。可以根据应用场景选择,或让滤波器空跑几个周期直到稳定后再使用输出。
  3. 系数α的范围:理论上α ∈ (0, 1]α=1时,y[n]=x[n],滤波器完全透明(无滤波)。α越接近0,平滑效果越强。切勿让α等于或小于0,否则滤波器会不稳定或行为异常。确保你的cutoff_freqsample_freq都是正数,且cutoff_freq小于sample_freq/2(奈奎斯特频率)。
  4. 采样频率与截止频率的关系:这是一个常见的坑。截止频率f_c必须显著小于采样频率f_s。经验法则是f_c < f_s / 10。如果f_c接近f_s/2,离散化误差会非常大,滤波器特性会严重偏离预期。在上例中,f_s=100Hz,f_c=5Hz,比例是20倍,是合理的。
  5. 实时性要求LPF_Update函数执行时间必须小于采样周期T。在高速采样场合(如f_s=10kHz),需优化计算(查表法计算α,使用更快的乘法指令等)。
  6. 抗溢出处理:在定点数实现或输入信号幅值很大的情况下,乘法操作可能导致溢出。需要评估中间变量的动态范围,必要时进行缩放。

5.5 性能验证与调试

如何验证你的滤波器工作正常?

  1. 阶跃响应测试:输入一个从0跳变到常数的信号,观察输出是否按指数曲线平滑上升,时间常数是否约为τ(达到63.2%的时间)。
  2. 正弦扫频测试(如果条件允许):输入不同频率的正弦波,测量输出幅值与输入幅值的比值,绘制幅频特性曲线,看-3dB点是否在设计的f_c附近。
  3. 观察实际数据:在真实系统中,将原始信号和滤波后信号同时绘制出来。你应该能看到高频毛刺被有效平滑,而真实的趋势变化得以保留。如果发现滤波后信号仍然噪声很大,可能需要降低f_c;如果发现滤波后信号明显滞后于真实变化,可能需要适当提高f_c

踩坑实录:我曾在一个电池电压采样的项目中,将f_c设得过低(0.1Hz),α非常小。在MCU中,由于浮点数精度限制,(1-α)计算出来几乎是1.0,导致滤波器更新极其缓慢,几乎“冻住”了。后来改用双精度浮点数,并重新评估了必要的带宽,问题才解决。教训:在系数α极小时,要特别注意数据类型的精度是否足够。

6. 进阶话题:变参数滤波、非线性与多级串联

基础的一阶低通滤波已经能解决大部分问题。但在更复杂的场景下,我们需要一些变体。

6.1 变截止频率滤波

有时,我们希望滤波器的带宽能动态调整。例如,在运动检测中,静止时希望强滤波(小α)来抑制噪声,运动时希望弱滤波(大α)来快速跟踪。 实现很简单:根据某个条件(如加速度幅值)动态计算并更新α(1-α)系数。注意,改变系数会改变滤波器的动态特性,可能会引入瞬态扰动。一种平滑的方法是让系数本身也通过一个低通滤波器缓慢变化。

6.2 非线性滤波:限幅与死区

纯粹的一阶低通滤波是线性的。有时我们需要引入非线性来应对特殊噪声。

  • 限幅滤波:在更新公式前,先判断本次输入x[n]与上一次输出y[n-1]的差值是否超过一个阈值delta_max。如果超过,则认为可能是脉冲干扰,不直接使用x[n],而是使用y[n-1] ± delta_max作为有效输入。这能有效抑制偶发的尖峰脉冲。
  • 死区滤波:当|x[n] - y[n-1]|小于一个很小的阈值dead_zone时,认为变化是噪声,不更新滤波器,即y[n] = y[n-1]。这可以消除传感器在零点附近的小幅抖动。

6.3 多级一阶低通滤波串联

将两个或多个一阶低通滤波器串联,可以得到更高阶的低通滤波效果,其滚降斜率更陡峭(每增加一阶,滚降率增加-20dB/decade)。例如,两个相同的、截止频率为f_c的一阶滤波器串联,其传递函数为[1/(τs+1)]^2。在-3dB点,总衰减是-6dB。这种方法的优点是:

  • 仍然实现简单,只需重复调用一阶滤波函数。
  • 相位滞后会比单级更大,这是代价。
  • 离散化时,可以对每一级独立使用后向欧拉法。

实现时需要注意,串联滤波器的等效截止频率会发生变化。如果希望总体的-3dB截止频率是f_c,那么每一级的设计截止频率需要更高。对于两级相同滤波器,每级的截止频率f_c1约为f_c / sqrt(sqrt(2)-1) ≈ f_c / 0.643。更通用的方法是先确定目标的高阶传递函数,然后用双线性变换等方法来离散化,而不是简单串联离散一阶节。

7. 在具体场景中的应用实例

让我们看两个具体的例子,看看一阶低通滤波如何解决实际问题。

7.1 实例一:单片机读取模拟温度传感器

场景:STM32通过ADC读取NTC热敏电阻的电压来测算温度。ADC读数存在±3LSB的随机噪声,导致直接转换的温度值在±0.2°C范围内波动。目标:平滑温度读数,使得显示的温度值稳定,同时能跟上真实的环境温度变化(通常变化很慢)。设计

  • 采样频率f_s:ADC设置为每秒采样10次(10Hz),T=0.1s
  • 截止频率f_c:环境温度变化通常不超过0.1°C/分钟,即约0.0017 Hz。但为了兼顾一定的响应速度,我们可以设f_c = 0.05 Hz(时间常数约3秒)。这能滤除远高于0.05Hz的ADC噪声。
  • 计算系数:τ = 1/(2π*0.05) ≈ 3.183 sα = T / (T+τ) = 0.1 / (0.1+3.183) ≈ 0.03051-α ≈ 0.9695实现:在ADC中断服务程序或主循环中,调用filtered_temp = 0.9695 * filtered_temp_prev + 0.0305 * raw_temp_adc效果:温度读数的跳动被有效抑制,显示值平滑。当环境温度真实变化时,滤波后的值会在几十秒内逐渐跟踪到新值,这对于温度监控来说是完全可以接受的。

7.2 实例二:平衡小车的陀螺仪角速度滤波

场景:MPU6050陀螺仪输出角速度,用于计算小车倾角。陀螺仪数据存在高频噪声,积分后会导致角度估计漂移。目标:滤除陀螺仪信号中的高频噪声,但尽量保留有用的低频信号(因为小车控制需要快速的角速度反馈)。设计

  • 采样频率f_s:IMU数据读取和控制循环频率为500Hz,T=0.002s
  • 截止频率f_c:需要分析。小车自身的机械振动噪声可能高达几十Hz,需要滤除。而控制环路带宽可能设计在20-30Hz。因此,将陀螺仪低通滤波的截止频率设为f_c = 30 Hz,可以抑制高频振动噪声,同时保留控制所需的有效带宽。
  • 计算系数:τ = 1/(2π*30) ≈ 0.005305 sα = T / (T+τ) = 0.002 / (0.002+0.005305) ≈ 0.002 / 0.007305 ≈ 0.2741-α ≈ 0.726实现:在500Hz的控制中断中,先读取原始陀螺仪数据gyro_raw,然后gyro_filtered = 0.726 * gyro_filtered_prev + 0.274 * gyro_raw,再用gyro_filtered进行角度积分和控制计算。效果:原始陀螺仪数据的毛刺被平滑,积分得到的角度曲线更干净,减少了因噪声积分导致的随机游走漂移,提升了控制稳定性。

一阶低通滤波及其离散化是信号处理中最基础、最实用的工具之一。它的魅力在于用最简单的数学形式,解决了工程中无处不在的噪声问题。理解其连续域的原理是根基,掌握后向欧拉离散化方法并将其转化为两三行代码是核心技能。在实际应用中,关键在于根据信号特性和系统需求,合理地选择截止频率与采样频率的比例,并注意数值实现的细节。希望这篇长文能帮你不仅记住公式y[n] = (1-α)y[n-1] + αx[n],更能透彻理解它背后的每一个为什么,从而在下次面对嘈杂的数据时,能够自信地应用这个强大的工具。

返回列表