传感器数字滤波算法选型与实现:从限幅平均到卡尔曼滤波

基于《数字滤波常用的软件方法代码实例》《数字滤波与卡尔曼滤波》等技术资料,按干扰类型给出10种经典数字滤波算法的C代码、参数整定与一维卡尔曼滤波数值算例

2026-08-24
数字滤波卡尔曼滤波传感器数据采集信号处理MCU嵌入式开发

传感器数字滤波没有"万能算法",正确的做法是按干扰类型选算法:脉冲型干扰(毛刺、误触发)选限幅、中值、消抖类滤波;随机噪声(热噪声、量化噪声)选算术平均、滑动平均、加权滑动平均;慢变信号叠加高频噪声选一阶滞后滤波;需要动态估计运动状态或连续量时选卡尔曼滤波。本文基于《数字滤波常用的软件方法代码实例》与《数字滤波与卡尔曼滤波》技术资料,给出 10 种经典算法的 C 代码、参数整定原则,以及一维卡尔曼滤波的完整数值算例,可直接用于嵌入式数据采集、RTU 模拟量通道与物联网终端的信号预处理。

一、干扰类型决定滤波策略

现场传感器信号中的干扰大致分三类:一是脉冲型干扰,来自变频器启停、继电器吸合、静电放电等瞬态事件,表现为信号上叠加大幅值尖峰;二是随机噪声,来自器件热噪声、AD 量化噪声与工频耦合,表现为围绕真值的上下抖动;三是误触发抖动,常见于开关量、液位、接近传感器输出。三类干扰的统计特征完全不同,对应的滤波手段也不同,这是选型的总纲。

算法针对干扰原理特点与代价
限幅滤波脉冲毛刺与上次值偏差超限则丢弃最简单,无法滤随机噪声
中值滤波脉冲毛刺N 点排序取中值抗脉冲强,需缓存并排序
消抖滤波误触发抖动连续 N 次采样一致才采纳适合开关量,有响应延迟
算术平均滤波随机噪声连续 N 点求和取平均平滑好,实时性差
滑动平均滤波随机噪声固定窗口滚动平均实时性好,占 N 点 RAM
加权滑动平均随机噪声近时刻权重更大灵敏度高于等权平均
中位值平均滤波脉冲+随机排序去极值后平均综合最强,耗时较长
限幅平均滤波脉冲+随机先限幅剔除毛刺再平均组合算法,折中方案
一阶滞后滤波高频噪声惯性平滑 y=(1-a)y+a·z参数单一,响应可调
限幅消抖滤波脉冲+抖动先限幅再消抖组合算法,双重防护

二、脉冲干扰滤波:限幅、中值、消抖

限幅滤波(又称程序判断滤波)的核心是设定最大允许偏差 A,本次采样与上次有效值偏差超过 A 就判定为干扰并丢弃,直接输出上次值。它实现成本最低,适合保护后续算法不被单个毛刺污染。

#define A 10                     /* 最大允许偏差,按信号变化率整定 */
char value;                      /* 上次有效采样值 */
char limit_filter(void) {
    char new_value = get_ad();   /* 本次采样 */
    if ((new_value - value > A) || (value - new_value > A))
        return value;            /* 超限:判为干扰,保持上次值 */
    return new_value;
}

中值滤波连续采样 N 点(取奇数)排序后输出中值,对脉冲干扰的抑制能力很强,但会引入 N 次采样的延迟。消抖滤波则要求连续 N 次采样与当前值一致才更新输出,是开关量、按键、液位信号的标配,代价是响应存在 N 个采样周期的滞后。

#define N 11                     /* 采样点数(取奇数) */
char median_filter(void) {
    char value_buf[N], count, i, j, temp;
    for (count = 0; count < N; count++) {
        value_buf[count] = get_ad();
        delay();
    }
    for (j = 0; j < N - 1; j++)              /* 冒泡排序 */
        for (i = 0; i < N - 1 - j; i++)
            if (value_buf[i] > value_buf[i + 1]) {
                temp = value_buf[i];
                value_buf[i] = value_buf[i + 1];
                value_buf[i + 1] = temp;
            }
    return value_buf[(N - 1) / 2];           /* 取中值 */
}

#define N 12                                 /* 连续一致次数 */
char debounce_filter(void) {
    char count = 0;
    char new_value = get_ad();
    while (value != new_value) {
        count++;
        if (count >= N) return new_value;    /* 连续 N 次一致才采纳 */
        delay();
        new_value = get_ad();
    }
    return value;
}

三、随机噪声滤波:算术平均、滑动平均与加权

算术平均滤波把连续 N 次采样求和取平均,N 越大平滑越强、噪声方差降至 1/N,但每次输出都要等 N 次采样,实时性差。滑动平均滤波维护一个长度为 N 的窗口,每次采样先进先出再求平均,实时性优于算术平均,是 RTU 模拟量通道最常用的方案。

#define N 12
char value_buf[N];
char i = 0;
char slide_average_filter(void) {
    char count;
    int sum = 0;
    value_buf[i++] = get_ad();        /* 新值入队 */
    if (i == N) i = 0;                /* 环形队列回绕 */
    for (count = 0; count < N; count++)
        sum += value_buf[count];
    return (char)(sum / N);
}

加权滑动平均给越接近当前时刻的采样分配越大权重,在同样平滑程度下响应更快,但需额外保存权重表。中位值平均滤波(防脉冲干扰平均)先把 N 点排序,去掉最大最小值后再平均,同时抑制脉冲与随机噪声,是工业采集的"组合拳",代价是计算量最大。

