跳转至

08 选型地图与工程配方

前面七章讲了各种算法的原理、参数和边界。这一章回答一个更实际的问题:手里有一段真实测量数据,我该怎样判断问题类型、选择算法、设置参数、验证效果?

第 03 章讲的是"组合滤波的顺序和思想",这一章讲的是"拿到具体问题后怎么选型和落参"。它不引入新算法,而是把前面所有算法组织成一套工程决策流程。

先别选算法,先看数据

拿到一个测量问题时,最常见的错误是直接跳到"用什么算法"。正确做法是先花几分钟看数据。数据会告诉你问题是什么,算法只是工具。

看数据时回答这几个问题:

噪声长什么样?

  • 随机小幅抖动:读数围绕某个值无规律波动,幅度相对稳定。
  • 偶发尖峰:大部分时间正常,偶尔跳出一个离谱的值,持续 1~3 个采样点。
  • 周期干扰:读数有规律地波动,频率通常和工频、PWM 或机械转速相关。
  • 慢漂移:读数在几分钟或几小时内缓慢偏移,没有明显噪声。
  • 混合型:既有尖峰又有随机抖动,或者既有周期干扰又有慢漂移。

真实信号什么样?

  • 基本不变:温度、电池电压这类慢变量。
  • 缓慢变化:液位、压力、缓慢移动的位置。
  • 会突变:按键、阀门开关、负载投入。
  • 快速连续变化:电机电流、振动、旋转编码器。

工程约束是什么?

  • 允许多大延迟?显示仪表可以接受几百毫秒,控制环可能只接受几毫秒。
  • 输出是连续值还是开关状态?报警只需要开/关,监控需要连续曲线。
  • MCU 有没有 FPU?没有的话浮点乘法开销大,除法更贵。
  • RAM 能放多少?窗口滤波器需要缓冲区,32 个 float 就是 128 字节。
  • 采样率是多少?能不能改?采样率太低会混叠,太高会增加计算负担。

先回答这些问题,再看选型表。 如果噪声类型都判断错了,选型表再准确也帮不上忙。

第一步:判断问题类型

把噪声现象和问题类型对应起来:

现象 大概率是 对应章节
读数小幅随机抖动,没有明显规律 随机噪声 02(平均、一阶滞后)
偶尔跳出一个离谱值,然后恢复正常 偶发尖峰 02(限幅、中值)
读数有规律地上下波动,频率固定 周期干扰 06(陷波、FIR)
读数缓慢偏移,没有明显噪声 慢漂移 04(趋势估计)、05(状态估计)
读数在阈值附近反复跳动 阈值抖动 02(迟滞、消抖)
读数变化很快,需要跟踪 快速信号 05(α-β、卡尔曼)
两个传感器各有优缺点 传感器融合 05(互补、Mahony)
有参考信号,想抵消干扰 自适应干扰抵消 07(LMS)
需要判断某个频率是否存在 频率检测 06(Goertzel)
需要检测"变化太快"的事件 突变检测 07(变化率门限)

这张表不是绝对规则。同一个现象可能有多种原因——比如读数抖动可能是随机噪声,也可能是采样率不够导致的混叠。判断错了原因,再好的算法也只是在掩盖问题。

第二步:确定工程约束

选算法之前,先确认约束。约束决定了哪些算法能用、哪些不能用。

约束 影响
延迟不能超过 X ms 排除长窗口平均、高阶 FIR、中心窗口 SG
RAM 不足 排除大窗口滑动平均、高阶 FIR、需要排序缓冲区的中值
没有 FPU 优先考虑定点实现友好的算法,避免三角函数在线计算
采样率固定且偏低 滤波器截止频率设计空间受限,可能需要更高阶。如果已经发生混叠,数字滤波无法补救,必须提高采样率或加强模拟抗混叠
输出必须是开关量 最终用迟滞 + 消抖确认,但送入判断前通常仍需要轻微平滑或限幅
输出必须是连续值 不能只用迟滞,需要平滑算法
采样率可以改 可以通过过采样 + 平均/低通后抽取降低噪声,再用简单滤波

约束不是选完算法再检查的,而是在选型之前就筛掉不合适的方案

第三步:选择算法组合

