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

1、问题的提出

我们已经实现了基于算术平均的递推算术平均滤波器。虽然它对周期性干扰和高频的干扰都有一定的效果,但是对于这种滤波器其灵敏度和滤波效果很难同时达到较好的效果。一般来说,当N值较小时,灵敏度会增高但滤波效果则不太理想;当N值较大时,滤波效果会比较好,但灵敏度会受到影响。所以我们希望能找到一种方法,让灵敏度和滤波效果都能有较好的表现。

关于这个问题,我们先来分析一下。一般来说,不管是周期性干扰还是噪声干扰都是在一定的范围内对数据造成影响。不会出现很大幅度的数据差异。基于这一点我们可以考虑对比本次采集与上次输出之间的偏差值,如果偏差值大于一定的限值则我们认为是数据发生了较大变化,远大于干扰造成的影响,干扰可以忽略,所以我们直接对数据进行更新。当数据偏差处于一定的变化范围之内时,我们认为是处于稳定的范围内,这时干扰造成的影响于数据的变化不能忽略,我们需要采用滤波。具体如图所示:

其中HL和LL就是我们之间的范围就是可能干扰不能忽略的范围;而大于HL的部分我们认为采集数据变化远超干扰的影响,忽略干扰提高灵敏度;而小于LL的部分说明干扰造成的影响很小,在允许的误差范围之内或者说在数据的正常波动范围之内,我们也不需要滤波。

我们在数据的变化大于干扰所能引起的数据差异时,选择不滤波而是快速更新数据以提高灵敏度。可是如果有一个偶然的脉冲干扰出现时,这种操作方式则会导致系统失效,所以我们必须引入消抖操作。当连续出现多个值都是大范围变化时,我们认为是数据的正常变化,否则我们认为是偶然的脉冲干扰造成的。

2、算法设计

我们已经描述了在不同的偏差区间对采集数据采取不同处理方式的办法。具体怎么设计这一滤波算法呢?首先我们需要根据经验或者基于对被控对象的判断来确定HL和LL的范围,这样在不同范围内采取不同的处理方式的做法才能达到良好的效果。

我们先来看偏差处于HL和LL之间时该怎么处理。同样需要定义一个长度为N的数据队列。和前一篇中所说的一样,当采集到一个新的数据时,用这个新的数据替换掉最老的数据。并且将数据指针指向下一次需要替换掉的最老数据。然后使用队列中的数据去算术平均值而得到最新的输出数据,具体队列如下:

若是偏差落在大于HL和小于LL的范围内,则不需要滤波,该如何处理呢?我们一样需要数据队列,因为数据随时有可能回归到需要滤波的范围,我们必须每次的更新数据队列即使没有滤波需求。这时的更新数据方式不同,我们将整个队列的数据都替换为新数据,但我们不更新数据指针。输出数据就是本次采集的数据,具体的数据队列如下:

但是偏差落在大于HL和小于LL的范围内并不能直接更新数据队列的全部数据,因为可能是偶然性的脉冲干扰,我们需要作消抖处理。我们判断如果连续多少个的采集数据均落在相应的区间,我们就认为不是偶然的脉冲干扰。这是我们就更新队列的全部数据。

3、代码实现

我们已经设计了带阻区间滤波的相关算法,接下来我们来考虑如何实现这一滤波器。同样的,我们需要定义一个滤波器对象然后基于这一对象实现相应的滤波器操作。

