滤波器开发之一:基于算数平均的平滑滤波器_算术平均掩模_foxclever的博客-程序员秘密

技术标签: 数字滤波器  算法  算术平均  

信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望。环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波器的用武之地。这里我们讨论的主要是软件实现的数字滤波器,这一篇我们就来讨论基于递推算术平均算法的平滑滤波器。

1、问题的提出

在我们通过AD采集获取数据时,不可避免会受到干扰信号的影响,而且很多时候我们希望尽可能的将这种影响减到最小。为实现这一目的,人们想了很多办法,有硬件方面的,也有软件方面的。在硬件难以改变或者软件能够达到相应效果时,我们一般采用软件方法来实现,通常称之为数字滤波。

实现数字滤波的算法有很多种,根据不同的应用需求我们可以选择不同滤波算法来实现。对于一般的AD采集最常见的是周期性干扰和随机性噪声,对于此类干扰一般采用算术平均的方法就能得到比较理想的效果。其计算公式如下:

使用简单的算术平均值算法虽然能够实现滤波,但在一些情况下有一个问题可能会有影响,那就是当做算术平均的数量比较大时会出现曲线并不是十分平滑的情况。这很容易理解,因为一次采集n个数做算术平均得到一个结果,当n越大则间隔的时间就越长。为了解决这一问题我们并不是甲酸完后就将n个数同时丢弃,而是将最早的数丢弃并采用最新采集的数代替,这就是所谓的递推算术平均算法。但其计算公式并没有发生变化。

2、算法设计

我们如何实现这种递推方式的平滑滤波器呢?首先我们来看一看一般的算术平均算法是如何实现的。算术平均算法就是采集N个数然后对这N个数取平均值作为最终的结果。我们将这些数的序列记录如下:

这N个数计算完毕后就会丢弃,然后再采集N个数。很显然,如果N值较大,采集所耗费的时间跨度就会比较长,数据看起来可能就并不那么平滑,而且数据的输出速率会慢很多,也不能展示数据的变化过程。而递推平均算法则不存在这些问题。同样是一个长度为N的数据队列,但没采样一次数据,我们就用最新的数据替换掉最久的数据,并输出算术平均值。我们将这些数的序列记录如下:

这样每采样一个数据我们都会输出一个滤波后的数据,而不是等待采集N个数据后才会输出,这样既可保证数据的连续性也可达到平滑滤波的效果。

3、代码实现

我们分析了平滑滤波器的实现算法,接下来我们来讨论如何实现这一滤波器。首先我们将滤波器作为一个对象,我们实现的滤波器操作也将面向这一对象来实现。那么我们实现对滤波器对象的操作需要确定该对象的那些属性呢?

作为滤波器肯定需要获取当前采集到的数据值;同时我们为了实现对N个数据的递推平均就需要有一个存储这N个数的队列;我们需要记录最新的数据硬件存储到哪个位置就需要一个位置指针;同时我们也需要知道N的大小,所以我们将它们都定义滤波器对象的属性。平滑滤波的过程必须要计算算术平均值,而递推算术平均则是在每次采集一个数据之时都计算平均值,可是如果N值较大时,就会存在大量的重复计算。我们考虑到上一次采样的平均值已经得到,我们将其记录下来的话就可以用最新采集的数据替换掉最老的数据,从而得到新的平均值,所以我们将上一时间的输出值记录下来作为对象的一个属性。根据以上分析我们可定义滤波器对象类型为:

/*定义平滑滤波对象类型*/
typedef struct FilterObject{
  float newValue;       //最新测量值
  float lastValue;      //上一个输出值
  float *buffer;        //数据缓存区
  int16_t position;    //写操作位置指针
  uint16_t bufCount;    //滤波的数量
}FilterObjectType;

我们获得了滤波器对象,接下来我们基于该对象实现平滑滤波器。对于平滑滤波自然是要采取计算平均值的过程。但我们使用了循环队列的操作方式,所以判断新数据指针当前所处的位置。具体实现如下:

/*平滑滤波处理函数,返回滤波后的值 */
float SmoothingFilter(FilterObjectType *filter)
{
  float result=0.0;
 
  if(filter->position<0)
  {
    for(int i=0;i<filter->bufCount;i++)
    {
      filter->buffer[i]=filter->newValue;
    }
    filter->position=0;
    filter->lastValue=filter->newValue;
  }
 
  if(filter->position>=filter->bufCount)
  {
    filter->position=0;
  }
 
  result=filter->lastValue-filter->buffer[filter->position]/filter->bufCount;
 
  result=result+filter->newValue/filter->bufCount;
 
  filter->buffer[filter->position++]=filter->newValue;
 
  filter->lastValue=result;
 
  filter->newValue=0.0;
  return result;
}

4、应用总结

我们实现了基于算术平均的平滑滤波器,对于消除周期性干扰有良好的抑制作用,对于一般具有随机干扰的信号也能进行滤波。对于数据平滑度较高有不错的效果。

但是这种滤波方式有几点是需要注意的。第一,它的灵敏度低。这很好理解,因为我们总是对N个数采取平均值算法,所以新数据对平均值的影响有限,数据变化不明显,响应较慢,而且N越大越明显。第二.对偶然出现的脉冲性干扰的抑制作用较差。第三,不易消除由于脉冲干扰所引起的采样值偏差。所以这种滤波器并不适用于脉冲干扰比较严重的场合。

