在嵌入式开发程序中涉及数据采样如传感器采样,AD采样等如果直接读取信号后,将信号值直接参与后续逻辑处理,若程序无软件滤波,会导致静态或者动态采样时:
1、信号曲线相对没有那么平滑。
2、同时可能存在脉冲干扰导致逻辑判断错误。
在信号处理系统中,输入信号通常含有各种噪声和干扰。为对信号进行准确的测量和控制,必须削弱或滤除被测信号中的噪声和干扰。因此在工程应用需要使用软件滤波,软件滤波也称数字滤波,是通过一定的算法削弱噪声的影响。在实际的开发过程中使用了滑动窗口滤波算法来对传感器的数据采样进行滤波处理。
1、建立采样窗口和滤波窗口,自定义各窗口长度大小。
2、当数据样本点数未填满采样窗口,对采样窗口内的数据累加做平均值计算。
例如此时采样窗口内数据采样点只有4个,小于定义的采样窗口长度,则将4个值累加后再做平均值计算。
3、当数据样本点数已填满采样窗口,进行冒泡排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加做平均值运算。
例如此时采样窗口内数据采样点有7个,已填满定义长度大小的采样窗口,则分别去除自定义的1个最大值和1个最小值后,对剩余滤波窗口内的数据累加后再做平均值计算。
4、新的数据样本到来,移除采样窗口中时间最早的点(FIFO),重复上述3操作。
1、经过滤波处理后,滤除了噪声干扰,数据波动稳定平滑。
2、每采样一个新数据,就将最早采集的那个数据丢掉,因此每进行一次采样,就可计算出一个新的平均值,从而加快了数据处理的速度。
3、可以根据实时性的要求和需要滤波后数据的平滑度来设置采样窗口和滤波窗口的大小。
4、当采样的数据量非常大时,这时的采样窗口会设置很大,那么窗口需要消耗一定的内存空间。
5、当采样数据越多,数据实时性越差,当数据突然发生较大变化时,不能被立刻检测到,无法及时处理突发事件。
1、在工程根目录下新建filter文件夹,将源文件filter.cpp和头filter.h放在文件夹中供修改调用。
2、头文件:
(1)定义滤波算法函数中的可修改宏值;
(2)声明定义的滤波函数模板;
(3)使用extern的方式声明实例化后的模板函数。
3、源文件:
(1)定义需要使用滤波算法的函数模板;
(2)在定义的函数模板后进行函数实例化操作,通过这样的方法实现具体的模板函数。
1 #ifndef _FILTER_H_
2 #define _FILTER_H_
3
4 #define MAX_SENSOR_NUM 9 //使用滤波时的传感器数量
5 #define MAX_DATA_NUM 9 //最大采样点数量,即采样窗口长度
6 #define WINDOW_DATA_NUM 5 //滤波窗口长度
7 //去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小
8 #define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
9
10 //extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
11
12 //声明定义的函数模板
13 template<typename InType> InType Filter_SlidingWindowAvg(int index, InType data);
14 //使用extern的方式声明实例化后的模板函数,根据实际需要自定义数据类型
15 extern template short Filter_SlidingWindowAvg(int index, short data);
16 extern template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);
17
18 #endif
1 #include <algorithm>
2 #include "Filter.h"
3
4 using namespace std;
5 //定义各个传感器的数据采样点列表
6 double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
7 //滑窗均值滤波,使用函数模板可用于适配不同数据类型的采样点
8 template<typename InType>
9 InType Filter_SlidingWindowAvg(int index, InType data)
10 {
11 static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
12 int i;
13 double sum = 0;
14 double out = 0;
15 double array[MAX_DATA_NUM] = {0};
16
17 //数据采样点在采样窗口内移动,FIFO操作
18 for(i = MAX_DATA_NUM - 2; i >= 0; i--)
19 m_dataList[index][i+1] = m_dataList[index][i];
20
21 m_dataList[index][0] = data;
22 //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算
23 if(dataNum[index] < MAX_DATA_NUM)
24 {
25 dataNum[index]++;
26 for(i = 0; i < dataNum[index]; i++)
27 {
28 sum += m_dataList[index][i];
29 }
30 out = sum / dataNum[index];
31 }
32 //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进
33 //行平均值运算
34 else
35 {
36 for(i = 0; i < MAX_DATA_NUM; i++)
37 {
38 array[i] = m_dataList[index][i];
39 }
40 //利用C++标准库的sort函数进行排序,这里使用默认的升序
41 sort(array, array + MAX_DATA_NUM);
42
43 int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
44
45 for(i = start; i < start + WINDOW_DATA_NUM; i++)
46 {
47 sum += array[i];
48 }
49 out = sum / WINDOW_DATA_NUM;
50 }
51 return out;
52 }
53
54 //对函数模板进行函数实例化操作,根据实际需要自定义数据类型
55 template short Filter_SlidingWindowAvg(int index, short data);
56 template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);
1、在工程根目录下新建filter文件夹,将头filter.h和源文件filter.c放在文件夹中供修改调用。
2、头文件:
(1)定义滤波算法函数中的可修改宏值;
(2)声明定义的滤波算法函数;
3、源文件:
(1)定义冒泡排序功能函数;
(2)定义滤波算法功能函数。
1 #ifndef _FILTER_H_
2 #define _FILTER_H_
3
4 #define MAX_SENSOR_NUM 9 //使用滤波时的传感器数量
5 #define MAX_DATA_NUM 9 //最大采样点数量,即采样窗口长度
6 #define WINDOW_DATA_NUM 5 //滤波窗口长度
7 //去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小
8 #define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
9
10 //extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
11
12 //声明定义的函数
13 double Filter_SlidingWindowAvg(int index, double data);
14
15 #endif
1 #include "Filter.h"
2
3 //定义各个传感器的数据采样点列表
4 double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
5
6 //冒泡排序
7 void BubbleSort(int array[], int len)
8 {
9 int temp;
10 //外层循环控制排序的趟数,n个元素排序需要循环n-1次
11 for(int i=0; i<len-1; i++)
12 {
13 //内层循环控制比较的次数,n个元素第i趟比较n-i次
14 for(int j=0; j<len-1-i; j++)
15 {
16 //比较相邻的元素大小 目的:将最大的元素选出到移动到最后
17 if(array[j] > array[j+1])
18 {
19 temp = array[j];
20 array[j] = array[j+1];
21 array[j+1] = temp;
22 }
23 }
24 }
25 }
26
27 //滑窗均值滤波,这里采样点data数据类型和滤波后返回值数据类型都是double,实际使用可根据需要定义
28 //其他数据类型
29 double Filter_SlidingWindowAvg(int index, double data)
30 {
31 static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
32 int i;
33 double sum = 0;
34 double out = 0;
35 double array[MAX_DATA_NUM] = {0};
36
37 //数据采样点在采样窗口内移动,FIFO操作
38 for(i = MAX_DATA_NUM - 2; i >= 0; i--)
39 m_dataList[index][i+1] = m_dataList[index][i];
40
41 m_dataList[index][0] = data;
42 //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算
43 if(dataNum[index] < MAX_DATA_NUM)
44 {
45 dataNum[index]++;
46 for(i = 0; i < dataNum[index]; i++)
47 {
48 sum += m_dataList[index][i];
49 }
50 out = sum / dataNum[index];
51 }
52 //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进
53 //行平均值运算
54 else
55 {
56 for(i = 0; i < MAX_DATA_NUM; i++)
57 {
58 array[i] = m_dataList[index][i];
59 }
60 //调用冒泡排序函数
61 BubbleSort(array, MAX_DATA_NUM);
62
63 int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
64
65 for(i = start; i < start + WINDOW_DATA_NUM; i++)
66 {
67 sum += array[i];
68 }
69 out = sum / WINDOW_DATA_NUM;
70 }
71 return out;
72 }

如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来