打印
[经验分享]

10种简单的数字滤波算法

[复制链接]
1558|49
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
janewood|  楼主 | 2023-7-15 23:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机利用软件抗干扰的几种滤波方法:

1、限幅滤波法(又称程序判断滤波法)
    A、方法:
        根据经验判断,确定两次采样允许的最大偏差值(设为A)
        每次检测到新值时判断:
        如果本次值与上次值之差<=A,则本次值有效
        如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值
    B、优点:
        能有效克服因偶然因素引起的脉冲干扰
    C、缺点
        无法抑制那种周期性的干扰
        平滑度差
   
2、中位值滤波法
    A、方法:
        连续采样N次(N取奇数)
        把N次采样值按大小排列
        取中间值为本次有效值
    B、优点:
        能有效克服因偶然因素引起的波动干扰
        对温度、液位的变化缓慢的被测参数有良好的滤波效果
    C、缺点:
        对流量、速度等快速变化的参数不宜

3、算术平均滤波法
    A、方法:
        连续取N个采样值进行算术平均运算
        N值较大时:信号平滑度较高,但灵敏度较低
        N值较小时:信号平滑度较低,但灵敏度较高
        N值的选取:一般流量,N=12;压力:N=4
    B、优点:
        适用于对一般具有随机干扰的信号进行滤波
        这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动
    C、缺点:
        对于测量速度较慢或要求数据计算速度较快的实时控制不适用
        比较浪费RAM
        
4、递推平均滤波法(又称滑动平均滤波法)
    A、方法:
        把连续取N个采样值看成一个队列
        队列的长度固定为N
        每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)
        把队列中的N个数据进行算术平均运算,就可获得新的滤波结果
        N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4
    B、优点:
        对周期性干扰有良好的抑制作用,平滑度高
        适用于高频振荡的系统   
    C、缺点:
        灵敏度低
        对偶然出现的脉冲性干扰的抑制作用较差
        不易消除由于脉冲干扰所引起的采样值偏差
        不适用于脉冲干扰比较严重的场合
        比较浪费RAM
        
5、中位值平均滤波法(又称防脉冲干扰平均滤波法)
    A、方法:
        相当于“中位值滤波法”+“算术平均滤波法”
        连续采样N个数据,去掉一个最大值和一个最小值
        然后计算N-2个数据的算术平均值
        N值的选取:3~14
    B、优点:
        融合了两种滤波法的优点
        对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差
    C、缺点:
        测量速度较慢,和算术平均滤波法一样
        比较浪费RAM


6、限幅平均滤波法
    A、方法:
        相当于“限幅滤波法”+“递推平均滤波法”
        每次采样到的新数据先进行限幅处理,
        再送入队列进行递推平均滤波处理
    B、优点:
        融合了两种滤波法的优点
        对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差
    C、缺点:
        比较浪费RAM

7、一阶滞后滤波法
    A、方法:
        取a=0~1
        本次滤波结果=(1-a)*本次采样值+a*上次滤波结果
    B、优点:
        对周期性干扰具有良好的抑制作用
        适用于波动频率较高的场合
    C、缺点:
        相位滞后,灵敏度低
        滞后程度取决于a值大小
        不能消除滤波频率高于采样频率的1/2的干扰信号
        
8、加权递推平均滤波法
    A、方法:
        是对递推平均滤波法的改进,即不同时刻的数据加以不同的权
        通常是,越接近现时刻的数据,权取得越大。
        给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低
    B、优点:
        适用于有较大纯滞后时间常数的对象
        和采样周期较短的系统
    C、缺点:
        对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号
        不能迅速反应系统当前所受干扰的严重程度,滤波效果差

9、消抖滤波法
    A、方法:
        设置一个滤波计数器
        将每次采样值与当前有效值比较:
        如果采样值=当前有效值,则计数器清零
        如果采样值<>当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出)
            如果计数器溢出,则将本次值替换当前有效值,并清计数器
    B、优点:
        对于变化缓慢的被测参数有较好的滤波效果,
        可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动
    C、缺点:
        对于快速变化的参数不宜
        如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导
入系统

10、限幅消抖滤波法
    A、方法:
        相当于“限幅滤波法”+“消抖滤波法”
        先限幅,后消抖
    B、优点:
        继承了“限幅”和“消抖”的优点
        改进了“消抖滤波法”中的某些缺陷,避免将干扰值导入系统
    C、缺点:
        对于快速变化的参数不宜

