软件滤波程序总结

目录

一.滤波种类

1. 1 限幅滤波

优点:克服偶然因素引入的脉冲干扰
缺点:周期性干扰无法去除、平滑度差

1.2 中值滤波

优点:克服偶然因素引起的干扰,对缓慢变化的被测量效果良好
缺点:对流量、速度等快速变化参数不宜采用,对较大的N占用RAM和处理器较多

1.3 算术平均滤波

优点:可对具有随机干扰的信号进行处理,这类信号一般具有一个平均值,信号会在某一数值范围附近上下波动
缺点:不适用于高速数据应用,灵敏程度与平滑程度与N有关,RAM和处理速度由N值决定

1.4 递推平均滤波

优点:对周期性干扰有良好的抑制作用,平滑度高
缺点:灵敏度较低,对偶发脉冲干扰抑制作用较弱,不易消除由脉冲干扰引起的采样值的偏差,费RAM

1.5 中值平均滤波

优点:综合了两种滤波方法的有点,抑制脉冲干扰
缺点:只适合用于速度较慢的场合,RAM由N决定

1.6 限幅平均滤波

优点:抑制偶发脉冲干扰,消除由此引入的采样的偏差
缺点:不适合高速信号的处理,RAM资源由N决定

1.7 一阶滞后滤波

优点:适用于波动频率较高的场合,对周期性干扰具有良好的抑制作用,运算量不大
缺点:造成相位滞后,灵敏度低,不能消除频率高于采样率1/2的干扰信号

1.8 加权递推平均滤波

优点:适用于较大纯滞后时间常数的对象和采样周期较短的系统
缺点:对纯滞后时间常数较小,采样周期较长,变化缓慢的信号不能迅速反应系统当前所受干扰严重程度,滤波效果差

1.9 消抖滤波

优点:对变化缓慢的被测参数有较好的滤波效果,可避免在临界值附近控制器的反复开、关跳动或显示器上数值的抖动
缺点:对快速变化的参数不宜,若计数器溢出的那一次采样到的正好是干扰,则干扰会被当成有效值导入系统

1.10 限幅消抖滤波

优点:限幅和消抖的优点,改进了消抖滤波的缺陷,避免将干扰值导入系统
缺点:对于快速变化的参数不宜使用

二.滤波介绍

2.1限幅滤波

根据采集的数据,若当前采集值较前一次采集值相差维持在一定的偏差内,则将
每次采集到的数据和前一次的数据进行比较,若其差的绝对值大于某一特定值,则认为是干扰数据,继续输出上一次的数据,反之 ,则认为数据有效

代码:

#define uint unsigned int
#define  uchar unsigned char

uchar A[]={100,110,106 ,108,130,100,100,100,101,102} ;
uchar get_ad_val()
{
    uchar ad_val;
    return ad_val; 
}

/*限幅滤波参考程序*/
#define Amp 10
uchar value
uchar Amplitude_Fliter()
{
    uchar new_value;
    new_value=get_ad_val();
    if((new_value-value )>Amp || (value-new_value) >Amp)
        return value;        //其余情况,本次值无效 
    return new_value;       //若本次与上次之差<=Amp,本次无效 
} 

2.2中位值滤波

进行连续的N此采样,把N次采样的值按照大小进行排列,取其中间一个值(N为奇数)或中间两个值的平均值(N为偶数)作为中值,N的大小决定了平滑程度和灵敏程度

代码:

/*中值滤波参考程序*/
#define N 11
uchar Median_Fliter()
{
    uchar value[N];
    uchar count,i,j,temp;
    for(count=0;count<N;count++)//获取采样值
        value[count]=get_ad_val();
    for(j=0;j<N-1;j++)          //冒泡排序法
    {
        for(i=0;i<N-j;i++) //       { //            if(value[i]>value[i+1])
            {
                temp=value[i];
                value[i]=value[i+1];
                value[i+1]=temp;
            }
        }
    }
    return value[(N+1)/2];
}

2.3算术平均滤波

过程与中值滤波类似,但是取的是算术平均值

代码:

/*算术平均滤波*/
#define N 12
uchar Aver_Fliter()
{
    uchar count;
    int sum=0;
    for(count=0;count<N;count++)
    {
        sum+=get_ad_val();
    }   
    return (uchar)(sum/N);
}

2.4递推平均滤波(滑动平均滤波)

N个采样序列设为一个FIFO(先入先出)队列,每次采样值加入队列尾部,最旧的值出队列并舍弃,每次对队列内现有的元素取平均值作为此次采样值,队列的长度是一定的使用时,存储空间本身应预先存有一定量的(N)数据

代码:

/*递推平均滤波**/
#define N 12
uchar value[N];
uchar i=0;
uchar Raver_Fliter()
{
        uchar count;
        int sum=0;
        value[i++]=get_ad_val();
        if(i==N)i=0;//保证FIFO
        for(count=0;count<N;count++)
        sum+=value[count]; 
        return (uchar)(sum/N);
}

2.5中值平均滤波(防脉冲干扰平均滤波)

中值滤波和算术平均滤波的思想相结合,采N个数据,去掉一个最大值,去掉一个最小值,求剩下的数据的平均值作为采样值

代码:'

/*中值平均滤波*/
#define N 12
uchar Median_Avr_Fliter()
{
    uchar count,i,j,temp;
    uchar value[N];
    int sum=0;
    for(count=0;count<N;count++)
        value[count]=get_ad_val();
    for(j=0;j<N-1;j++)//冒泡排序,也可以换成其他比较大小的方式
    {
        for(i=0;i<N-j;i++)
        {
            temp=value[i];
            value[i]=value[i+1];
            value[i+1]=temp;
        }
    }
    for(count=1;count<N-1;count++)
        sum+=value[count];
    return (uchar)(sum/(N-2));      
}

2.6限幅平均滤波

限幅滤波+递推平均滤波,每次采样得到的数据先进行限幅处理,再送入队列进行平均滤波处理

代码:

 /*限幅平均滤波*/
 #define N 12
 #define Amp 10 
 uchar value[N]
 uchar i=0;
 uchar value;
 uchar Amplitude_Fliter()
 {
    uchar new_value;
    new_value=get_ad_val();
    if(new_value-value>Amp ||(value-new_value)>Amp)
        return value;
    return new_value;
 } 

 // 调用了限幅滤波函数 
 uchar Raver_Fliter()
 {
    uchar count;
    int sum=0;
    value[i++]=Amplitude_Fliter();
    if(i==N) I=0;  //保证FIFO;
     for(count=0;count<N;count++)
        sum+=value[count];
    return (uchar) (sum/N); 

 } 

2.7一阶滞后滤波

取一个比例常数k(0<k<1),本次输出的结果=k本次采样值+(1-k)前一次的输出值,输出由本次和前一次共同决定,影响程度由k决定,阶数可扩展。

代码:

/*一阶滞后滤波*/
#define a 50
uchar value;
uchar Delay_Fliter()
{
    uchar new_value;
    new_value=get_ad_val();
    return (uchar)( ( (100-a)*value+a*new_value) /100);
}

2.8加强递归平均滤波

对递归平均滤波的改进,不同时刻采样数据具有不同的权重。通常是距离当前时刻越近,权重越大,给新的采样值的权重越大,灵敏度越高,信号平滑度越低.

代码:

/*加权递归平均滤波*/
#define N 12
uchar code coe[N]={1,2,3,4,5,6,7,8,9,10,11,12};
uchar code sum_coe=78;
uchar Weighting_Fliter()
{
    uchar count;
    uchar value[N];
    int sum=0;
    for(count=0;count<N;count++)
        value[count]=get_ad_val();
    for(count=0;count<N;count++) 
        sum+=value[count]*coe[count];
    return (uchar)(sum/sum_coe);
}

2.9消抖滤波

设置一个滤波计数器,将每次采样值和当前的有效值进行比较,若采样值等于当前有效值,则计数器清零;反之,计数器加1,并判断滤波计数器是否达到设置的溢出上限,若计数器溢出,则将本次的值替换当前有效值,并清零计数器

代码:

/*消抖滤波*/
#define N 12
uchar value;
uchar EL_Fliter()
{
    uchar count=0;
    uchar new_value;
    new_value=get_ad_val();
    while(value!=new_value)
    {
        count++;
        if(count>=N)return new_value;
        new_value=get_ad_val();
    }
    return value;
}

2.10限幅消抖滤波

限幅滤波+消抖滤波,先限幅,后消抖

代码:

*限幅消抖滤波参考程序*/
/*先限幅,后消抖*/
#define Amp 10
#define N 12
uchar value;
uchar Amplitude_Fliter()
{
     uchar new_value;
     new_value=get_ad_val();
     if((new_value-value>Amp)||(value-new_value>Amp))
     return value; //其余情况下,本次值无效
     return new_value; //若本次与上次之差<=Amp,本次值有效
}
//调用 限幅滤波函数Amplitude_Fliter()
uchar EL_Fliter()
{
    uchar count=0;
    uchar new_value;
    new_value=Amplitude_Fliter()
    while(value!=new_value)
    {
        count++;
        if(count>=N)return new_value;
        new_value=Amplitude_Fliter()
    }
    return value;
}
打赏作者