大多数工程问题不是单一算法能解决的。典型链路是:预处理 → 主滤波 → 后处理

  • 预处理:限幅去尖峰、中值去孤立异常。
  • 主滤波:平均、一阶滞后、卡尔曼、陷波——解决主要噪声问题。
  • 后处理:迟滞判断、消抖确认、限幅输出——约束输出行为。

第 03 章详细讲了组合顺序的原理。这里只强调一点:先去异常,再做平滑,最后约束输出。 反过来做会让平滑算法被尖峰拉偏,或者让迟滞判断收到已经被过度平滑的信号。

选型时不要从"最厉害的算法"开始试。先从最简单的组合开始:

  1. 能不能只用一阶滞后?参数能不能满足要求?
  2. 一阶滞后不够,加限幅或中值行不行?
  3. 还不够,考虑滑动平均、动态一阶滞后。
  4. 有系统模型,考虑 α-β 或卡尔曼。
  5. 有周期干扰,加陷波或 FIR。
  6. 有参考信号,考虑 LMS。

每升一级,参数变多、行为更难预测、调试更复杂。够用就停。

第四步:从指标反推参数

参数不应该"先随便写一个,再慢慢调"。工程做法是从指标反推。

从截止频率反推 alpha

已知采样率 \(f_s\) 和目标截止频率 \(f_c\),一阶滞后的平滑系数:

\[ \alpha = 1 - \exp\left(-2\pi \frac{f_c}{f_s}\right) \]

这个公式来自连续一阶系统的阶跃响应匹配(matched-z),在 \(f_c\) 远小于 \(f_s\) 时能给出接近 -3 dB 的截止效果。当 \(f_c / f_s\) 较大时,实际 -3 dB 点会略有偏差,但作为工程起点足够用。

例如 \(f_s = 100\;\text{Hz}\),希望截止频率 \(2\;\text{Hz}\)\(\alpha \approx 1 - \exp(-0.126) \approx 0.118\)

从允许延迟反推窗口长度

N 点滑动平均的群延迟为 \((N-1)/(2 f_s)\)。如果允许延迟不超过 50 ms,采样率 100 Hz:

\[ N \le 2 \times 0.05 \times 100 + 1 = 11 \]

\(N = 10\)\(N = 11\)

从噪声幅度反推限幅阈值

限幅阈值要同时考虑两个因素:稳态噪声幅度和真实最大变化速度。先在稳态下记录传感器输出的最大正常波动幅度 \(A\);再估算物理量的最大变化速率 \(v_{\max}\),单步最大合理变化为 \(v_{\max} \cdot dt\)。阈值 \(D\) 应取两者中较大的那个,再留 1.5~2 倍余量。如果不确定,宁可设大一点——设大了只是偶尔漏掉一个尖峰,设小了会卡住正常信号。

从稳态抖动反推迟滞宽度

回差带应大于稳态噪声的峰峰值。如果传感器在阈值附近抖动 ±20 mV,回差带至少设 50~60 mV。

从传感器噪声指标反推卡尔曼 R

有两种方法,推荐优先用第二种。

方法一:从噪声密度估算。 传感器数据手册给出噪声密度 \(e_n\) 时,可以用:

\[ R \approx e_n^2 \cdot B \]

其中 \(B\) 是有效噪声带宽,受模拟前端、抗混叠滤波和数字滤波影响,通常远小于 \(f_s/2\)。如果不确定 \(B\) 的值,直接用 \(f_s\) 会高估 \(R\),导致滤波器过度信任预测。

方法二(推荐):直接测量稳态方差。 在传感器输入固定(比如短接或接标准信号)的情况下,采集几百个样本,计算方差作为 \(R\) 的估计。这个方法不依赖噪声模型假设,结果更可靠。

从系统变化速度反推卡尔曼 Q

过程噪声 \(Q\) 反映"系统每步变化的不确定度"。在一维随机游走模型(状态只有位置,没有显式速度)中,初始可以从 \(R/100\)\(R/10\) 开始。如果滤波器对真实变化响应太慢,增大 Q;如果输出太抖,减小 Q。多维卡尔曼的 \(Q\) 是矩阵,单位和结构取决于状态定义,不能简单地和 \(R\) 做比例。

反推只是起点