欢迎关注:

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

智能推荐

本机如何远程开启别的计算机服务,如何远程开启对方的remoteregistry服务_weixin_39667509的博客-程序员秘密

在Windows 2003操作系统中,有两个默认启动的服务,Terminal Services与Remote Registry服务,本文通过两个实例,谈一下这两个服务可能给计算机用户带来的安全隐患。首先列举一下两个服务的作用:Terminal Services服务,允许用户以交互方式连接到远程计算机。而Remote Registry服务可以使远程用户能修改此计算机上的注册表设置。一、 ...

项目部署--我爱起名网平台搭建学习研究(含php源码,亲测有效)_起名网源码_刘帅0952的博客-程序员秘密

30年八字起名经验,起名专业权威,已为近十万名宝宝起名,好评率高达99.9%平台的搭建先看效果图

C基础入门 - 第一章 - C语言绪言_weixin_30610755的博客-程序员秘密

第1章 C语言绪言 1.1 C语言概述  1.1.1 C语言世界   1.1.2 C语言学习, 能当饭吃吗  1.2 开发环境构建   1.2.1 visual studio安装使用   1.2.2 visual studio无脑调试  1.3 请记住 hello world   1.3.1 注释详解  1.3.2 也许这一章是最难的 1.4 扩展阅读...

tomcat8.0连mysql数据库_Tomcat的服务器配置连接sqlserver和mysql数据库_李诗旸的博客-程序员秘密

Tomcat 的服务器配置一、tomcat的安装1、jdk的安装,建议选用最新的JDK 1.6里面包括JDK还有JRE1.6。2、安装tomcat,没有什么好说的,值得一说的是服务器虚拟机的选择。一定要选择jdk1.6.0\jre\bin\server下的jvm.dll文件,不要选择jre1.6.0\bin\client 下的jvm.dll二、配置web文件夹虚拟目录,应该指出的是每一个web...

PXE安装ESXi6_weixin_34067980的博客-程序员秘密

1.安装dhcp、tftp-server、syslinux、xinetd。yuminstalldhcptftp-serversyslinuxxinetd12.挂载ESXi ISO到/mntmount/dev/cdrom/mnt13.修改dhcpd.confddns-update-styleinterim;allowbooting;allowbootp;...

随便推点

数据库 - PostgreSQL - 常用命令_爱吃烤面筋的鱼的博客-程序员秘密

https://blog.csdn.net/u010856284/article/details/70142810连接数据库, 默认的用户和数据库是postgrespsql -U user -d dbname切换数据库,相当于mysql的use dbname\c dbname列举数据库,相当于mysql的show databases\l列举表,相当于mysql的show tabl...

QEMU-KVM无法启动_密斯特羅的博客-程序员秘密

今天在把QEMU-KVM上的一个虚拟机Shutdown后总是无法启动,使用virt-manager管理工具启动时总是导致该工具意外终止,如果是使用virsh命令行管理工具启动时总是报错:[[email protected] ~]# virsh start oneracvmerror: Failed to start domain oneracvmerror: Timed out during opera

如何在终端编辑文件并保存_deepin终端编辑后如何保存_未名编程的博客-程序员秘密

1.这个时候如果想修改这个文件的内容,按下间键盘上的’i’键,最下方就会变成INSERT,就可以修改了2.保存 写个echo的代码进行保存 Esc+:+wq 这个是保存,回车保存(有可能要在后面输入感叹号)...

win2008磁盘管理_Dvi23d的博客-程序员秘密

先打开win2008转化为动态后联机,初始化磁盘才可新建卷简单卷建立其他如上跨区卷:多个磁盘共同形成的区带区卷:多个磁盘分相同空间,使一个文件在多个盘同时写入与读取,速度加快(raid0)镜像卷:50%利用率,一半当备份盘(raid1)raid5:所有磁盘容量必须一样大,当容量不同时,会以最小的容量为准。 最好硬盘转速一样,否则会影响性能,而且可用空间=磁盘数n-1,Raid 5 没有独立的奇偶校验盘,所有校验信息分散放在所有磁盘上, 只占用...

Spark Streaming应用_风度不想说话的博客-程序员秘密

SparkStreaming 的用途(流式计算的应用场景) 1. 实时统计,累加(淘宝的大屏) kafka + sparkstreaming(updateStatByKey,mapwithState) 2. 实时统计,最近一段时间指标 实时查看最近一个小时之内的用户点击量,各省或者重点城市(window窗口)工作原理:Spark Core RDD sc =

海思麒麟芯片详细参数全集_麒麟a1参数_szx940213的博客-程序员秘密

海思麒麟芯片有那些?规格是怎么样的?华为海思半导体(Hisilicon)麒麟A1(穿戴设备):http://bbs.16rd.com/thread-481026-1-1.html华为海思半导体(Hisilicon)麒麟Kirin620(麒麟620)http://bbs.16rd.com/thread-481860-1-1.html华为海思半导体(Hisilicon)麒麟Kirin650(麒麟650)http://bbs.16rd.com/citiao-xinpian-kirin650.html华为海

推荐文章

热门文章

相关标签