我们先来分析一下,首先滤波器对象需要获取当前采集到的数据值;同时我们为了实现对N个数据的递推平均就需要有一个存储这N个数的队列;我们需要记录最新的数据硬件存储到哪个位置就需要一个位置指针;同时我们也需要知道N的大小,所以我们将它们都定义滤波器对象的属性。平滑滤波的过程必须要计算算术平均值,而递推算术平均则是在每次采集一个数据之时都计算平均值,可是如果N值较大时,就会存在大量的重复计算。我们考虑到上一次采样的平均值已经得到,我们将其记录下来的话就可以用最新采集的数据替换掉最老的数据,从而得到新的平均值,所以我们将上一时间的输出值记录下来作为对象的一个属性。除此之外,我们还需要知道滤波器的限制区间,即HL和LL,所以我们将采集数据所对应的量程范围、上限(HL)、下限(LL)比例均作为对象的属性。同时为了实现消抖,我们需要记录数据大幅变化的持续数及确认消抖的最大数值,这两个也作为对象的属性。根据以上分析我们可定义滤波器对象类型为:

/*定义平滑滤波对象类型*/
typedef struct FilterObject{float newValue;       //最新测量值float lastValue;      //上一个输出值float *buffer;        //数据缓存区int16_t position;    //写操作位置指针uint16_t bufCount;    //滤波的数量uint16_t delayCount;  //延迟计数uint16_t delayLimit;  //延迟限值float rangeLimit;     //量程范围float upperRario;     //比例下限float lowerRatio;     //比例下限
}FilterObjectType;

我们已经获得了滤波器对象,接下来将基于这一对象实现相应的滤波器功能。我们要对比当前的采集值与上一个输出值的比较,根据它们的偏差绝对值来决定采取怎样的处理方式。处理流程如下:

我们通过判断新值与前一个值的偏差来决定所要进行的操作,当偏差处于HL和LL之间时做滤波处理,否则不做滤波处理。根据以上的分析及流程图我们可以设计带阻平滑滤波器的代码为:

/* 带阻平滑滤波器,对指定区间滤波,返回滤波后的值*/
float BandSmoothingFilter(FilterObjectType *filter)
{float result=filter->lastValue;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;}if(fabs(filter->newValue-filter->lastValue)>(filter->rangeLimit*filter->upperRario/100)){filter->delayCount+=1;if(filter->delayCount>=filter->delayLimit){for(int i=0;i<filter->bufCount;i++){filter->buffer[i]=filter->newValue;}filter->position++;result=filter->newValue;filter->delayCount=0;}}else if(fabs(filter->newValue-filter->lastValue)>=(filter->rangeLimit*filter->lowerRatio/100)){result=filter->lastValue-filter->buffer[filter->position]/filter->bufCount;result=result+filter->newValue/filter->bufCount;filter->buffer[filter->position++]=filter->newValue;filter->delayCount=0;}else{filter->delayCount+=1;if(filter->delayCount>=filter->delayLimit){for(int i=0;i<filter->bufCount;i++){filter->buffer[i]=filter->newValue;}filter->position++;result=filter->newValue;filter->delayCount=0;}}filter->lastValue=result;filter->newValue=0.0;return result;
}

4、应用总结

我们实现了基于算术平均的带阻平滑滤波器。该滤波器对周期性干扰和小幅的噪声干扰均有较好的效果。而且通过区间滤波,在数据快速变化时也提高了系统的灵敏度。对于干扰对数据的影响处于一定范围内的系统有很好的效果。

这一滤波器有效的前提是基于干扰的幅度并不是很大的前提而实现的。如果系统存在较大幅度的脉冲干扰,在这种脉冲干扰的出现频率较低时,消抖操作能够很好的去除这种偶然性干扰。但如果出现持续性的高频大幅脉冲干扰,这一滤波器将变得无能为力。

对于限值区间HL和LL的取值一般只能根据采集系统的特点或者工程师的经验来判断,这个取值决定了滤波器的滤波效果。

欢迎关注:

滤波器开发之二:基于算数平均的带阻平滑滤波器相关推荐

  1. 滤波器开发之三:基于算数平均的阶进平滑滤波器

    信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望.环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波 ...

  2. 滤波器开发之一:基于算数平均的平滑滤波器

    信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望.环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波 ...

  3. 方案设计:IPC产品系统设计 - 基于芯片商提供的SDK API开发之二

    方案:安霸.海思(君正.Mstar.安凯) 1.每个模块都是开N(1,2,3...)个pthread线程,线程之间通过生产者,消费者模型(或者进程间通信机制)实现数据同步/异步.通过数据队列缓冲模块数 ...

  4. 基于Nokia S60的游戏开发之二

    把基于Series 60的智能电话作为一种游戏设备 本章将深入研究Series 60和Symbian OS,描述它们作为一个游戏平台的特性.此外,智能电话的需求和限制也将被讨论. 需求 与许多其它用于 ...

  5. linux mp4转h264工具,Linux音视频开发之二:转换YUY2到I420便于压缩成h264

    在用libx264做h264压缩的时候,我们可以通过命令ffmpeg -h encoder=libx264来查看它所支持的输入格式 Encoder libx264 [libx264 H.264 / A ...

  6. unity开发之二:调用电脑外部键盘osk

    今天领导突然说项目需要调用外部键盘很急,然后我匆匆忙忙的写了这个功能,遇到很多蛋疼的地方,记录下来! 第一步: 管理员模式打开unity: 我们需要使用管理员模式打开unity,不然osk.exe是电 ...

  7. Step by Step WebMatrix网站开发之二:使用WebMatrix(1)

    第一次运行WebMatrix会看到如图1所示的窗口. 图1 第一次运行WebMatrix显示的窗口 我的网站 进入"我的网站"可看到自己设计过的网站. 从Web库创建网站 可以从& ...

  8. 指尖下的js ——多触式web前端开发之二:处理简单手势

    这篇文章将描述多触式网页开发中对手势(Gesture)事件的处理.      水果设备中的Gesture,广义的说包括手指点击(click),轻拂(flick),双击(double-click),两只 ...

  9. Step by Step WebMatrix网站开发之二:使用WebMatrix(2)

    上一篇,从Web库创建了一个电子商务的网站.现在回到WebMatrix,看看它有什么功能. 由图1可以看到,WebMatrix主要有3个区域,顶部Ribbon区域,左边是功能区域,右边是信息或编辑区域 ...

最新文章

  1. 领度CEO廖睿:企业社交最大的阻力来自老板
  2. linux用数字方式显示文件权限,全面解析Linux数字文件权限
  3. 文件管理服务器数据库,会博通系统的海量数据库管理策略
  4. 我所碰到的智能手机自动重启的情况
  5. 微软系统修复工具(试用版)
  6. 如何在 ASP.NET Core 中使用 API 分析器
  7. CentOS中通过NAT连接网络
  8. Rtworld目录网全解开源2.0-功能齐全
  9. 发外链网站服务器瘫痪,哪些操作可以导致网站接入瘫痪 - 搜外SEO问答
  10. 算数运算符与关系运算符_Swift进阶三——运算符相关
  11. 【SPOJ5971】LCMSUM
  12. Vue的babel-plugin-transform-remove-console依赖使用方法
  13. VScode 同时开多个窗口
  14. CS229学习笔记(2)多变量线性回归
  15. 从底层来看函数的调用和返回
  16. 电子海图通信态势软件设计与实现
  17. Day2 | SpringBoot电商mall项目学习
  18. android后台定时执行任务,后台执行的定时任务
  19. MRR(Mean Reciprocal Rank)笔记
  20. 德鲁克谈《自我管理》笔记摘要

热门文章

  1. MarkDown/Html在线转换(支持代码高亮,可复制到微信公众号、今日头条)
  2. 知道一个数组某个index对应的值 不知道下标的情况下删除该值
  3. PLECS软件学习使用(一)简单的RLC电路搭建
  4. python中paramiko模块的使用
  5. ceSetThreadPriority设置线程优先级~!
  6. MyEclipse+Tomcat 启动时出现 configuration error occured during startup错误的解决方法
  7. div下图片自适应解决方法
  8. C++调用C#的dll
  9. 【转】近期Coolite控件的技术点总结
  10. Snap Shots 出了新东西