上次用到了AD转换芯片TLC2543,采样的数据有时候偶尔会有毛刺和噪声,没有打算用硬件滤波的方法,所以参考了很多软件滤波的方案,针对自己设计的系统,决定采用滑动加权滤波的方法。
优点:相比限幅滤波,中值滤波,算数平均滤波,去极值平均滤波,滑动平均滤波等方法,滑动加权滤波方法实时好(相比前几种滤波方式),反应快(相比滑动平均滤波降低滞后效果)等特点。
实现原理:将当前的采样值和之前连续的若干采样值(最近历史采样值)一起进行加权平均,将得到的平均值作为当前有效的值投入使用。由于参与加权平均运算的历史采样个数固定且内容不断更新,相当于一个滑动的时间窗口,故称这种平均滤波方式称为“滑动加权滤波”。
实现方法:1.窗口的大小用采样数据样本个数用m来表示,
2.用数组k[m]给数据样本中的每一个数据分配加权系数,一般给当前的采样数据(即较新的采样数据)分 配以比较大的加权系数,给早期的样本分配较低的权重,这样做是为了降低严重的滞后效果(相比滑动平均滤波),提高系统的反映速度。
#define M 6 //滑动窗口的大小(参与平均运算的采样数据样本的个数)
#define Q 21 //加权系数之和
INT16U history[M]; //加权值的历史记录,一般从左到右逐渐增大
INT8U k[M]={1,2,3,4,5,6}; //加权系数
INT8U p; //采样值的历史记录循环队列的入队指向
INT16U Samp; //滤波算法输出的有效采样值
void TaskSampleCtrl(void *pdata)
{
INT8U i,j;
float s;
for(p=0;p<M;p++)//准备工作,进行M-1次采样,并不进行第M次采样
{
history[p]=SampeAdc();//将采样的数据入队
OSTimedly(5);//采样周期为0.1s,系统节拍周期20ms
}
while(1) //控制采样和控制任务循环
{
history[p]=SampleAdc();//接着上次,第M次采样,后来新的采样数据入队,覆盖窗口中最老的数据
p++; //调整入队指针,指向下一个最老的数据;
if(p==M) p=0; //指针循环控制
s=0; //初始化累加和
j=p; //j指向最老的数据
for(i=0;i<M;i++) //按加权系数累加历史数据窗口内的数据
{
s+=k[i]*history[j];//加权累加运算
j++; //指向下一个采样数据
if(j==M) j=0; //指针循环控制
}
Samp=s/Q; //计算加权平均值,供其他函数使用
PIDCtrl(); //调用PID算法
OSTimedly(5); //采样时间为0.1s
}
}
程序中的最新的采样数据一直紧挨着最老的数据,并且最新的在最老的左边。