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 章详细讲了组合顺序的原理。这里只强调一点:先去异常,再做平滑,最后约束输出。 反过来做会让平滑算法被尖峰拉偏,或者让迟滞判断收到已经被过度平滑的信号。
选型时不要从"最厉害的算法"开始试。先从最简单的组合开始:
- 能不能只用一阶滞后?参数能不能满足要求?
- 一阶滞后不够,加限幅或中值行不行?
- 还不够,考虑滑动平均、动态一阶滞后。
- 有系统模型,考虑 α-β 或卡尔曼。
- 有周期干扰,加陷波或 FIR。
- 有参考信号,考虑 LMS。
每升一级,参数变多、行为更难预测、调试更复杂。够用就停。
第四步:从指标反推参数
参数不应该"先随便写一个,再慢慢调"。工程做法是从指标反推。
从截止频率反推 alpha
已知采样率 \(f_s\) 和目标截止频率 \(f_c\),一阶滞后的平滑系数:
这个公式来自连续一阶系统的阶跃响应匹配(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 = 10\) 或 \(N = 11\)。
从噪声幅度反推限幅阈值
限幅阈值要同时考虑两个因素:稳态噪声幅度和真实最大变化速度。先在稳态下记录传感器输出的最大正常波动幅度 \(A\);再估算物理量的最大变化速率 \(v_{\max}\),单步最大合理变化为 \(v_{\max} \cdot dt\)。阈值 \(D\) 应取两者中较大的那个,再留 1.5~2 倍余量。如果不确定,宁可设大一点——设大了只是偶尔漏掉一个尖峰,设小了会卡住正常信号。
从稳态抖动反推迟滞宽度
回差带应大于稳态噪声的峰峰值。如果传感器在阈值附近抖动 ±20 mV,回差带至少设 50~60 mV。
从传感器噪声指标反推卡尔曼 R
有两种方法,推荐优先用第二种。
方法一:从噪声密度估算。 传感器数据手册给出噪声密度 \(e_n\) 时,可以用:
其中 \(B\) 是有效噪声带宽,受模拟前端、抗混叠滤波和数字滤波影响,通常远小于 \(f_s/2\)。如果不确定 \(B\) 的值,直接用 \(f_s\) 会高估 \(R\),导致滤波器过度信任预测。
方法二(推荐):直接测量稳态方差。 在传感器输入固定(比如短接或接标准信号)的情况下,采集几百个样本,计算方差作为 \(R\) 的估计。这个方法不依赖噪声模型假设,结果更可靠。
从系统变化速度反推卡尔曼 Q
过程噪声 \(Q\) 反映"系统每步变化的不确定度"。在一维随机游走模型(状态只有位置,没有显式速度)中,初始可以从 \(R/100\) 到 \(R/10\) 开始。如果滤波器对真实变化响应太慢,增大 Q;如果输出太抖,减小 Q。多维卡尔曼的 \(Q\) 是矩阵,单位和结构取决于状态定义,不能简单地和 \(R\) 做比例。
反推只是起点
反推出来的参数是工程起点,不是最终值。实际系统中传感器噪声、信号特性和干扰环境都和理论假设不同。反推之后必须用真实数据验证,根据验证结果微调。
常用工程配方
下面每个配方按统一格式写:适用场景、推荐链路、参数起点、验证方法、什么时候会失效。
稳定显示仪表
适用场景。 温度、电压、液位等慢变量的显示。用户需要看到稳定读数,但又不能明显滞后于真实值。
推荐链路。
参数起点。
- 限幅阈值 \(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 的一阶滞后。
电池电压保护
适用场景。 电池供电设备的欠压保护。需要在电压跌破阈值时可靠关断,但不能因为负载瞬态导致误关断。
推荐链路。
参数起点。
- 滑动平均窗口:按允许保护延迟选。采样率 100 Hz,允许 100 ms 延迟,窗口取 10。
- 欠压阈值:按电池规格和负载特性选。锂电池保护通常 3.0~3.2 V。
- 回差带:恢复阈值比欠压阈值高 100~200 mV,防止在阈值附近反复开关。
- 消抖时间:覆盖负载瞬态。大电容充电可能持续几十毫秒,消抖可以设 100~500 ms。
验证方法。
- 用可调电源模拟电压缓慢下降,确认在正确电压触发保护。
- 在阈值附近反复升降电压,确认不会反复开关。
- 投入大负载制造瞬态,确认不会误触发保护。
- 电压恢复后确认能正常解除保护状态。
什么时候会失效。 负载电流变化很大时,电池内阻压降会导致电压剧烈波动,单看电压可能误判。如果负载状态可以读取(比如通过电流传感器),可以结合负载状态做判断:负载投入时不检查欠压,等电压稳定后再判断。
压力/液位传感器抗尖峰
适用场景。 工业现场的压力、液位传感器。信号上有偶发尖峰(接触不良、电磁干扰),同时有小幅随机抖动。
推荐链路。
参数起点。
- 限幅阈值:取正常最大变化速率 × 采样周期 × 2。例如压力每秒最多变化 10 kPa,采样率 100 Hz,单步最大变化 0.1 kPa,阈值设 0.2 kPa。
- 持续 2 个采样点可用 5 点中值;持续 3 个采样点至少考虑 7 点窗口,或者先用变化率门限检测异常段,再用保持旧值策略跳过。
- 一阶滞后 alpha:从 0.1 开始,根据显示稳定性调整。
验证方法。
- 在正常数据中人为插入尖峰,确认限幅或中值能去掉。
- 确认正常快速变化时输出不会被限幅卡住。
- 长时间运行,确认没有累积漂移。
什么时候会失效。 尖峰持续时间超过中值窗口的一半时,中值也会被污染。此时需要加大窗口,或者先用变化率门限检测异常段,再用保持旧值策略跳过。
称重或慢速测量
适用场景。 称重传感器、高精度电压测量。信号很干净但有小幅随机噪声,需要尽可能降低抖动,同时允许较大延迟。
推荐链路。
或者:
参数起点。
- 滑动平均窗口:按允许延迟选。称重显示可以接受 0.5~1 秒延迟,窗口可以取大。
- 如果采样率可以提高,过采样 16 倍后每 16 点平均再抽取,标准差约降为 \(1/\sqrt{16}=1/4\)。注意:单纯每 16 点取 1 点没有降噪效果,必须先做平均或低通。
- 一阶滞后 alpha:0.01~0.05,配合长窗口使用。
验证方法。
- 静态测试:传感器放固定砝码,记录输出的最大最小值之差。
- 阶跃测试:放上砝码后记录输出达到 95% 的时间,确认延迟在允许范围内。
- 和高精度参考对比(如果有)。
什么时候会失效。 过采样假设噪声是白噪声。如果噪声有低频分量(比如 1/f 噪声或温漂),过采样不能降低这些成分。长窗口在信号突变时延迟很大——称重时物品放上后要等很久读数才稳定,可能需要配合动态 alpha 加快响应。
电机电流检测
适用场景。 电机控制中的电流采样。信号上有 PWM 纹波和开关噪声,需要提取基波分量或平均电流。
推荐链路。
参数起点。
- 采样时机:尽量在 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 工频干扰。
推荐链路。
或者:
参数起点。
- 陷波 Q:工频较稳定时从 20 开始,频率会漂移时降到 5~10。
- 整周期平均:如果采样率能和工频同步,取工频周期的整数倍作为平均窗口。
验证方法。
- 对比陷波前后数据的频谱,确认 50/60 Hz 分量被压低。
- 确认目标信号频率没有被误伤。
- 长时间运行,确认工频频率漂移时陷波仍然有效。
什么时候会失效。 工频频率漂移超出陷波带宽时会漏掉部分干扰。整周期平均要求采样率和工频严格同步,不同步时效果下降。如果干扰不是单一频率(比如有谐波),可能需要多个陷波或宽带低通。
单频检测
适用场景。 DTMF 检测、电力谐波监测、判断某个振动频率是否存在。
推荐链路。
参数起点。
- Goertzel 窗口长度 \(N\):让目标频率尽量落在 DFT bin 上,即 \(f_0 \approx k \cdot f_s / N\)。
- 阈值:先采集没有目标频率时的背景能量,再采集有目标频率时的能量,选两者之间有裕量的位置。
- 连续确认:要求连续多帧能量都超阈值才确认。
验证方法。
- 用已知频率的正弦信号测试,确认检测灵敏度。
- 用不含目标频率的噪声测试,确认误报率。
- 测试目标频率有小范围漂移时的检测能力。
什么时候会失效。 目标频率漂移导致能量分散到邻近 bin,检测灵敏度下降。输入幅度变化大时,固定阈值可能不适用,需要用能量占比作为判断指标。
判断算法是否用错
出现下面现象时,通常说明算法或参数不合适:
| 现象 | 可能原因 | 检查方向 |
|---|---|---|
| 输出很稳,但真实变化来了半天跟不上 | alpha 太小或窗口太大 | 检查截止频率是否远低于信号带宽 |
| 稳态时输出跟着噪声一起抖 | alpha 太大或没有预处理 | 先限幅或中值去尖峰,再减小 alpha |
| 异常尖峰后,平均值很久才恢复 | 尖峰进入了平均窗口 | 先限幅或中值去尖峰,再送入平均 |
| 阈值附近报警器疯狂开关 | 回差带太小或没有消抖 | 加大回差带,加消抖确认 |
| 卡尔曼调了很多参数,效果和一阶滞后差不多 | 系统模型没有价值,或 Q/R 比例不对 | 先确认模型是否合理,再调 Q/R |
| 采样率改了,滤波效果完全变了 | 参数和采样率耦合 | alpha、窗口长度、Q,以及由带宽估算出来的噪声方差需要重新确认 |
| 陷波后目标信号也被压掉了 | 陷波频率和信号频率太近 | 确认信号频率和干扰频率的关系,考虑用更窄的陷波或换方案 |
| 滤波输出有周期性波动 | 可能有未处理的周期干扰 | 用频谱分析确认干扰频率,加陷波或 FIR |
关键原则: 先确认问题类型,再选算法。先用简单算法,再升级复杂算法。参数从指标反推,再用数据微调。效果不好时先检查问题类型判断是否正确,再检查参数是否合理,最后才怀疑算法本身。
选型流程清单
拿到一个测量问题时,按这个顺序走一遍:
- 画原始曲线。 把 ADC 原始值随时间画出来,不要一上来就滤波。
- 标注问题。 在图上标出:尖峰在哪里、周期波动的频率是多少、有没有慢漂移、真实信号的变化速度大概多快。
- 写延迟上限。 这个应用能接受多大延迟?写下来,后面选窗口和 alpha 时对照。
- 写约束。 MCU 有没有 FPU、RAM 能放多少、输出是连续值还是开关量。
- 选链路。 按"预处理 → 主滤波 → 后处理"选算法组合,从最简单的开始试。
- 反推参数。 用截止频率、延迟、噪声指标反推,不要凭感觉写。
- 记录验证结果。 静态测试、阶跃测试、长时间测试的数据都记下来。参数改了之后重新测,对比前后效果。
这个流程不保证一次选对,但能保证每次调整都有依据。
小结:选型不是比算法高级
| 决策步骤 | 核心问题 | 常见错误 |
|---|---|---|
| 看数据 | 噪声长什么样?信号允许多大延迟? | 不看数据就选算法 |
| 判断问题类型 | 是随机噪声、尖峰、周期干扰还是慢漂移? | 把尖峰当随机噪声处理 |
| 确定约束 | 延迟、RAM、FPU、输出形式 | 选完算法才发现约束不满足 |
| 选算法组合 | 预处理 → 主滤波 → 后处理 | 只用一个算法硬扛 |
| 反推参数 | 从截止频率、延迟、噪声指标反推 | 凭感觉调参数 |
| 验证效果 | 静态、阶跃、长时间、边界测试 | 只看曲线"像不像" |
选型的本质不是"哪个算法更高级",而是"哪个算法最适合这个问题、这个约束、这个验证条件"。简单算法可解释、可维护、可验证,在很多 MCU 项目里反而更可靠。