反推出来的参数是工程起点,不是最终值。实际系统中传感器噪声、信号特性和干扰环境都和理论假设不同。反推之后必须用真实数据验证,根据验证结果微调。

常用工程配方

下面每个配方按统一格式写:适用场景、推荐链路、参数起点、验证方法、什么时候会失效。

稳定显示仪表

适用场景。 温度、电压、液位等慢变量的显示。用户需要看到稳定读数,但又不能明显滞后于真实值。

推荐链路。

ADC → 限幅 → 动态一阶滞后 → 显示

参数起点。

  • 限幅阈值 \(D\):取稳态噪声幅度的 2~3 倍。
  • 动态一阶滞后:\(\alpha_{\text{slow}}\) 从 0.05 开始,\(\alpha_{\text{fast}}\) 从 0.3 开始。
  • \(E_{\text{small}}\):取稳态噪声的典型幅度。
  • \(E_{\text{large}}\):取允许快速响应的最小误差,通常为 \(E_{\text{small}}\) 的 5~10 倍。

验证方法。

  • 稳态测试:传感器不动,观察输出抖动是否在可接受范围内。
  • 阶跃测试:快速改变输入,观察输出是否能在 1~2 秒内跟上。
  • 和原始数据对比:记录原始 ADC 值和滤波后值,确认稳态噪声被抑制、阶跃响应没有过度延迟。

什么时候会失效。 噪声幅度和真实变化幅度接近时,动态一阶滞后分不清"稳定"和"变化",alpha 会频繁跳动,输出反而比固定参数更抖。此时应先用限幅或中值降低尖峰,再用固定小 alpha 的一阶滞后。

电池电压保护

适用场景。 电池供电设备的欠压保护。需要在电压跌破阈值时可靠关断,但不能因为负载瞬态导致误关断。

推荐链路。

ADC → 滑动平均 → 迟滞判断 → 消抖确认 → 保护状态

参数起点。

  • 滑动平均窗口:按允许保护延迟选。采样率 100 Hz,允许 100 ms 延迟,窗口取 10。
  • 欠压阈值:按电池规格和负载特性选。锂电池保护通常 3.0~3.2 V。
  • 回差带:恢复阈值比欠压阈值高 100~200 mV,防止在阈值附近反复开关。
  • 消抖时间:覆盖负载瞬态。大电容充电可能持续几十毫秒,消抖可以设 100~500 ms。

验证方法。

  • 用可调电源模拟电压缓慢下降,确认在正确电压触发保护。
  • 在阈值附近反复升降电压,确认不会反复开关。
  • 投入大负载制造瞬态,确认不会误触发保护。
  • 电压恢复后确认能正常解除保护状态。

什么时候会失效。 负载电流变化很大时,电池内阻压降会导致电压剧烈波动,单看电压可能误判。如果负载状态可以读取(比如通过电流传感器),可以结合负载状态做判断:负载投入时不检查欠压,等电压稳定后再判断。

压力/液位传感器抗尖峰

适用场景。 工业现场的压力、液位传感器。信号上有偶发尖峰(接触不良、电磁干扰),同时有小幅随机抖动。

推荐链路。

ADC → 限幅或中值 → 一阶滞后 → 输出

参数起点。

  • 限幅阈值:取正常最大变化速率 × 采样周期 × 2。例如压力每秒最多变化 10 kPa,采样率 100 Hz,单步最大变化 0.1 kPa,阈值设 0.2 kPa。
  • 持续 2 个采样点可用 5 点中值;持续 3 个采样点至少考虑 7 点窗口,或者先用变化率门限检测异常段,再用保持旧值策略跳过。
  • 一阶滞后 alpha:从 0.1 开始,根据显示稳定性调整。

验证方法。

  • 在正常数据中人为插入尖峰,确认限幅或中值能去掉。
  • 确认正常快速变化时输出不会被限幅卡住。
  • 长时间运行,确认没有累积漂移。

什么时候会失效。 尖峰持续时间超过中值窗口的一半时,中值也会被污染。此时需要加大窗口,或者先用变化率门限检测异常段,再用保持旧值策略跳过。

称重或慢速测量

适用场景。 称重传感器、高精度电压测量。信号很干净但有小幅随机噪声,需要尽可能降低抖动,同时允许较大延迟。