假定从8位AD中读取数据(如果是更高位的AD可定义数据类型为int),子程序为get_ad();  
1、限副滤波
/* A值可根据实际情况调整
value为有效值,new_value为当前采样值
滤波程序返回有效的实际值 */

#define A 10
char value;
char filter()
{
        char new_value;
        new_value = get_ad();
        if ( ( new_value - value > A ) || ( value - new_value > A )
        return value;
        return new_value;

}

2、中位值滤波法
/* N值可根据实际情况调整
排序采用冒泡法*/

#define N 11
char filter()
{
        char value_buf[N];
        char 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-j;i++)
                {
                        if ( value_buf>value_buf[i+1] )
                        {
                                temp = value_buf;
                                value_buf = value_buf[i+1];
                                value_buf[i+1] = temp;
                        }
                }
        }
return value_buf[(N-1)/2];
}

3、算术平均滤波法
/*
*/

#define N 12
char filter()
{
        int sum = 0;
        for ( count=0;count<N;count++)
        {
                sum + = get_ad();
                delay();
        }
        return (char)(sum/N);
}

4、递推平均滤波法(又称滑动平均滤波法)
/*
*/

#define N 12
char value_buf[N];
char i=0;
char filter()
{
        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);
}


楼主的滑动滤波法不对,应该是:
#define N 12
char value_buf[N];
char i=0;
int sum=0;
char filter()
{
  char Temp_Value;

  Temp_Value = get_ad();
  sum += value_buf - Temp_Value;
  value_buf[i++] = Temp_Value;
  if ( i == N ) i = 0;
  return (char)(sum/N);
}//注意 value_buf全部初始化为第一次采集的值!!




5、中位值平均滤波法(又称防脉冲干扰平均滤波法)
/*
*/

#define N 12
char filter()
{
        char count,i,j;
        char value_buf[N];
        int sum=0;
        for (count=0;count<N;count++)
        {
                value_buf[count] = get_ad();
                delay();
        }
        for (j=0;j<N-1;j++)
        {
                for (i=0;i<N-j;i++)
                {
                        if ( value_buf>value_buf[i+1] )
                        {
                                temp = value_buf;
                                value_buf = value_buf[i+1];
                                value_buf[i+1] = temp;
                        }
                }
        }
        for(count=1;count<N-1;count++)
        sum += value[count];
        return (char)(sum/(N-2));
}



中位值滤波,为什么要排序?简单的东西,复杂化了。中位值无非就是去掉最大最小值而已,排序太麻烦了。贴上我自己的做法,给大家参考
//
//------------------------------
//
//  ?D???μ??2¨
//  
//------------------------------
//
u16 GetTheMiddleValue(u16 *Pointer,u8 Length)
{
    u8 i;
    u32 temp32 = 0;

    u16 MaxVal = 0x0000;
    u16 MinVal = 0xffff;

    if ( Length>2 )
    {
        for ( i=0;i<Length;i++ )
        {
            if ( Pointer> MaxVal)
            {
                MaxVal = Pointer;
            }
            if ( Pointer<MinVal )
            {
                MinVal = Pointer;
            }
            temp32 += Pointer;
        }
        temp32 = (temp32-MaxVal-MinVal)/(Length-2);
    }
    else
    {
        for ( i=0;i<Length;i++ )
        {
            temp32 += Pointer;
        }
        temp32 = temp32/Length;
    }

    return (u16)temp32;
}



6、限幅平均滤波法
/*
*/
略 参考子程序1、3


7、一阶滞后滤波法
/* 为加快程序处理速度假定基数为100,a=0~100 */

#define a 50
char value;
char filter()
{
        char new_value;
        new_value = get_ad();
        return (100-a)*value + a*new_value;
}


8、加权递推平均滤波法
/* coe数组为加权系数表,存在程序存储区。*/

#define N 12
char code coe[N] = {1,2,3,4,5,6,7,8,9,10,11,12};
char code sum_coe = 1+2+3+4+5+6+7+8+9+10+11+12;
char filter()
{
        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);
}


9、消抖滤波法

#define N 12
char filter()
{
        char count=0;
        char new_value;
        new_value = get_ad();
        while (value !=new_value);
        {
                count++;
                if (count>=N) return new_value;
                delay();
                new_value = get_ad();
        }
        return value;
}

使用特权

评论回复
沙发
OKAKAKO| | 2023-7-22 13:27 | 只看该作者
楼主这个滤波算法还是比较齐全的

使用特权

评论回复
板凳
中国龙芯CDX| | 2023-7-24 13:08 | 只看该作者
经常使用中均值滤波的方法,基本上很准确

使用特权

