嵌入式信号处理:限幅、中值、均值与惯性滤波算法实战解析 1. 项目概述从噪声中提取信号的艺术在嵌入式开发、数据采集和信号处理领域我们常常会面对一个现实从传感器、ADC模数转换器或者任何物理接口读回来的原始数据很少是“干净”的。这些数据里混杂着各种噪声——可能是电源的50Hz工频干扰可能是电路板上的高频开关噪声也可能是传感器自身的热噪声甚至是一次偶然的物理碰撞。如果你直接把这些“毛刺”数据拿去用轻则导致屏幕上的曲线跳来跳去、用户体验糟糕重则可能让一个自动控制系统做出错误的决策引发故障。这时候数字滤波算法就登场了。它就像一位经验丰富的工匠面对一块粗糙的玉石原始数据通过一系列巧妙的“打磨”手法剔除杂质噪声还原出玉石本身温润的质地真实信号。与需要电阻、电容、电感等物理元件搭建的模拟滤波器不同数字滤波完全在数字域通常是微控制器或处理器的内存中通过数学运算实现。这种“软”实现方式带来了巨大的灵活性算法可以随时修改参数甚至更换无需改动硬件电路一个处理器可以同时运行多种滤波算法处理多路信号而且数字滤波没有模拟器件的老化、温漂问题一致性非常好。今天我们就来深入聊聊几种在工程实践中出场率最高、也最实用的数字滤波算法。我不会只给你干巴巴的公式而是会结合我十多年在工业控制、物联网设备开发中踩过的坑详细拆解它们的原理、特点、适用场景以及那些数据手册上不会写的“玄学”参数调整经验。无论你是正在做毕设的学生还是需要快速解决产品数据抖动问题的工程师这篇文章都能给你提供可以直接“抄作业”的方案。2. 滤波算法核心思路与选型逻辑在具体介绍算法之前我们必须先建立一个正确的认知没有“最好”的滤波算法只有“最合适”的。选择哪种算法取决于你的信号特性、噪声特性、系统资源以及对实时性的要求。盲目套用高级算法有时效果还不如一个简单的限幅滤波。2.1 理解信号与噪声滤波的前提滤波的本质是分离。要想分离得好你必须先了解你要的“信号”和你不要的“噪声”各自长什么样。信号的频率与变化速度你的有效信号变化快慢如何是一个缓慢变化的温度可能几分钟才变1度还是一个高速旋转的电机编码器脉冲微秒级变化有效信号的最高频率成分决定了滤波器需要保留的带宽。噪声的来源与特性随机白噪声广泛存在幅值随机频谱平坦。像ADC的量化噪声、传感器热噪声。这类噪声通常幅度较小且随机适合用均值滤波或惯性滤波来平滑。脉冲噪声椒盐噪声偶然出现的、幅值很大的突变点。比如开关触点抖动、电磁干扰引起的瞬间毛刺。这类噪声会严重破坏均值但用中值滤波或限幅滤波对付它效果奇佳。周期性干扰如50Hz工频干扰。这需要设计特定频率的陷波器如IIR滤波器今天讨论的几种简单算法对此效果有限但惯性滤波能一定程度衰减特定频率。2.2 算法选型决策树面对一个具体的滤波需求你可以沿着下面这个思路快速决策原始数据是否经常出现“离谱”的异常跳变脉冲噪声 ├── 是优先使用【限幅滤波】作为第一道防线滤除明显异常值。 │ 然后根据信号特性选择后续处理 │ ├── 信号变化缓慢追求平滑使用【惯性滤波】或【均值滤波】。 │ └── 信号中有偶发脉冲且排序后取中间值有意义使用【中值滤波】。 │ └── 否数据基本可靠只是有小幅波动随机噪声。 ├── 系统资源极度紧张RAM/算力小使用【递推均值滤波】滑动平均。 ├── 需要平滑曲线且能接受少许相位滞后使用【惯性滤波】一阶低通。 └── 需要严格保证实时性且对突变响应要求高考虑【限幅滤波】或少量点的【中值滤波】。这个决策树只是一个起点。在实际项目中我经常采用“组合拳”比如“限幅惯性”或者“限幅中值”先用限幅干掉明显坏点再用其他算法平滑随机噪声。2.3 关键性能指标权衡选择算法时心里要时刻掂量这几个指标的平衡滤波效果输出信号有多平滑噪声被抑制了多少通常用信噪比提升程度来衡量。实时性/滞后性滤波后的信号相比真实信号延迟了多少这对于闭环控制系统如PID是致命的。均值滤波和中值滤波的滞后是固定的由窗口大小决定而惯性滤波的滞后与参数有关。计算开销需要多少CPU时间和内存在低端的8位MCU上一个浮点乘除都可能成为负担。代码复杂度算法是否易于实现、调试和维护鲁棒性对异常值的容忍度如何一个异常点会不会导致输出严重失真接下来我们就带着这些权衡逐一拆解每个算法。3. 限幅滤波简单粗暴的“门卫”限幅滤波也叫程序判断滤波。它的思想最简单也最直观我不相信一次剧烈的突变。它设定一个合理的最大变化幅度如果本次采样值相对上次有效值的偏差超过了这个幅度就认为这是不可信的噪声或干扰于是丢弃它用上次的有效值代替。3.1 算法原理与实现它的核心就是一个条件判断。假设last_value是上一次滤波输出的有效值current_raw是本次采样原始值threshold是你设定的最大允许变化量。// 限幅滤波函数示例 (C语言) float LimiterFilter(float current_raw, float last_value, float threshold) { float delta current_raw - last_value; if (delta threshold) { // 正向变化超限认为是干扰输出上次值 return last_value; } else if (delta -threshold) { // 负向变化超限认为是干扰输出上次值 return last_value; } else { // 变化在允许范围内认为是有效信号更新为本次值 return current_raw; } }在实际使用中last_value需要作为一个静态变量或全局变量在函数外部保持。3.2 特点与适用场景分析优点极致简单几乎不消耗计算资源几行代码搞定在8位单片机上也游刃有余。零滞后对于有效信号只要变化量在阈值内输出立即等于最新输入对信号的快速跟踪能力极强。有效抑制大幅脉冲干扰对于偶尔出现的、幅值巨大的毛刺它能像门卫一样坚决拦在外面。缺点对阈值设定非常敏感threshold是这个算法的灵魂也是最大的难点。设大了滤不掉噪声设小了可能把真实的快速信号也滤掉导致信号失真。对慢变噪声无效如果噪声幅度小于阈值它会完全放行没有任何平滑作用。可能“卡住”信号如果真实信号发生了一个合理的、但超过阈值的阶跃变化比如设备突然启动限幅滤波会将其误判为干扰而拒绝更新导致输出“卡”在旧值上直到某次采样值落在阈值范围内才能跟上。这在系统状态突变时很危险。适用场景预处理或第一级滤波我几乎会在所有需要滤波的数据通道前先加一个限幅滤波。用它来剔除那些显而易见的、物理上不可能的异常值比如温度瞬间跳变100度。信号本身变化缓慢但偶有大干扰例如电池电压监测电压通常很稳定但可能在继电器吸合时受到瞬间干扰。对实时性要求极高的控制回路作为最后一道保护防止因单个采样错误导致控制量剧烈波动。3.3 参数设定心得与避坑指南设定threshold没有万能公式但有几个实用的方法基于物理常识这是最好的方法。你的信号在正常工况下单位时间一个采样周期内最大可能变化多少比如一个散热良好的电机温升速率是1°C/秒你每秒采样10次那么一个采样周期内温度最大变化可能就是0.1°C。你可以将threshold设为0.15°C留一点余量。观察历史数据在系统稳定运行时记录一段时间内相邻采样值的最大差值取这个差值的1.5到2倍作为初始阈值。动态阈值进阶对于更复杂的场景阈值可以不固定。例如可以根据信号最近的变化率来动态调整阈值变化快时阈值放宽变化慢时阈值收紧。但这增加了复杂度。踩坑记录在一个无人机高度计数据滤波中我使用了限幅滤波。初期阈值设得较小飞行器快速升降时真实的高度变化被误滤导致控制器认为高度没变做出了错误调整引发震荡。后来改为当检测到油门大幅变化时临时增大高度数据的滤波阈值问题才解决。关键点阈值不是一成不变的需要结合系统状态。4. 中值滤波对付“刺头”的专家如果说限幅滤波是门卫那中值滤波就是一位冷静的裁判。它的思路是在一小段时间内取一个样本序列按大小排序取中间的那个值作为输出。这个方法的妙处在于它能完美滤除偶然出现的、与其他值差异巨大的脉冲干扰因为无论这个脉冲是极大还是极小在排序后它只会出现在序列的两端而中位值永远来自序列中“大多数”正常样本。4.1 算法原理与排序优化基本步骤创建一个长度为N奇数的缓冲区存放最近的N次采样值。每次新采样到来替换掉缓冲区中最旧的一个值。对缓冲区内的N个数据进行排序。取排序后位于正中间位置的值第 (N1)/2 个作为本次滤波输出。N通常取3, 5, 7, 9。N越大滤波效果越平滑但滞后也越大计算量也急剧上升因为排序。排序是性能关键。对于嵌入式系统对每个采样点都做一次全排序比如冒泡排序 O(N²)开销太大。有两大优化策略使用更高效的排序算法对于固定小窗口如N5可以使用插入排序。因为每次只更新一个值缓冲区基本有序插入排序在这种情况下效率接近O(N)。或者针对3/5/7这种小窗口直接用比较交换网络一种硬编码的比较序列来实现排序完全没有循环和分支速度极快。递推式中值滤波这是更高级的优化。其核心思想是维护一个“左堆”和“右堆”来快速获取中位数但实现复杂。在大多数MCU项目中如果N≤5直接用优化后的排序如比较网络就足够了。下面是一个N5的硬编码比较交换网络示例伪代码它比冒泡排序快得多// 对数组a[5]进行排序比较交换网络 void sort5(int a[5]) { #define SWAP(i, j) if (a[i] a[j]) { int t a[i]; a[i] a[j]; a[j] t; } // 共9次比较交换固定顺序 SWAP(0, 1); SWAP(3, 4); SWAP(2, 4); SWAP(2, 3); SWAP(0, 3); SWAP(0, 2); SWAP(1, 4); SWAP(1, 3); SWAP(1, 2); #undef SWAP } // 排序后a[2]就是中位数4.2 特点与适用场景分析优点卓越的抗脉冲干扰能力这是它的看家本领能有效滤除偶然的、强度大的毛刺而均值滤波会被这种毛刺严重带偏。能较好保护信号边缘对于信号的阶跃变化中值滤波的输出也会是一个阶跃只是会有N/2个采样点的延迟不像均值滤波会把边缘变缓。不需要乘除运算核心是排序和比较适合整数运算或没有硬件乘除法器的低端MCU。缺点计算开销大排序操作即使优化了也比简单的加减乘除开销大。窗口N越大开销增长越快。固定滞后输出滞后输入 (N-1)/2 个采样周期。这对于实时控制是个问题。对高斯噪声随机小噪声平滑效果一般对于均匀分布的随机小波动中值滤波的平滑效果不如均值滤波或惯性滤波。需要缓冲区消耗RAM窗口越大消耗越多。适用场景图像处理中的椒盐噪声滤除这是中值滤波的经典应用场景。开关量、数字信号去抖动比如按键检测读取一连串的电平取中值可以有效消除抖动。存在强烈脉冲干扰的工业现场例如靠近电焊设备、大电机启停的传感器信号采集。保护信号细节当你需要滤除噪声但又不想过度平滑掉信号本身的快速变化特征时。4.3 窗口大小选择与实战技巧窗口大小N的选择是门艺术N3最快速滞后最小1个采样点能滤除单点脉冲。但平滑能力弱对连续两个异常点就无能为力了。N5最常用的折中选择。能滤除连续两个异常点平滑效果和滞后都在可接受范围。N7或更大用于噪声非常严重或对平滑度要求极高且可以接受较大滞后的场合。比如一些离线数据分析。实操心得在电机电流采样中PWM开关会导致电流波形上有尖峰。直接用均值滤波尖峰会影响平均值。我用一个N5的中值滤波先处理完美去掉了这些周期性尖峰然后再用一个惯性滤波来平滑高频纹波效果非常好。组合使用往往比单打独斗更强。5. 均值滤波最经典的平滑器均值滤波也叫移动平均滤波或滑动平均滤波它的思想朴素而强大认为噪声是随机的多次测量的平均值会更接近真实值。它计算一个滑动窗口内所有采样值的算术平均值作为输出。5.1 算法原理与递推优化最直接的实现需要维护一个长度为N的循环缓冲区float buffer[N]; int index 0; float sum 0; float MovingAverageFilter(float new_sample) { sum sum - buffer[index] new_sample; // 减去最旧的加上最新的 buffer[index] new_sample; index (index 1) % N; return sum / N; }这就是递推均值滤波它非常高效。每次更新只需要一次加法、一次减法和一次除法不需要遍历整个数组求和。还有一种变体叫加权移动平均给窗口内不同时刻的数据赋予不同的权重通常越新的数据权重越高。这可以在平滑噪声的同时提高对信号变化的响应速度。其公式为输出 (w1*x1 w2*x2 ... wn*xn) / (w1w2...wn)。当所有权重相等时就退化为普通均值滤波。5.2 频率响应与参数影响均值滤波在频域上相当于一个低通滤波器。它的幅频特性是一个sinc函数。有两个关键特性截止频率窗口长度N越大或采样周期T越长滤波器的截止频率就越低能滤除更高频的噪声但同时也会把更高频的有效信号成分滤掉。截止频率粗略估算为fc ≈ 0.443 / (N * T)。旁瓣sinc函数有旁瓣意味着在某些特定频率上噪声不但没被衰减反而被放大了。这是均值滤波的一个缺点。N的选择至关重要N太小平滑效果不明显噪声残留多。N太大平滑效果强但信号滞后严重滞后约 (N-1)/2 个采样点并且会过度平滑导致信号变化变缓陡峭的边沿会变成斜坡。5.3 特点、适用场景与局限性优点算法简单易于理解实现。对随机噪声有良好的抑制效果平滑能力强。递推实现计算效率高资源消耗少。缺点对脉冲干扰非常敏感一个异常大值会显著影响整个窗口的平均值造成输出出现一个“毛刺”。固定滞后影响系统实时性。降低了信号的分辨率经过平均信号的变化变得迟缓。适用场景信号变化缓慢噪声为随机白噪声如温度、压力、湿度等慢变物理量的测量。系统资源有限需要简单有效的平滑递推均值滤波是性价比极高的选择。作为更复杂滤波器的前置平均器先对数据进行多点平均降低数据速率再送给后续处理器。局限性警示千万不要在有可能出现脉冲干扰的场合单独使用均值滤波否则一个干扰脉冲会导致输出出现一个宽达N个周期的“驼峰”。在实际项目中我见过因为一个电源干扰导致均值滤波后的水位数据出现一个长达10秒的虚假峰值触发了错误报警。务必与限幅滤波联用。6. 惯性滤波模拟世界的数字映射惯性滤波在电子和信号处理领域更常被称为一阶低通滤波或指数加权移动平均。它模仿了RC模拟低通滤波器的行为输出不能突变只能缓慢地跟踪输入。它的数学表达非常优雅用到了上一次的输出结果。6.2 算法原理与差分方程它的核心公式如下Y(n) α * X(n) (1 - α) * Y(n-1)其中Y(n)是本次滤波输出值。Y(n-1)是上一次滤波输出值。X(n)是本次采样输入值。α是滤波系数0 α ≤ 1。这个公式具有深刻的物理意义本次的输出是本次输入和上次输出的加权平均。α越大本次输入的权重越高滤波器响应越快但平滑效果越差α越小上次输出的权重越高滤波器惯性越大越平滑但响应越慢。这个公式是递推的它只需要记住上一次的输出值而不需要像均值滤波那样维护一个历史缓冲区节省了内存。6.2 滤波系数α与截止频率的关系这是惯性滤波最关键也最容易用错的地方。α不是一个随意设置的“感觉”值它与系统的采样周期T和期望的滤波器截止频率fc有明确的数学关系。对于一个模拟RC低通滤波器其时间常数τ R*C截止频率fc 1 / (2πτ)。 在数字域我们需要将其离散化。根据后向差分法可以得到α T / (τ T) 2πfcT / (1 2πfcT)通常当2πfcT 1时即采样频率远高于截止频率这个公式可以简化为工程上常用的近似公式α ≈ 2πfcT计算示例假设我们采样一个信号采样周期T 0.01秒即采样率100Hz。我们想设计一个截止频率fc 1 Hz的低通滤波器来滤除高频噪声。 计算2πfcT 2 * 3.1416 * 1 * 0.01 ≈ 0.0628由于0.0628 1我们可以使用近似公式α ≈ 0.0628你可以取α 0.06或0.07。如果不使用近似用完整公式α 0.0628 / (1 0.0628) ≈ 0.059结果非常接近。重要提示α必须小于1。如果按照公式算出来α 1说明你期望的截止频率fc太高了接近或超过了采样频率的一半即奈奎斯特频率这是不现实的你需要降低fc或提高采样率。6.3 特点、适用场景与实现细节优点超高效每次计算只需一次乘法、一次乘加和一次减法内存占用仅一个变量上次输出值。相位滞后相对较小与相同平滑效果的均值滤波相比。参数α有明确的物理意义可以直接关联到截止频率设计方便。对脉冲干扰有一定韧性由于输出受历史值影响大单个脉冲干扰对输出的影响会被“惯性”缓冲掉一部分不会像均值滤波那样产生一个平顶的干扰。缺点仍然有滞后α越小滞后越严重。对阶跃信号的响应是指数曲线上升速度由α决定无法像中值滤波那样保持阶跃形状。系数α通常为小数在只有定点数的MCU上需要处理精度问题。适用场景需要连续平滑的实时信号如机器人关节角度、车辆速度、飞行器姿态等控制回路中的反馈信号。系统内存极其紧张无法开辟缓冲区做均值或中值滤波时惯性滤波是唯一选择。作为PID控制器的输入滤波器滤除测量噪声防止微分项被噪声放大。定点数实现技巧在无浮点单元的MCU上可以用整数运算来模拟小数。例如设α 0.0625这恰好是1/16。那么滤波公式可以改写为Y(n) ( X(n) 15 * Y(n-1) ) / 16这里用了一次乘法和一次除法右移4位完全用整数完成。选择α为2的负幂次方如1/2, 1/4, 1/8, 1/16...可以极大地优化计算速度。参数调试经验调α时我习惯先在电脑上用历史数据仿真。把α从大到小调整观察滤波后的曲线。一个好的起始点是让α对应的截止频率是你信号带宽的3-5倍。然后遵循一个原则在满足平滑性要求的前提下尽可能选用较大的α更快的响应。记住滤波不是要把信号变得“一动不动”而是要剔除不合理的噪声保留真实的变化趋势。7. 算法组合与进阶策略在实际工程中单一算法往往难以应对所有情况。将几种简单算法组合起来形成滤波链路是提升数据质量的常用手段。7.1 经典组合方案限幅 惯性滤波这是我个人最常用、也最推荐的组合之一。第一级限幅滤波。设置一个合理的阈值将那些明显超出物理变化极限的野值直接剔除。这一步保护了后续的滤波器防止一个野值污染惯性滤波器的内部状态Y(n-1)。第二级惯性滤波。对经过限幅“净化”的数据进行平滑抑制随机高频噪声。优点兼具抗脉冲干扰和平滑能力资源消耗低实时性好。代码实现上就是把限幅滤波的输出作为惯性滤波的输入。限幅 中值滤波第一级限幅滤波。同样先做粗筛。第二级中值滤波。进一步滤除那些幅度较大但未超过限幅阈值的偶发干扰同时对信号边缘保持较好。适用场景信号中脉冲噪声较多且需要保持信号快速变化特征。例如数字通信中的信号整形。中值滤波 均值滤波第一级中值滤波窗口较小如N3。去除尖峰脉冲。第二级均值滤波窗口可稍大。平滑剩余的高斯噪声。优点综合了中值滤波抗脉冲和均值滤波平滑随机的优点。在图像处理中这种组合很常见。7.2 自适应滤波思路对于更复杂的场景固定的滤波参数可能不够用可以考虑让滤波器“聪明”起来。变系数惯性滤波核心思想是让滤波系数α动态变化。当检测到信号变化剧烈时可能是真实变化增大α让滤波器快速跟踪当信号平稳时减小α增强平滑效果。判断信号变化剧烈程度可以通过计算近期数据的方差或差分值来实现。// 简化的变系数惯性滤波思路 float delta fabs(current_raw - last_output); float adaptive_alpha base_alpha; if (delta change_threshold) { adaptive_alpha high_alpha; // 变化大快速跟踪 } else { adaptive_alpha low_alpha; // 变化小强力平滑 } output adaptive_alpha * current_raw (1 - adaptive_alpha) * last_output;动态限幅阈值如前所述根据系统工况如电机转速、设备负载动态调整限幅滤波的阈值在稳定时收紧阈值以提高精度在动态过程中放宽阈值以防止信号卡死。这些自适应方法增加了算法的复杂性需要仔细调试但在应对非平稳信号时效果显著。7.3 滤波器的“负作用”与系统级考量使用滤波器时必须清醒地认识到它在消除噪声的同时一定会对原始信号造成影响这种影响有时是“负作用”。相位滞后几乎所有滤波器都会引入相位延迟。在闭环控制系统中反馈通道的相位滞后会减少系统的相位裕度可能引发振荡。在设计控制器时必须考虑滤波环节带来的相位滞后。信号失真过度滤波会平滑掉信号中的高频成分导致信号的快速变化特征丢失。例如一个方波经过低通滤波后会变成三角波或正弦波。响应速度下降滤波器使得系统对输入的响应变慢。这对于需要快速响应的系统如碰撞检测、紧急制动是不可接受的。系统级建议在项目初期就要规划数据流。明确哪些数据需要滤波在哪个环节滤波是在传感器数据读取后立即滤波还是在控制算法计算前滤波还是在显示输出前滤波。为不同的数据通道选择合适的滤波器和参数并记录在案。滤波器的参数如窗口大小N、系数α、阈值应设计为可配置的通过宏定义或配置文件以便于现场调试和优化。8. 实战问题排查与经验汇编即使理解了原理在实际编码和调试中还是会遇到各种问题。下面是我整理的一些常见“坑”和解决技巧。8.1 典型问题速查表问题现象可能原因排查思路与解决方案滤波后数据仍有高频抖动1. 滤波强度不够α太大N太小。2. 噪声频率在滤波器通带内。3. 采样率过低发生混叠。1. 降低α或增大N观察效果。2. 分析噪声频率重新设计滤波器截止频率。3. 提高采样率或在ADC前端增加模拟抗混叠滤波器。信号变化明显变慢像“粘住”一样滤波过度α太小N太大滞后严重。增大α或减小N。考虑是否必须用滤波能否从源头降低噪声输出出现不应有的台阶或毛刺1. 限幅滤波阈值设得太小卡住了真实信号。2. 中值滤波窗口内有多个连续异常点。3. 缓冲区溢出或索引错误编程Bug。1. 适当增大限幅阈值或改用动态阈值。2. 增大中值滤波窗口N或先进行限幅预处理。3. 仔细检查循环缓冲区的索引更新和初始化代码。系统运行一段时间后数据异常1. 滤波算法中的静态变量或缓冲区未正确初始化。2. 整数或定点数运算溢出。3. 内存被意外修改。1. 确保上电或重启后对所有滤波器的内部状态进行清零或赋初值。2. 检查计算过程中的数据范围使用更大位宽的数据类型。3. 检查是否有数组越界、指针错误等问题。滤波算法消耗CPU时间过多1. 使用了低效的排序算法如冒泡排序做中值滤波。2. 窗口N设置过大。3. 在中断服务程序中进行了浮点运算某些MCU很慢。1. 对固定小窗口使用比较交换网络。2. 评估是否必须用这么大的N尝试减小N或换用惯性滤波。3. 将浮点运算改为定点运算或将滤波移到主循环中。8.2 调试与验证技巧离线仿真先行在电脑上用Python、MATLAB或Excel用录制好的真实数据或模拟数据运行你的滤波算法调整参数观察效果。这比在目标板上在线调试高效得多。可视化是关键尽可能将原始数据和滤波后的数据同时绘制成曲线图。眼睛是最强大的调试工具。观察噪声是否被抑制信号边缘是否保持滞后是否明显。分段调试在代码中设置条件编译开关可以方便地切换不同的滤波器或参数组合进行对比测试。关注边界条件滤波器在启动时缓冲区是空的或内部状态是零。这会导致启动瞬间的输出不正确。考虑给滤波器一个“预热”过程或用前几个采样值初始化缓冲区。量化评估如果条件允许可以计算滤波前后的信噪比、均方根误差等指标量化评估滤波效果。8.3 关于滤波的几点终极心得最后分享几条从无数项目中总结出来的经验滤波是“不得已而为之”最好的噪声处理方式是在硬件层面解决比如优化PCB布局、增加屏蔽、使用更好的电源、在传感器端加模拟滤波器。数字滤波是弥补硬件不足的最后手段。理解你的数据比选择算法更重要花时间分析你的信号和噪声特性用示波器、频谱仪去看用数据记录仪去存。搞清楚了敌情才能选对武器。简单算法优先在满足性能要求的前提下优先选择限幅、递推均值、惯性滤波这些简单算法。它们的确定性更好更容易调试出问题了也更容易排查。不要为了“高级”而使用卡尔曼滤波这类复杂算法。参数没有银弹别人项目里好用的参数照搬到你的系统里可能一塌糊涂。一定要根据你的实际采样率、信号带宽、噪声特性重新计算和调试。记录与文档为每一个数据通道的滤波方案和最终参数添加清晰的注释。半年后当你或别人需要维护这段代码时会感谢当初的自己。