推荐链路。

ADC → 长窗口滑动平均 → 输出

或者:

ADC → 过采样 + 抽取 → 一阶滞后 → 输出

参数起点。

  • 滑动平均窗口:按允许延迟选。称重显示可以接受 0.5~1 秒延迟,窗口可以取大。
  • 如果采样率可以提高,过采样 16 倍后每 16 点平均再抽取,标准差约降为 \(1/\sqrt{16}=1/4\)。注意:单纯每 16 点取 1 点没有降噪效果,必须先做平均或低通。
  • 一阶滞后 alpha:0.01~0.05,配合长窗口使用。

验证方法。

  • 静态测试:传感器放固定砝码,记录输出的最大最小值之差。
  • 阶跃测试:放上砝码后记录输出达到 95% 的时间,确认延迟在允许范围内。
  • 和高精度参考对比(如果有)。

什么时候会失效。 过采样假设噪声是白噪声。如果噪声有低频分量(比如 1/f 噪声或温漂),过采样不能降低这些成分。长窗口在信号突变时延迟很大——称重时物品放上后要等很久读数才稳定,可能需要配合动态 alpha 加快响应。

电机电流检测

适用场景。 电机控制中的电流采样。信号上有 PWM 纹波和开关噪声,需要提取基波分量或平均电流。

推荐链路。

ADC(同步采样)→ 限幅/异常点剔除 → 低通或陷波 → 输出

参数起点。

  • 采样时机:尽量在 PWM 周期的中点采样,避开开关边沿。
  • 陷波频率:设在 PWM 开关频率或其谐波。
  • 如果只需要平均电流,一阶低通截止频率设在目标带宽的 3~5 倍。
  • 限幅阈值:按电机最大电流变化速率设。

验证方法。

  • 对比不同采样时机的波形,确认同步采样有效。
  • 用示波器确认 ADC 输出和滤波后输出的纹波抑制比。
  • 在突加负载时测试响应速度。

什么时候会失效。 PWM 频率漂移时固定陷波会漏掉部分纹波。电流传感器带宽不足时,高频纹波本身就被传感器滤掉了,数字滤波只是锦上添花。

姿态角估计入门

适用场景。 机器人、云台、平衡车等需要估计倾角的项目。有陀螺仪和加速度计。

推荐链路。

陀螺仪积分角度 + 加速度计倾角 → 互补滤波

参数起点。

  • alpha:从 0.98 开始。近似时间常数 \(\tau \approx \alpha \cdot dt / (1-\alpha)\),精确关系为 \(\tau = -dt / \ln(\alpha)\)。采样率 100 Hz(dt=0.01 s)时,\(\tau \approx 0.49\;\text{s}\)
  • 如果需要更长的短期信任(更慢修正),增大 alpha。
  • 如果加速度计噪声大或运动加速度明显,增大 alpha(减少加速度计修正);如果陀螺漂移明显,减小 alpha(增加加速度计修正)。

验证方法。

  • 静态测试:角度是否稳定,不漂移。
  • 动态测试:缓慢转动后回到原位,角度是否回到原值。
  • 震动测试:在振动环境下角度是否不跳变。

什么时候会失效。 剧烈运动时加速度计不只反映重力,互补滤波会被运动加速度污染。此时应升级到 Mahony 或 Madgwick,加入加速度计可信度判断。

工频干扰抑制

适用场景。 传感器信号上叠着 50 Hz 或 60 Hz 工频干扰。

推荐链路。

ADC → 陷波(50/60 Hz)→ 后续滤波

或者:

ADC → 整周期平均(采样率和工频同步)→ 后续滤波

参数起点。

  • 陷波 Q:工频较稳定时从 20 开始,频率会漂移时降到 5~10。
  • 整周期平均:如果采样率能和工频同步,取工频周期的整数倍作为平均窗口。

验证方法。

  • 对比陷波前后数据的频谱,确认 50/60 Hz 分量被压低。
  • 确认目标信号频率没有被误伤。
  • 长时间运行,确认工频频率漂移时陷波仍然有效。

什么时候会失效。 工频频率漂移超出陷波带宽时会漏掉部分干扰。整周期平均要求采样率和工频严格同步,不同步时效果下降。如果干扰不是单一频率(比如有谐波),可能需要多个陷波或宽带低通。