#define N 12
char code coe[N] = {1,2,3,4,5,6,7,8,9,10,11,12};  /* 权重递增 */
#define SUM_COE 78                                 /* 权重和 1+...+12 */
char weight_average_filter(void) {
    char count;
    char value_buf[N];
    int sum = 0;
    for (count = 0; count < N; count++) {
        value_buf[count] = get_ad();
        delay();
    }
    for (count = 0; count < N; count++)
        sum += value_buf[count] * coe[count];
    return (char)(sum / SUM_COE);
}

四、一阶滞后滤波:慢变信号的惯性平滑

一阶滞后滤波输出 y = (1-a)·y + a·z,其中 a 在 0~100 之间(资料中示例 a=50),a 越大对新采样越敏感、响应越快但滤波越弱;a 越小越平滑但滞后越明显。它只用两个变量、无数组缓存,非常适合温度、液位等慢变模拟量在 MCU 中做轻量平滑,工程实现时注意用整型运算避免溢出(原资料示例未除 100,实际实现须补除以 100):

#define a 50                          /* 0~100,越大对新值越敏感 */
char value;                           /* 上次滤波输出 */
char lag_filter(void) {
    char new_value = get_ad();
    return (char)(((100 - a) * value + a * new_value) / 100);
}

五、卡尔曼滤波:动态估计的最优递推

卡尔曼滤波针对的是"既有噪声又需要跟踪动态变化"的场景,它以状态空间模型为基础,通过"预测-更新"两步递推给出最小均方误差意义下的最优估计。一维恒定模型的五个公式为:预测阶段 x̂(k|k-1)=x̂(k-1)、P(k|k-1)=P(k-1)+Q;更新阶段 K=P(k|k-1)/(P(k|k-1)+R)、x̂(k)=x̂(k|k-1)+K·(z(k)-x̂(k|k-1))、P(k)=(1-K)·P(k|k-1)。其中 Q 为过程噪声方差(反映模型不确定度),R 为测量噪声方差(可由传感器噪声统计标定)。

typedef struct {
    float x;              /* 状态估计值 */
    float p;              /* 估计方差 */
    float q;              /* 过程噪声方差 Q */
    float r;              /* 测量噪声方差 R */
} kalman_1d_t;

float kalman_1d_update(kalman_1d_t *k, float z) {
    float kg;             /* 卡尔曼增益 */
    k->p += k->q;                     /* 预测:方差增大 */
    kg = k->p / (k->p + k->r);        /* 计算增益 */
    k->x += kg * (z - k->x);           /* 更新:按增益修正 */
    k->p *= (1.0f - kg);               /* 更新:方差收缩 */
    return k->x;
}

以一维恒温估计为例验证收敛特性:标称 25.0℃ 的恒温箱,传感器读数叠加标准差 0.5℃ 的高斯噪声(R=0.25),取 Q=0.001,初值 x=24.0、P=1.0。逐次递推 20 步的结果节选如下(固定随机种子可复现):

步数测量值 z(℃)卡尔曼增益 K估计值 x(℃)估计方差 P
124.9280.80024.7430.200
224.9140.44624.8190.111
524.9360.19624.9680.049
1025.0580.10924.9090.027
1524.6310.08324.9930.021
2024.9470.07225.0130.018

可见卡尔曼增益从初期的 0.8 快速衰减到 0.07 附近,估计值从初值 24.0 收敛并稳定在 25.0 附近,估计方差从 1.0 收缩到 0.018。与一阶滞后(a=0.5)对比,同样 20 步内一阶滞后输出在 24.46~25.31 之间波动,而卡尔曼估计的最大偏差不超过 0.2℃,收敛更快且稳态更稳。Q/R 整定原则:R 取传感器实测噪声方差;Q 反映过程模型的可信度,跟踪快速变化时适当增大 Q(如 0.01~0.1),恒温缓变场景取小 Q(如 0.001)。

六、工程选型框架

把算法与现场场景对应起来,可按下表快速决策。需要说明的是,多数工程现场并非单一干扰,组合使用(如限幅前置+滑动平均后置)比单一算法更可靠;滤波器引入的相位延迟与响应速度需要在系统层面权衡。

应用场景信号特征推荐滤波组合
RTU 模拟量采集(4-20mA)工频耦合+随机噪声滑动平均 或 加权滑动平均
称重/力传感器冲击+机械振动中位值平均滤波
温度采集(慢变)高频噪声一阶滞后 或 算术平均
液位/接近/按键开关量抖动误触发消抖滤波 或 限幅消抖
变频器环境下的信号强脉冲群干扰限幅+中值组合
IMU 姿态/运动估计动态变化+噪声卡尔曼滤波

最后给出三点工程建议:一是滤波参数(限幅阈值 A、窗口 N、权重 a、Q/R)必须按被测信号的实际带宽与现场干扰强度标定,不能照抄;二是滤波放在 AD 采样后、控制/上传前,且要统一采样周期;三是若系统已有其他滤波环节(如硬件 RC 低通),数字滤波应与其配合而非叠加,避免过度滤波造成响应迟钝。站内《中值滤波分析》一文对中值滤波的窗口选择有更细致的讨论,可与本文互相印证。

结语

数字滤波的工程本质是"以延迟换平滑、以复杂度换抗扰":脉冲干扰用限幅/中值/消抖,随机噪声用平均族,慢变信号用一阶滞后,动态估计用卡尔曼滤波。卡尔曼滤波通过 Q/R 两个参数即可在平滑度与跟踪速度之间连续调节,是嵌入式端性价比最高的动态滤波手段。本文基于《数字滤波常用的软件方法代码实例》《数字滤波与卡尔曼滤波》等资料整理优化。

需要定制开发?

沧州艾诺威电子 — 国家高新技术企业,20+项国家专利
嵌入式系统开发 · 物联网方案 · AI智能硬件 · 一站式交付

立即微信咨询

电话:13930711029 | 邮箱:tech@czinv.com | 24小时内响应