前言
在嵌入式開發程序中涉及數據采樣如傳感器采樣,AD采樣等如果直接讀取信號后,將信號值直接參與后續邏輯處理,若程序無軟件濾波,會導致靜態或者動態采樣時:
1、信號曲線相對沒有那么平滑。
2、同時可能存在脈沖干擾導致邏輯判斷錯誤。
在信號處理系統中,輸入信號通常含有各種噪聲和干擾。 為對信號進行準確的測量和控制,必須削弱或濾除被測信號中的噪聲和干擾。 因此在工程應用需要使用軟件濾波,軟件濾波也稱數字濾波,是通過一定的算法削弱噪聲的影響。 在實際的開發過程中使用了滑動窗口濾波算法來對傳感器的數據采樣進行濾波處理。
一、圖解滑動窗口濾波器的原理
1、建立采樣窗口和濾波窗口,自定義各窗口長度大小。
2、當數據樣本點數未填滿采樣窗口,對采樣窗口內的數據累加做平均值計算。
例如此時采樣窗口內數據采樣點只有4個,小于定義的采樣窗口長度,則將4個值累加后再做平均值計算。
3、當數據樣本點數已填滿采樣窗口,進行冒泡排序后,去除n個最大值及最小值后,對濾波窗口內的數據累加做平均值運算。
例如此時采樣窗口內數據采樣點有7個,已填滿定義長度大小的采樣窗口,則分別去除自定義的1個最大值和1個最小值后,對剩余濾波窗口內的數據累加后再做平均值計算。
4、新的數據樣本到來,移除采樣窗口中時間最早的點(FIFO),重復上述3操作。
二、滑動窗口濾波器的特點
1、經過濾波處理后,濾除了噪聲干擾,數據波動穩定平滑。
2、每采樣一個新數據,就將最早采集的那個數據丟掉,因此每進行一次采樣,就可計算出一個新的平均值,從而加快了數據處理的速度。
3、可以根據實時性的要求和需要濾波后數據的平滑度來設置采樣窗口和濾波窗口的大小。
4、當采樣的數據量非常大時,這時的采樣窗口會設置很大,那么窗口需要消耗一定的內存空間。
5、當采樣數據越多,數據實時性越差,當數據突然發生較大變化時,不能被立刻檢測到,無法及時處理突發事件。
三、滑動窗口濾波器的C++代碼實現
1、基本思路
1、在工程根目錄下新建filter文件夾,將源文件filter.cpp和頭filter.h放在文件夾中供修改調用。
2、頭文件:
(1)定義濾波算法函數中的可修改宏值;
(2)聲明定義的濾波函數模板;
(3)使用extern的方式聲明實例化后的模板函數。
3、源文件:
(1)定義需要使用濾波算法的函數模板;
(2)在定義的函數模板后進行函數實例化操作,通過這樣的方法實現具體的模板函數。
2、頭文件filter.h
#ifndef _FILTER_H_
#define _FILTER_H_
#define MAX_SENSOR_NUM 9 //使用濾波時的傳感器數量
#define MAX_DATA_NUM 9 //最大采樣點數量,即采樣窗口長度
#define WINDOW_DATA_NUM 5 //濾波窗口長度
//去除采樣窗口內最大最小值的數量,這里去除兩個最大和兩個最小
#define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
//extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
//聲明定義的函數模板
template<typename InType> InType Filter_SlidingWindowAvg(int index, InType data);
//使用extern的方式聲明實例化后的模板函數,根據實際需要自定義數據類型
extern template short Filter_SlidingWindowAvg(int index, short data);
extern template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);
#endif
3、源文件filter.cpp
#include
#include "Filter.h"
using namespace std;
//定義各個傳感器的數據采樣點列表
double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
//滑窗均值濾波,使用函數模板可用于適配不同數據類型的采樣點
template<typename InType>
InType Filter_SlidingWindowAvg(int index, InType data)
{
static int dataNum[MAX_SENSOR_NUM] = {0}; //定義記錄傳感器的采樣點個數
int i;
double sum = 0;
double out = 0;
double array[MAX_DATA_NUM] = {0};
//數據采樣點在采樣窗口內移動,FIFO操作
for(i = MAX_DATA_NUM - 2; i >= 0; i--)
m_dataList[index][i+1] = m_dataList[index][i];
m_dataList[index][0] = data;
//數據采樣點數量小于采樣窗口長度,對采樣窗口數據累加后進行平均值運算
if(dataNum[index] < MAX_DATA_NUM)
{
dataNum[index]++;
for(i = 0; i < dataNum[index]; i++)
{
sum += m_dataList[index][i];
}
out = sum / dataNum[index];
}
//數據采樣點已填滿采樣窗口,進行排序后,去除n個最大值及最小值后,對濾波窗口內的數據累加后進
//行平均值運算
else
{
for(i = 0; i < MAX_DATA_NUM; i++)
{
array[i] = m_dataList[index][i];
}
//利用C++標準庫的sort函數進行排序,這里使用默認的升序
sort(array, array + MAX_DATA_NUM);
int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
for(i = start; i < start + WINDOW_DATA_NUM; i++)
{
sum += array[i];
}
out = sum / WINDOW_DATA_NUM;
}
return out;
}
//對函數模板進行函數實例化操作,根據實際需要自定義數據類型
template short Filter_SlidingWindowAvg(int index, short data);
template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);
四、滑動窗口濾波器的C代碼實現
1、基本思路
1、在工程根目錄下新建filter文件夾,將頭filter.h和源文件filter.c放在文件夾中供修改調用。
2、頭文件:
(1)定義濾波算法函數中的可修改宏值;
(2)聲明定義的濾波算法函數;
3、源文件:
(1)定義冒泡排序功能函數;
(2)定義濾波算法功能函數。
2、頭文件filter.h
#ifndef _FILTER_H_
#define _FILTER_H_
#define MAX_SENSOR_NUM 9 //使用濾波時的傳感器數量
#define MAX_DATA_NUM 9 //最大采樣點數量,即采樣窗口長度
#define WINDOW_DATA_NUM 5 //濾波窗口長度
//去除采樣窗口內最大最小值的數量,這里去除兩個最大和兩個最小
#define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)
//extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];
//聲明定義的函數
double Filter_SlidingWindowAvg(int index, double data);
#endif
3、源文件filter.c
#include "Filter.h"
//定義各個傳感器的數據采樣點列表
double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
//冒泡排序
void BubbleSort(int array[], int len)
{
int temp;
//外層循環控制排序的趟數,n個元素排序需要循環n-1次
for(int i=0; i
-
傳感器
+關注
關注
2551文章
51099瀏覽量
753570 -
嵌入式
+關注
關注
5082文章
19126瀏覽量
305194 -
濾波器
+關注
關注
161文章
7817瀏覽量
178126 -
C++
+關注
關注
22文章
2108瀏覽量
73651 -
AD采樣
+關注
關注
0文章
23瀏覽量
15989
發布評論請先 登錄
相關推薦
評論