单片机的滤波算法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/huolu0602/article/details/102488612

   关于滤波,我们常常听说有滤波电路、滤波器、滤波对抗器等等,这些都是有效的解决单片机的信号干扰问题,都是从硬件上进行滤波处理,从而增加检测值的精确度。下面我们来简单介绍一下软件是如何进行单片机滤波的,这就要引出我们今天的主题--滤波算法。

  滤波算法是什么呢?既然是算法,那就要运用到数学公式了,即通过算法将我们检测到误差大的数据进行处理,从而达到滤波作用。下面通过例子来讲述几种常用的滤波算法。

  假设向8位AD中读取数据,AD获取程序为getad(),采用滤波算法增加数据精度。

1.限幅滤波(程序判断滤波)

   原理:根据经验确定两次采样之间所允许的最大偏差值(假定为MAX),每次检测到新值(new_value)时作出判断。若差值在允许的最大偏差之内,则当前值为有效值,反之,则用上次值(value)替代当前值。

  优势:能克服偶然因素引起的脉冲干扰。

代码示范:

#define MAX 10
char value;
char LimitFileter()
{
char new_value;
new_value = getad();
if((new_value-value>MAX) || (value-new_value>MAX))
  return value;
return new_value;
}

2.中值滤波法

   原理:连续采样奇数次(N),获取奇数个数值,并按照大小从左到右进行排序,取中间值为本次有效值。

   优势:能够有效克服偶然因素引起的波动干扰,对于变化缓慢的参数测试有良好的滤波效果。

代码示范:

#define N 11
char MedFilter()
{
char value_buf[N];
char count,i,j,temp;
for ( count = 0; count < N; count++)
{
value_buf[count] = getad();
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.算术平均滤波

   原理:连续取N个采样值进行平均运算,N值较大时,信号平滑度较高,灵敏度较低。N值较小时,信号平滑度较低,灵敏度较  高。

   优势:适用于一般具有随机干扰的信号进行滤波。

代码示范:

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

4.递推平均滤波法

   原理:将连续采样N个数据看成一个队列,队列长度固定为N。每次采样到一个新数据放入队尾,并向前递推一位数据,舍弃掉 原来的队头(先进先出原则)。再将队列中N个数据进行算术平均运算。

   优势:对周期性干扰有良好的抑制作用,适用于高频振荡的系统。

代码示范:

char value_buff[N];
char i=0;
char RecAveFileter()
{
char count;
int sum=0;
value_buff[i++]=getdata();
if(i==N)
i=0;
for(count=0;count<N;count++)
sum+=value_buff[count];
return (char)(sum/N);
}

5.中位值平均滤波法

   原理:即结合中位值滤波和算术平均滤波,连续采集N个数据,去掉一个最大值和一个最小值,然后计算剩下的N-2个数据的算术平均值。

   优势:对于偶然出现的脉冲性干扰,可以消除由于脉冲干扰而引起的采值偏差。

代码示范:

#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] = getad();
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));
}

6.限幅平均滤波

   原理:即结合限幅滤波和递推平均滤波。每次采样到新数据进行限幅处理,再将有效值添加到队列进行递推平均滤波处理。

   优势:能克服偶然因素引起的脉冲干扰,对周期性干扰有良好的抑制作用。

代码示范:

#define MAX 10
#define N 12

char value;
char LimitFileter()
{
char new_value;
new_value = getad();
if((new_value-value>MAX) || (value-new_value>MAX))
  return value;
return new_value;
}
char AverageFileter()
{
int sum = 0;
for ( count=0;count<N;count++)
{
sum + = LimitFileter();
delay();
}
return (char)(sum/N);
}

7.一阶滞后滤波

   原理:取a = 0~1,滤波结果 = (1-a)*本次采样值+a*上次滤波结果。

   优势:对周期性干扰具有良好的抑制作用,适用于波动频率较高的场合。

代码示范:

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

8.加权递推平均滤波

  原理:在递推平均滤波法上进行的改进,不同时刻的数据加以不同的权,越接近现时刻的数据,权取得越大。新采样值的权系数越大,灵敏度越高,但平滑度就越低。

  优势:适用于周期较短的系统,有较大纯滞后时间常数的对象。

代码示范:

#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 WeiRecAveFileter()
{
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.消抖滤波

  原理:设置一个滤波计数器,每次采样值与当前有效值比较,如果相同,则计数器清零,如果大于或小于当前有效值,则计数器加1,并判断计数器是否溢出,如果溢出,则将本次值替换当前有效值,并将计数器清零。

  优势:对于变化缓慢的被测参数有较好的滤波效果,可以避免在临界值附近控制器的反复开/关跳动或显示器上数值的抖动。

代码示范:

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

10.限幅消抖滤波

    原理:先限幅,后消抖。

    优势:改进了消抖滤波中的一些缺陷,避免将干扰值导入系统。

代码示范:

#define MAX 10
#define N 12
char value;
char LimitFileter()
{
char new_value;
new_value = getad();
if((new_value-value>MAX) || (value-new_value>MAX))
  return value;
return new_value;
}
char LimDitFileter()
{
char count=0;
char new_value;
new_value = LimitFileter();
while (value !=new_value);
{
count++;
if (count>=N) return new_value;
delay();
new_value = get_ad();
}
return value;
}

以上就是个人总结的10个常用的滤波算法,根据不同的事件,灵活运用这10种算法,能够减少误差数据的产生,从而提高自己的代码质量。

猜你喜欢

转载自blog.csdn.net/huolu0602/article/details/102488612
今日推荐