单频检测

适用场景。 DTMF 检测、电力谐波监测、判断某个振动频率是否存在。

推荐链路。

ADC → Goertzel → 阈值判断 → 连续确认 → 输出状态

参数起点。

  • Goertzel 窗口长度 \(N\):让目标频率尽量落在 DFT bin 上,即 \(f_0 \approx k \cdot f_s / N\)
  • 阈值:先采集没有目标频率时的背景能量,再采集有目标频率时的能量,选两者之间有裕量的位置。
  • 连续确认:要求连续多帧能量都超阈值才确认。

验证方法。

  • 用已知频率的正弦信号测试,确认检测灵敏度。
  • 用不含目标频率的噪声测试,确认误报率。
  • 测试目标频率有小范围漂移时的检测能力。

什么时候会失效。 目标频率漂移导致能量分散到邻近 bin,检测灵敏度下降。输入幅度变化大时,固定阈值可能不适用,需要用能量占比作为判断指标。

判断算法是否用错

出现下面现象时,通常说明算法或参数不合适:

现象 可能原因 检查方向
输出很稳,但真实变化来了半天跟不上 alpha 太小或窗口太大 检查截止频率是否远低于信号带宽
稳态时输出跟着噪声一起抖 alpha 太大或没有预处理 先限幅或中值去尖峰,再减小 alpha
异常尖峰后,平均值很久才恢复 尖峰进入了平均窗口 先限幅或中值去尖峰,再送入平均
阈值附近报警器疯狂开关 回差带太小或没有消抖 加大回差带,加消抖确认
卡尔曼调了很多参数,效果和一阶滞后差不多 系统模型没有价值,或 Q/R 比例不对 先确认模型是否合理,再调 Q/R
采样率改了,滤波效果完全变了 参数和采样率耦合 alpha、窗口长度、Q,以及由带宽估算出来的噪声方差需要重新确认
陷波后目标信号也被压掉了 陷波频率和信号频率太近 确认信号频率和干扰频率的关系,考虑用更窄的陷波或换方案
滤波输出有周期性波动 可能有未处理的周期干扰 用频谱分析确认干扰频率,加陷波或 FIR

关键原则: 先确认问题类型,再选算法。先用简单算法,再升级复杂算法。参数从指标反推,再用数据微调。效果不好时先检查问题类型判断是否正确,再检查参数是否合理,最后才怀疑算法本身。

选型流程清单

拿到一个测量问题时,按这个顺序走一遍:

  1. 画原始曲线。 把 ADC 原始值随时间画出来,不要一上来就滤波。
  2. 标注问题。 在图上标出:尖峰在哪里、周期波动的频率是多少、有没有慢漂移、真实信号的变化速度大概多快。
  3. 写延迟上限。 这个应用能接受多大延迟?写下来,后面选窗口和 alpha 时对照。
  4. 写约束。 MCU 有没有 FPU、RAM 能放多少、输出是连续值还是开关量。
  5. 选链路。 按"预处理 → 主滤波 → 后处理"选算法组合,从最简单的开始试。
  6. 反推参数。 用截止频率、延迟、噪声指标反推,不要凭感觉写。
  7. 记录验证结果。 静态测试、阶跃测试、长时间测试的数据都记下来。参数改了之后重新测,对比前后效果。

这个流程不保证一次选对,但能保证每次调整都有依据。

小结:选型不是比算法高级

决策步骤 核心问题 常见错误
看数据 噪声长什么样?信号允许多大延迟? 不看数据就选算法
判断问题类型 是随机噪声、尖峰、周期干扰还是慢漂移? 把尖峰当随机噪声处理
确定约束 延迟、RAM、FPU、输出形式 选完算法才发现约束不满足
选算法组合 预处理 → 主滤波 → 后处理 只用一个算法硬扛
反推参数 从截止频率、延迟、噪声指标反推 凭感觉调参数
验证效果 静态、阶跃、长时间、边界测试 只看曲线"像不像"

选型的本质不是"哪个算法更高级",而是"哪个算法最适合这个问题、这个约束、这个验证条件"。简单算法可解释、可维护、可验证,在很多 MCU 项目里反而更可靠。