资讯动态

截止频率全链路解析:从-3dB定义到模拟数字滤波器验证

发布时间:2026/10/28 3:54:56 来源:尧图企业网站定制
信号处理这行干久了会发现一个挺有意思的现象很多人能画出漂亮的幅频响应曲线也能把滤波器系数算得清清楚楚可一旦被问你这个截止频率到底卡在哪个点上、为什么是这个数回答就开始含糊。截止频率看着是最基础的一个参数实际却是模拟电路、数字滤波器、采样率、阶数、相位响应几件事拧在一起的交汇点。我见过太多项目在这里栽跟头——电路焊出来了低频增益不对、代码跑起来了结果通带比预期窄一截、明明设了 100 Hz 实际测出来 70 多 Hz。这些问题追到根上往往不是算法写错了而是对截止频率这四个字的理解少了一层。这篇内容想聊的就是这一层。从最基础的 -3dB 定义讲起把模拟侧 RC 网络的公式推导、数字侧归一化频率和预畸变的换算关系、阶数与过渡带的权衡、以及最后怎么用实测数据验证自己设的截止频率是对的一条线串下来。适合刚接触滤波器设计、正在做传感器信号调理或者音频处理的读者也适合那些会用 scipy 但说不清参数含义的朋友。里面会给出可以直接跑的计算和代码也会把我自己踩过的几个坑摊开讲。1. 把截止频率这个词拆开它究竟落在哪条线上1.1 -3dB 这个数字不是随手定的先说清楚一件事理想低通滤波器的幅频响应是一条直角折线通带内增益恒为 1到了截止频率瞬间掉到 0。这种响应在数学上很干净物理上造不出来。任何用电阻电容电感搭出来的网络或者用有限阶差分方程实现的数字滤波器通带到阻带之间必然有一段斜坡式过渡。既然没有瞬间掉下去的那个点截止频率就必须人为定义在一个具体的幅度上。工程上最通用的定义是幅频响应降到通带增益的 0.707 倍也就是 -3.01 dB 的那个频率点。为什么是 0.707 而不是 0.5 或者 0.9因为 0.707 对应的是半功率点。功率正比于幅度平方0.707² ≈ 0.5信号通过这个频率点时功率正好被砍掉一半。这个定义在电学里有明确的物理意义也和一阶系统的极点位置天然吻合——一阶低通的传递函数是 H(s) ω_c/(sω_c)把 s 换成 jω令 ω ω_c模值恰好是 1/√2。换句话说-3dB 点就是一阶系统的极点频率在频域上的投影不是拍脑袋选的美学数字。不过这里有个特别容易混淆的地方不同滤波器类型、不同设计工具对截止频率的默认定义并不一致。巴特沃斯的 -3dB 点确实落在标称截止频率上因为它的幅频响应是 |H| 1/√(1(f/f_c)^(2n))不管阶数 n 是多少f f_c 时模值恒为 1/√2。切比雪夫 I 型的定义就不一样了它的标称截止频率指的是纹波带边缘也就是响应第一次跌到通带纹波下限的那个点这个点的衰减量等于纹波系数可能是 0.5 dB、1 dB 或者 3 dB取决于你设的纹波参数。椭圆滤波器更绕它的截止频率通常定义为通带边缘但阻带起点另有参数。1.2 三种常被混着用的截止说法我在帮别人看代码的时候发现有三类表述经常被混为一谈必须分开。第一类是幅频 -3dB 点就是上面说的半功率点最通用。第二类是阻带起始频率这是滤波器开始提供足够衰减的位置。它和 -3dB 点之间隔着一整段过渡带两者可能差得很远。一个 8 阶巴特沃斯低通-3dB 点在 100 Hz阻带起始点可能要到 200 Hz 才达到 40 dB 衰减。如果你把这两个当成一个东西设计出来的滤波器通带会比预期宽或者窄很多。第三类是数字滤波器设计工具里的归一化参数。这个最坑后面单独开一节讲因为它是实际项目里翻车率最高的地方。下面这张表把常见的几种滤波器在标称截止频率处的实际衰减列出来做设计选型的时候可以对着看滤波器类型标称截止频率处的衰减说明巴特沃斯任意阶-3.01 dB最平坦通带定义最直观切比雪夫 I 型等于设定的通带纹波纹波 1 dB 时该点衰减 1 dB切比雪夫 II 型通常按阻带边缘定义通带平坦阻带有纹波贝塞尔-3.01 dB通带幅度略逊群时延最平坦一阶 RC 无源-3.01 dB但后级负载会拉偏这个值FIR 窗函数法firwin约 -6 dB理想矩形截断半幅点最后一行需要特别强调。用窗函数法设计 FIR 低通时如果直接把 cutoff 设成想要的 -3dB 频率实测会发现通带边缘比预期低不少因为窗函数法逼近的是理想矩形它的半幅点-6 dB才落在 cutoff 上。想得到 -3dB 点得把 cutoff 往下调一点点或者改用等波纹设计remez并直接控制通带边缘。1.3 相位和群时延被忽略的另一半大部分人调截止频率只看幅频曲线这是不够的。截止频率附近恰恰是相位变化最剧烈的地方群时延在这里会出现明显起伏。对于音频、控制环路、生理信号这类对波形保真度敏感的场景截止频率设得太贴近有用信号即使幅频看起来还过得去波形也会被相位失真搞得面目全非。举一个具体的例子。某项目做电机电流采样PWM 频率 20 kHz采样率 40 kHz为了压住开关噪声在 ADC 前面加了一级二阶低通截止频率定在 2 kHz。幅频上看2 kHz 以内平坦20 kHz 处衰减约 40 dB看起来完美。但实际跑起来电流环震荡查了半天发现是 2 kHz 处的群时延已经接近 100 μs而电流环的带宽要求是 1.5 kHz。后来把截止频率抬到 5 kHz噪声靠数字侧再做一级陷波解决问题才消失。这个教训是选截止频率不光要看信号在不在通带内还要看这个频率上的相位延迟环路吃不吃得消。提示评估截止频率是否合适至少要同时看幅频响应、相频响应和群时延三条曲线。只看一条的决策后期返工概率很高。2. 模拟侧从一阶 RC 到高阶网络数值是怎么算出来的2.1 一阶 RC 的 f_c 1/(2πRC) 从哪来这个公式几乎所有教材都有但推导过程值得复述一遍因为它解释了为什么是 2π这个很多人背下来却说不清的东西。一阶 RC 低通的电路很简单输入经过电阻 R节点对地接电容 C输出取自电容两端。把电容看成阻抗 1/(jωC)整个网络就是一个分压器传递函数写成H(jω) (1/(jωC)) / (R 1/(jωC)) 1 / (1 jωRC)模值是 |H| 1 / √(1 (ωRC)²)。要让这个值等于 1/√2就得让 ωRC 1也就是 ω 1/(RC)。注意这里的 ω 是角频率单位是 rad/s。换成我们平时说的频率 f单位 Hz关系是 ω 2πf代入就得到f_c 1 / (2πRC)那个 2π 就是这么来的它来自角频率和普通频率的换算不是什么神秘的常数。实际算一个R 1 kΩC 100 nF。f_c 1 / (2 × 3.14159 × 1000 × 100×10⁻⁹) 1 / (6.2832 × 10⁻⁴) ≈ 1591.5 Hz如果反过来想要 1 kHz 的截止频率用 1 kΩ 电阻需要 C 1/(2π × 1000 × 1000) ≈ 159 nF取标准值 150 nF 得到约 1061 Hz取 220 nF 得到约 723 Hz。这就是为什么设计的时候经常要在标准值和目标频率之间做取舍。高通的情况对称把 R 和 C 位置对调传递函数变成 H jωRC/(1jωRC)模值同样是 1/√(1(1/ωRC)²)令 ωRC 1 得到同样的 f_c 1/(2πRC)。所以同一个 RC 组合低通和高通的截止频率数值是一样的只是斜率方向不同。2.2 二阶之后截止频率不再等于某个元件值一阶的公式漂亮但它有个硬伤过渡带太缓。一阶低通的阻带衰减速率是 -20 dB/十倍频程也就是说从截止频率往上走十倍才衰减 20 dB。想要 40 dB 的衰减得往上走一百倍频率。这个速率在很多场景下完全不够用。于是就有了二阶、四阶、八阶。问题是一旦阶数上去截止频率和元件值的关系就不再是一对一的简单公式了。以最经典的二阶压控电压源Sallen-Key低通为例它的传递函数是H(s) K / (s²·R1·R2·C1·C2 s·(R1·C2 R2·C2 R1·C2·(1-K)) 1)自然频率 ω_n 1/√(R1·R2·C1·C2)品质因数 Q 则由电阻比值决定。而 -3dB 截止频率 f_c 和自然频率 f_n 的关系是f_c f_n × √(1 - 1/(2Q²) √((1 - 1/(2Q²))² 1))这个式子看着复杂实际用起来可以记几个关键点。当 Q 0.7071巴特沃斯响应时f_c 恰好等于 f_n这也是巴特沃斯最省心的原因。当 Q 大于 0.7071f_c 略大于 f_n通带会出现抬升峰值当 Q 小于 0.7071f_c 小于 f_n通带会提前下滑。这也是为什么很多人照着网上的电路图焊了一个二阶低通测出来的截止频率和计算值对不上。因为网上那些图可能用了 Q 1 甚至更高的参数来换取更陡的过渡带而你没注意到这个差别。2.3 元件容差、寄生参数与实测偏差理论算完只是开始真正焊到板子上偏差来源有一堆。电容容差是最主要的一项。普通瓷片电容常见 X7R、X5R 材质标称容差 ±10%实际还会随直流偏压和温度漂移。给它加个 5 V 直流偏压容量掉 20% 都不稀奇。我做过一个测试同一批 100 nF 的 0805 瓷片电容在 0 V 偏压下实测 96~104 nF加上 10 V 偏压后掉到 78~85 nF。对应到截止频率上理论 1591 Hz 的电路可能实际跑到 1900 Hz 以上。要做得准要么换 C0G/NP0 材质容差 ±5%几乎没有电压系数但容量做不大要么换薄膜电容。电阻的容差通常好一些1% 精度很便宜但要注意阻值大了以后寄生电容开始起作用。一个 1 MΩ 的电阻几 pF 的寄生电容在几百 kHz 就开始影响响应了。运放本身的带宽也是限制。用一颗增益带宽积只有 1 MHz 的运放做 100 kHz 的低通运放自身的滚降会叠加在滤波器响应上实测截止频率会比计算值低。经验上运放的增益带宽积至少要是截止频率的 10 倍以上20 倍更保险。还有一个特别隐蔽的坑测试方法本身会改变结果。用万用表测交流幅度表的内阻和输入电容会并到电路里用示波器探头10× 探头是 10 MΩ 并联约 10 pF1× 探头是 1 MΩ 并联约 100 pF。测一个 100 kΩ、100 pF 的 RC 网络f_c ≈ 15.9 kHz挂上 1× 探头等于在电容上又并了 100 pF截止频率直接掉一半。这时候你测出来的实测值其实是探头造成的不是电路的问题。提示测量高阻节点的频率响应一律用 10× 探头并且要先把探头本身的电容算进去做修正。低阻节点几百欧以下可以放宽。3. 数字侧归一化截止频率是最容易翻车的地方3.1 归一化到底是相对谁归一化模拟电路里说截止频率单位是 Hz没有歧义。数字滤波器不一样因为采样率的存在所有频率都得先映射到一个无量纲的区间里。数字频率的定义是 ω 2πf/f_s单位是 rad/sample取值范围 0 到 π。它对应的物理频率范围是 0 到 f_s/2也就是 0 到奈奎斯特频率。为什么上限是 f_s/2 而不是 f_s因为采样之后高于 f_s/2 的频率会和低于 f_s/2 的频率混叠在一起无法区分所以 0 到 f_s/2 是唯一有意义的区间。很多设计工具包括 scipy 的 signal 模块支持两种传参方式给 fs 参数截止频率直接填 Hz工具内部自己换算。不给 fs 参数截止频率填归一化值范围 0 到 1这里的 1 对应的是奈奎斯特频率 f_s/2不是采样率 f_s。第二种方式是最容易出错的。我见过不少人以为归一化的 1 对应采样率结果设了个 0.1实际期望的是 0.1 × f_s真实效果却是 0.1 × f_s/2 0.05 × f_s截止频率只有预期的一半。举个具体数字采样率 1000 Hz想要 100 Hz 的低通。正确写法是 Wn 100/(1000/2) 0.2。如果写成 100/1000 0.1那实际设计的截止频率就是 50 Hz通带窄了一半。这个错误在代码里不报错、不告警只是默默地让结果不对特别难查。3.2 双线性变换的频率预畸变数字滤波器通常的设计流程是先设计一个模拟原型滤波器在 s 域再用某种映射把它搬到 z 域。最常用的映射是双线性变换公式是s (2/T) × (1 - z⁻¹) / (1 z⁻¹)这个映射有个副作用它把模拟域的整条虚轴0 到 ∞压缩到了 z 域单位圆的上半圈0 到 π而且不是线性压缩是畸变的。具体来说模拟频率 Ω 和数字频率 ω 的关系是Ω (2/T) × tan(ω/2)在低频段tan(ω/2) ≈ ω/2所以 Ω ≈ ω/T 2πf基本是线性的。但频率越高tan 的弯曲越明显。到 ω π/2 时即 f f_s/4tan(π/4) 1而线性近似给出的值是 π/4 ≈ 0.785误差已经 27% 了。这意味着如果你直接按 s jω 把模拟原型的截止频率设成 2π×f_c再套双线性变换得到的数字滤波器在 f_c 处的响应并不是 -3dB而是偏移了。解决办法叫频率预畸变prewarping在设计模拟原型之前先把目标数字频率按 ω 2×arctan(ΩT/2) 的逆关系换算成一个虚拟的模拟频率这样经过双线性变换的畸变之后刚好落回想要的位置。工程上常用的等效写法是f_prewarped (f_s/π) × tan(π × f_c / f_s)好消息是scipy 的iirfilter、butter、cheby1这些函数只要传了fs参数或者直接用数字域的 Wn内部已经自动做了预畸变用户不需要自己算。坏消息是如果你自己手搓双线性变换或者从别处抄来一段没做预畸变的代码这个偏差就得自己扛。0.1 × f_s 这种偏低的截止频率下偏差可能只有 1%~2%但在 0.4 × f_s 这种偏高位置偏差能到 20% 以上。3.3 一个能跑通全流程的实例下面这段代码把设计、验证、画图整条链路走一遍用的是 4 阶巴特沃斯低通采样率 1000 Hz目标截止频率 150 Hz。import numpy as np from scipy import signal import matplotlib.pyplot as plt fs 1000.0 # 采样率 Hz fc 150.0 # 目标截止频率 Hz order 4 # 方式一传 fsWn 用 Hz b, a signal.butter(order, fc, btypelow, fsfs) # 方式二不传 fsWn 归一化到奈奎斯特频率 # wn_norm fc / (fs / 2) # 0.3 # b, a signal.butter(order, wn_norm, btypelow) # 计算频率响应 w, h signal.freqz(b, a, worN8192, fsfs) mag_db 20 * np.log10(np.abs(h)) # 找 -3dB 点 idx np.argmin(np.abs(mag_db 3.0103)) print(f设计截止频率: {fc} Hz) print(f实测 -3dB 点: {w[idx]:.2f} Hz) # 检查通带内是否有异常抬升 print(f100 Hz 处增益: {mag_db[np.argmin(np.abs(w-100))]:.3f} dB) print(f300 Hz 处增益: {mag_db[np.argmin(np.abs(w-300))]:.3f} dB)跑出来的结果实测 -3dB 点应该在 150 Hz 附近误差在 0.5 Hz 以内。这里有个细节值得注意freqz的worN参数设成 8192是为了让频率分辨率足够细否则用默认的 512 点在 150 Hz 附近的采样点可能正好错过真正的 -3dB 位置导致读数有 2~3 Hz 的偏差。这种测量误差经常被误当成设计误差浪费很多时间去调参数。再补一个对比如果不做预畸变会怎样。取同样的 fs 和 fc但采样率改成 2000 Hz目标截止频率抬到 800 Hz即 0.4 × f_s接近奈奎斯特这时候预畸变的影响就很明显了。用 scipy 的signal.bilinear手动做一次不做预畸变的变换会看到实测 -3dB 点跑到 900 Hz 以上偏差超过 12%。4. 阶数、过渡带与截止频率之间的三角关系4.1 过渡带宽度反过来决定阶数很多人设计滤波器的顺序是先定截止频率再随便选个阶数跑一下看效果。这个顺序其实是反的正确的逻辑是截止频率和阻带起始频率一起决定了过渡带宽度而过渡带宽度直接决定了需要多少阶。巴特沃斯的阶数估算公式是n ≥ log₁₀[(10^(A_s/10) - 1) / (10^(A_p/10) - 1)] / [2 × log₁₀(ω_s/ω_p)]其中 A_p 是通带允许的最大衰减dBA_s 是阻带需要达到的最小衰减dBω_p 是通带边缘ω_s 是阻带边缘。算一个具体的要求通带 100 Hz 内衰减不超过 1 dB200 Hz 以上衰减至少 40 dB。代入分子是 log₁₀[(10⁴ - 1)/(10^0.1 - 1)] log₁₀[9999/0.2589] log₁₀(38622) ≈ 4.587。分母是 2 × log₁₀(2) 0.602。n ≥ 7.62向上取整得 8 阶。如果把阻带要求放宽到 30 dB分子变成 log₁₀[(1000-1)/0.2589] log₁₀(3859) ≈ 3.586n ≥ 5.966 阶就够。如果把通带边缘从 100 Hz 拉到 150 Hz过渡带从 100 Hz 缩到 50 Hz分母变成 2 × log₁₀(200/150) 2 × 0.1249 0.2499n ≥ 18.4得 19 阶。这组数字说明一个很硬的道理过渡带越窄阶数需求爆炸式增长。从 100 Hz 过渡带缩到 50 Hz阶数从 8 涨到 19翻了一倍多。而在实际工程里阶数每增加一阶计算量、系数量化误差、定点实现的溢出风险都在增加。所以设计时的第一反应不该是我要多陡的滤波器而是我的过渡带到底能容忍多宽。4.2 截止频率贴着奈奎斯特频率会发生什么数字滤波器有个天然禁区截止频率不能超过 f_s/2而且越靠近它各种问题越集中。第一是系数精度问题。截止频率靠近奈奎斯特时滤波器的极点会挤到单位圆靠近 z -1 的位置系数的动态范围变得极大。用双精度浮点还算能撑住一旦转成 16 位定点系数量化误差会让实际响应严重偏离设计值甚至可能让极点跑到单位圆外滤波器直接发散。第二是预畸变放大效应。前面说过双线性变换在接近奈奎斯特的位置畸变最严重。虽然 scipy 会自动预畸变但如果截止频率设到 0.45 × f_s预畸变后的虚拟模拟频率已经跑到无穷远附近了设计出来的滤波器形状会变得很奇怪。第三是数值稳定性。高阶 IIR 滤波器通常用二阶节级联SOS形式实现而不是直接形式的 b/a 系数就是为了缓解这个问题。用signal.butter拿到 b、a 之后正常的做法是sos signal.butter(order, fc, btypelow, fsfs, outputsos) y signal.sosfilt(sos, x) # 单向滤波 y0 signal.sosfiltfilt(sos, x) # 零相位滤波outputsos这个参数只要阶数超过 4就该加上。用直接形式的 a 系数做 8 阶滤波在高频端出现数值噪声几乎是必然的。经验上截止频率建议控制在 0.4 × f_s 以内极端情况不超过 0.45 × f_s。真的需要更靠近奈奎斯特的截止频率说明采样率选低了应该先考虑提高采样率而不是硬压滤波器。4.3 抗混叠滤波器的截止频率与采样率配比抗混叠是截止频率最经典的应用场景也是配比关系最讲究的地方。理论上只要采样率大于信号最高频率的两倍就能无失真重建奈奎斯特采样定理。但实际上没有任何低通滤波器能在 f_s/2 处突然切断所以高于 f_s/2 的成分必然会有一部分漏进来混叠到低频。这就要求抗混叠滤波器的阻带起始频率要低于 f_s/2留出的余量取决于滤波器的过渡带宽度。一个常用的配置是信号最高频率 f_max采样率取 f_s 2.5 × f_max 到 4 × f_max抗混叠滤波器的 -3dB 点设在 f_max 略高处阻带起始点设在 f_s/2。举个数字信号带宽 1 kHz。采样率取 2.5 kHz奈奎斯特频率 1250 Hz过渡带只有 250 Hz从 1000 Hz 到 1250 Hz 要衰减 60 dB 以上需要非常高的阶数巴特沃斯约 24 阶不现实。采样率取 5 kHz奈奎斯特 2500 Hz过渡带 1500 Hz从 1000 Hz 到 2500 Hz 衰减 60 dB巴特沃斯约 6 阶可行。采样率取 10 kHz过渡带 4000 Hz3 阶就够了。这就是为什么实际系统里采样率经常远高于理论最小值。多出来的倍数不是浪费是给抗混叠滤波器留的过渡带空间。还有一点容易忽略ADC 前面通常有两级滤波一级是模拟 RC 或无源 LC负责粗滤把最强的干扰先压下去一级是有源或数字滤波负责精滤。模拟那级的截止频率不能设得太高否则强干扰信号可能在进入 ADC 之前就把运放推饱和了后面的数字滤波再精准也救不回来。这种情况在工业现场特别常见几十伏的工频干扰串进来运放早就削顶了。5. 怎么验证你设的截止频率是真的5.1 扫频法最直接也最可靠设计完、焊完、代码写完最后一步永远是实测。扫频是最基础的方法给系统输入一系列不同频率的正弦信号记录每个频率下的输出幅度画出来找 -3dB 点。手工做的话从 0.1 × f_c 扫到 10 × f_c每个十倍频程取 20 个点以上也就是对数均匀分布能画出足够平滑的曲线。测量的时候有两个细节要注意一是每个频点要等系统响应稳定后再读数。滤波器有建立时间一阶系统的时间常数是 RC理论上要等 5 个时间常数才能到 99%。对于 f_c 1 kHz 的一阶 RC时间常数约 159 μs等 1 ms 足够。但对于 Q 值高的高阶滤波器建立时间会明显拉长特别是接近截止频率附近振铃可能持续很久。二是输入幅度要控制。在截止频率附近滤波器内部节点的电压可能远高于输入或输出尤其是高 Q 的 Sallen-Key 结构中间节点的电压可能达到输入的 Q 倍。输入给 1 V中间节点可能摆动到 5 V运放如果供电只有 5 V直接削顶测出来的曲线就是错的。用代码做扫频验证可以这样import numpy as np from scipy import signal fs 48000.0 fc 2000.0 sos signal.butter(4, fc, btypelow, fsfs, outputsos) freqs np.logspace(1, 4.5, 200) # 10 Hz 到约 31.6 kHz results [] for f in freqs: t np.arange(0, 0.2, 1/fs) x np.sin(2 * np.pi * f * t) y signal.sosfilt(sos, x) # 取后 20% 的数据避开启动瞬态 seg y[int(0.8*len(y)):] amp np.sqrt(2) * np.std(seg) results.append(amp) results np.array(results) mag_db 20 * np.log10(results / results[freqs fc*0.1].mean()) idx np.argmin(np.abs(mag_db 3.0103)) print(f扫频实测 -3dB: {freqs[idx]:.1f} Hz)这段代码里用后 20% 的数据而不是全部是为了避开滤波器的启动瞬态用标准差乘 √2 而不是直接取最大值是为了抗噪在有干扰的情况下更稳。5.2 白噪声加功率谱一次测全频段扫频法准但慢。如果只是想快速看个大概白噪声激励加 FFT 分析效率高得多。方法是输入一段白噪声幅度要控制别让系统进非线性区采集输出算输入输出的互功率谱除以输入的自功率谱得到频率响应。这在scipy.signal里有现成的函数signal.csd和signal.welch。f, Pxy signal.csd(x_in, y_out, fsfs, nperseg4096) f, Pxx signal.welch(x_in, fsfs, nperseg4096) H Pxy / Pxx mag_db 20 * np.log10(np.abs(H))用互谱而不是直接算输出的功率谱好处是能排除输入信号本身不平坦带来的影响也能抑制与输入不相关的噪声。这个方法有个陷阱nperseg决定了频率分辨率分辨率是 fs/nperseg。fs 48000nperseg 4096分辨率约 11.7 Hz。要准确定位 2 kHz 附近的 -3dB 点11.7 Hz 的分辨率还行但如果截止频率只有 50 Hz这个分辨率就太粗了得把 nperseg 加大到 65536 甚至更多或者降低采样率。频率分辨率和平均次数是一对矛盾nperseg 大了能平均的段数就少了谱估计的方差变大。实操中需要根据目标截止频率和可用数据长度折中。5.3 阶跃响应里藏着的额外信息幅频曲线只反映幅度阶跃响应能同时暴露幅度和相位的问题有些毛病在幅频上根本看不出来。给系统一个阶跃输入看输出的上升时间、过冲量和振铃。一阶系统没有过冲10%~90% 上升时间约等于 2.2 × RC也就是 2.2/(2πf_c) ≈ 0.35/f_c。反推过来如果测出上升时间是 350 μs那 f_c 大约是 1 kHz。二阶及以上的系统会有过冲和振铃过冲量直接对应 Q 值Q 0.707 时过冲约 4.3%Q 1 时约 16%Q 2 时约 44%。振铃频率约等于自然频率 f_n。这几个数字很好用——如果你设计的巴特沃斯滤波器Q 0.707实测过冲到了 15%说明实际 Q 值偏高很可能元件容差把阻尼比拉低了顺带截止频率也会偏低。零相位滤波sosfiltfilt在这种情况下要特别小心。它把正向和反向各滤一遍幅频响应是单向滤波的平方。这意味着原来 -3dB 的点模值 0.707平方之后变成 0.5也就是 -6dB。真正的 -3dB 点会往低频方向移。对 n 阶巴特沃斯滤波两次之后的 -3dB 点约在原截止频率的 0.4142^(1/(2n)) 倍阶数filtfilt 后 -3dB 点与原截止频率之比20.81640.89660.93080.9474 阶巴特沃斯设 100 Hz做完 filtfilt 实际 -3dB 点只有约 90 Hz。做离线数据处理不需要实时性时如果对截止频率有精确要求这个偏移必须补偿处理方法是在设计时把 cutoff 除以对应的系数。6. 不同场景下截止频率的取值逻辑6.1 传感器信号调理卡在信号带宽和噪声之间传感器前端的低通截止频率本质上是放多少有用信号和放多少噪声进来之间的取舍。以应变片测量为例结构应变的变化频率通常不超过几十 Hz除非测振动或冲击但现场有 50 Hz 工频干扰、变频器的高频噪声、静电放电的瞬态。这种场景下截止频率设 10~30 Hz 很合适能把 50 Hz 压下去 20 dB 以上同时保留全部有用的静态和准静态信号。但如果测的是振动带宽要求可能到几千 Hz这时候 50 Hz 工频就落在通带里了低通滤波根本解决不了得换用陷波器或者提高共模抑制。这是选截止频率时最容易搞混的地方低通不是万能的它只能压掉截止频率以上的干扰落在通带内的干扰得用别的办法。还有一个容易被忽略的参数传感器的输出阻抗。很多传感器比如压电式、热电偶输出阻抗高直接接 RC 低通电阻的热噪声会被放大而且后级运放的输入偏置电流会在电阻上产生失调。这种场合要么用有源滤波运放做缓冲要么把 RC 的 R 值压小、C 值加大但 C 加大了又会影响响应速度。6.2 音频分频交叉频率不是随便选的音箱分频器是截止频率应用最直观的地方。两分频音箱低音单元和高音单元各有一个通带交叉点就是两个滤波器的截止频率重合处。常见的交叉频率是 2~3 kHz这个数字不是随口定的它取决于两个单元各自的频率响应特性。低音单元在 2 kHz 以上开始出现分割振动振膜不再整体运动而是局部弯曲失真急剧上升高音单元在 1.5 kHz 以下受限于自身谐振频率承受不了大功率。交叉点必须落在两个单元都能正常工作的重叠区间里。分频器的阶数直接决定了交叉点附近的相位关系和叠加效果。一阶分频-6 dB/oct两个单元在交叉点处的相位差是 90°叠加后会出现 3 dB 的凸起或者抵消取决于极性接法。二阶分频-12 dB/oct相位差 180°需要把高音反相接才能平坦。四阶分频-24 dB/oct相位差 360°同相接。这些细节决定了分频点附近的频响是否平坦也是 DIY 音箱最常翻车的地方——很多人买了成品分频器直接接上去忘了看相位结果交叉点附近凹了一大块。6.3 生理信号极低频截止的讲究心电、脑电这类生理信号频率范围很低但截止频率选起来反而更讲究。心电信号的有效带宽通常说 0.05~150 Hz但诊断用途和监护用途的要求不一样。监护场景看心率、看节律用 0.5~40 Hz 就够这样能有效去掉基线漂移和肌电干扰诊断场景看 ST 段形态需要 0.05 Hz 的低频截止因为 ST 段的缓慢变化包含了重要信息切高了会失真。0.05 Hz 的截止频率意味着什么意味着高通滤波器的时间常数是 1/(2π × 0.05) ≈ 3.18 秒。这个时间常数下滤波器的建立时间要十几秒而且对元件的容差极其敏感。更麻烦的是这么低的截止频率用模拟电路实现电容值要大到几百微法只能用钽电容或者电解电容漏电流和温漂都会带来问题。所以现代设备基本都是数字化之后做软件滤波但软件滤波同样要面对定点运算下极低频系数精度不够的问题通常要用二阶节级联加高精度系数。脑电的情况更极端感兴趣的频段比如 α 波 8~13 Hz本身就很窄滤波器的过渡带要做得非常陡但又不能引入相位失真否则会影响波形分析。这种场景下前向后向零相位滤波几乎是标配代价就是要接受前面说的截止频率偏移或者用等波纹 FIR 并在设计时补偿。7. 几个我自己踩过的坑7.1 把 rad/s 和 Hz 混了这个是新手坑但栽进去的人真不少包括工作几年的老手在赶工的时候。signal.butter传 Wn 的时候如果给了 fs单位是 Hz没给 fsWn 是归一化到奈奎斯特的比值。这两种都对。但如果你自己推导模拟原型用 s 域公式算很容易把 ω 2πf 里的 2π 漏掉或者多用一次。我遇到过一次某项目要从模拟原型迁移到数字代码里设了Wn 2 * np.pi * fc / fs看着像模像样实际上多乘了个 2π导致截止频率只有预期的 1/6.28。查了两天才发现因为幅频曲线形状是对的只是整体往低频平移了第一眼看不出来。防这种错的办法很简单设计完之后一定跑一次freqz把 -3dB 点算出来打印跟目标值对一下。多写三行代码省两天调试。7.2 滤波器设计对了但数据预处理把它毁了还有个更隐蔽的滤波器本身没问题但输入数据的预处理引入了偏差。做过一个振动分析的项目传感器信号里有个很大的直流偏置预处理第一步是去均值。去均值用的是整段数据的平均值看起来没问题。但后面接了 0.5 Hz 的高通高通启动时的瞬态响应在头几秒内非常剧烈振铃幅度比信号本身还大。后来改成先做高通、再单独处理前几秒的瞬态用反射填充或者直接丢弃问题才解决。类似的还有归一化。有人习惯先把数据归一化到 ±1再送进滤波器。如果归一化用的是整段数据的最大值而这段数据里恰好有一个尖峰那么整个信号的幅度都被压得很小滤波后信噪比下降。正确的做法是先滤波、后归一化或者用稳健的统计量比如 99 百分位做归一化。7.3 定点实现里系数量化把截止频率拉偏了浮点上跑得好好的滤波器转到定点 MCU 上出问题这个太常见了。根本原因是 IIR 滤波器的极点位置对系数极其敏感尤其当截止频率相对采样率很低的时候。比如 fs 10 kHzfc 10 Hz归一化频率只有 0.002极点紧贴 z 1 附近。用 Q15 定点表示系数量化步长是 1/32768 ≈ 3e-5这个精度相对于 0.002 的归一化频率还算够但如果阶数高误差会累积。实操中的应对办法有几个一是用二阶节级联SOS每个二阶节单独量化误差不会跨节累积。这是最有效的办法几乎能解决 90% 的定点精度问题。二是提高中间运算的位宽。Q15 系数配 Q31 累加器是很多 MCU DSP 指令的标准配置。三是把采样率降下来。如果信号带宽本来就只有几十 Hz用 10 kHz 采样是浪费改成 1 kHz归一化截止频率从 0.002 变成 0.02系数精度问题一下就缓解了。降采样通常比提高位宽更划算。还有一个小技巧如果滤波器系数是固定的不需要在线调参可以直接把系数算好烧进固件用浮点系数配浮点运算只要 MCU 有 FPU性能完全够。很多 Cortex-M4 以上的芯片都有单精度 FPU跑几个二阶节毫无压力没必要硬上定点。7.4 忽略群时延导致控制系统震荡前面提过一次这里再展开说说因为这类问题在嵌入式控制里特别普遍。控制环路的稳定裕度和相位延迟直接相关。滤波器的群时延在截止频率附近达到峰值如果你的控制带宽接近滤波器的截止频率那这部分额外的相位滞后可能直接把相位裕度吃光。做一个粗略的估算一阶低通在频率 f 处的相位滞后是 arctan(f/f_c)。当 f f_c 时滞后 45°f 0.5f_c 时滞后 26.6°f 0.2f_c 时滞后 11.3°。如果控制环路的相位裕度只有 30°而你在反馈路径上串了个截止频率等于环路带宽的低通光这一项就吃掉 45°环路必炸。工程上的经验值是反馈路径上的滤波器截止频率至少要是控制带宽的 5 倍10 倍更保险。这意味着如果要做 1 kHz 带宽的电流环反馈滤波的截止频率得在 5~10 kHz 以上。这时候就不得不权衡噪声抑制效果——截止频率抬高了高频噪声压不住。解决办法通常是把滤波拆成两级模拟侧一级截止频率较高的 RC比如 20 kHz数字侧一级截止频率较低但阶数高的滤波比如 5 kHz 的 4 阶两级串联得到陡峭的滚降同时把群时延控制在可接受范围。7.5 用错了滤波器类型截止频率对但形状不对最后说个概念性的。有次看到一段代码要做带通滤波用了signal.butter(4, [low, high], btypeband)参数看着没问题。但跑出来的结果通带中间凹下去了。原因是butter的 band 类型传两个截止频率时得到的是一个 8 阶滤波器4 阶原型映射到带通变成 8 阶而这两个频率分别是下边带和上边带的 -3dB 点。如果 low 和 high 靠得很近比如 100 Hz 和 120 Hz过渡带极窄对阶数的要求暴涨4 阶原型根本不够通带中间就凹了。正确的做法是先用signal.buttord算出所需阶数N, Wn signal.buttord(wp[100, 120], ws[80, 150], gpass1, gstop40, fs1000) print(N, Wn) # 输出所需阶数和实际截止频率 sos signal.butter(N, Wn, btypeband, fs1000, outputsos)buttord会根据通带、阻带指标反推最小阶数避免手拍阶数拍小了。这个函数在窄带滤波场景下几乎是必用的因为人的直觉很难判断100 到 120 Hz 的带通要几阶而公式能给出准确答案。另外带通滤波器的中心频率和截止频率是两个不同的量。中心频率是几何平均 √(f_low × f_high)不是算术平均 (f_low f_high)/2。100 和 120 的几何平均是 109.5算术平均是 110差得不多但如果频带更宽比如 100 和 1000几何平均是 316算术平均是 550差出一大截。用错这个会直接影响后续对滤波器特性的判断。上面这些内容里如果只能记住一句话我希望是截止频率从来不是一个孤立的数字它是定义、阶数、采样率、实现方式共同决定的结果。算出那个数字只是开始验证它落在预期位置、确认它在整个系统里没有带来副作用才算真正把这件事做完。我自己现在的习惯是任何滤波器上线之前先跑一遍freqz打印 -3dB 点再用一段合成信号做扫频复核两关都过了才敢往真实数据上用。这个流程看着笨但省下来的返工时间远比它多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