评论回复
地板
小小蚂蚁举千斤| | 2023-7-25 09:50 | 只看该作者
算术平均滤波法经常用到,楼主总结的很细致

使用特权

评论回复
5
小夏天的大西瓜| | 2023-7-25 10:10 | 只看该作者
数字滤波无需其他的硬件成本,只有一个计算过程,可靠性高,不存在阻抗匹配问题

使用特权

评论回复
6
szt1993| | 2023-7-25 11:07 | 只看该作者
滑动平均滤波法考虑的注意事项还是比较多的,采样准确性还是挺高的

使用特权

评论回复
7
OKAKAKO| | 2023-7-25 12:43 | 只看该作者
限幅消抖滤波法这个方法对于取值准确性比较好,建议还是整合一下程序

使用特权

评论回复
8
AdaMaYun| | 2023-7-26 13:10 | 只看该作者
限幅滤波法如何抑制周期性干扰

使用特权

评论回复
9
modesty3jonah| | 2023-8-9 15:11 | 只看该作者
移动平均(Moving Average):通过计算一段时间内数据的平均值来过滤数据。
指数加权移动平均(Exponential Weighted Moving Average):通过指数加权的方式计算一段时间内数据的平均值来过滤数据。
线性插值(Linear Interpolation):通过在数据点之间插入线性插值来平滑数据。
指数加权线性插值(Exponential Weighted Linear Interpolation):通过指数加权的方式在数据点之间插入线性插值来平滑数据。
均方误差(Mean Square Error):通过计算数据点与其真实值之间的均方误差来过滤数据。
最小二乘(Least Squares):通过最小化数据点与其真实值之间的平方和来过滤数据。
最大似然(Maximum Likelihood):通过最大化数据点与其真实值之间的似然函数来过滤数据。
卡尔曼滤波(Kalman Filter):通过线性系统理论和概率统计理论来估计数据的真实值和测量噪声。
自适应卡尔曼滤波(Adaptive Kalman Filter):通过自适应地调整卡尔曼滤波器的参数来提高滤波器的性能。
Butterworth滤波器:通过设计具有特定滤波特性的滤波器来过滤数据。

使用特权

评论回复
10
maudlu| | 2023-8-9 16:21 | 只看该作者
根据输入信号的特性和所需的滤波效果,选择适合的滤波器类型

使用特权

评论回复
11
plsbackup| | 2023-8-9 21:47 | 只看该作者
滤波器的阶数决定了滤波器的复杂度和性能。较高的阶数可以提供更陡峭的滤波特性,但也会增加计算复杂度。

使用特权

评论回复
12
pmp| | 2023-8-14 08:51 | 只看该作者
截止频率是滤波器的重要参数,它决定了滤波器对信号频率的响应。根据应用需求,选择适当的截止频率以满足信号处理的要求。

使用特权

评论回复
13
febgxu| | 2023-8-14 09:02 | 只看该作者
使用滤波器后,应该对滤波后的信号进行性能评估,例如频域和时域分析。如果滤波效果不理想,可以尝试调整滤波器参数或使用其他滤波算法进行优化。

使用特权

评论回复
14
adolphcocker| | 2023-8-14 09:13 | 只看该作者
这些算法可以根据具体的应用场景和需求选择使用。

使用特权

评论回复
15
jkl21| | 2023-8-14 14:14 | 只看该作者
考虑滤波算法的实时性和延迟。              

使用特权

评论回复
16
chenci2013| | 2023-8-14 14:58 | 只看该作者
需要避免使用过于平滑的滤波器,以免丧失有用的信息。

使用特权

评论回复
17
mmbs| | 2023-8-14 16:30 | 只看该作者
确定所需的滤波器阶数,以平衡滤波效果和计算复杂度。阶数越高,滤波效果越好,但计算复杂度也会增加。

使用特权

评论回复
18
qiufengsd| | 2023-8-14 16:50 | 只看该作者
过高或过低的采样频率可能会导致滤波器性能下降或信息丢失。

使用特权

评论回复
19
eefas| | 2023-8-14 17:37 | 只看该作者
需要根据实际应用场景和滤波目标选择合适的滤波器,例如低通滤波器、高通滤波器、带通滤波器、陷波器等。

使用特权

评论回复
20
houjiakai| | 2023-8-14 19:05 | 只看该作者
根据需要滤除的噪声类型和保留的信号特征,选择合适的滤波器类型。不同滤波器适用于不同的应用场景,例如低通滤波器适用于平滑信号,高通滤波器适用于去除直流偏置等。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

1081

帖子

1

粉丝