实用版滑动滤波算法,兼顾数据稳定性和实时性,已用于产品。

滑动平均值滤波是指先在RAM中建立一个数据缓冲区,依顺序存放N个采样数据,每采进一个新数据,就将最早采集的那个数据丢掉,而后求包括新数据在内的N个数据的算术平均值。这样,每进行一次采样,就可计算出一个新的平均值,从而加快了数据处理的速度。

优点:经过滤波处理后,滤除了噪声干扰,数据波动稳定平滑。

缺点:1、需要在RAM中建立数据缓冲区,浪费RAM。

2、当采样数据越多,数据实时性越差,当数据突然发生较大变化时,不能被立刻检测到,无法及时处理突发事件。

所以需要对传统滑动滤波算法进行改进。

1、不需要建立缓冲区,用一个变量保存所有采样数据的累加和,累加和除以采样个数就是滤波后的平均值。

2、在程序中设定数据波动阈值,超过阈值,立刻更新滤波平均值,提高实时性。

经过改进后,兼顾了数据的稳定性和实时性。

u16 Slide_filter(u16 data,u8 Filter_depth,u16 percent)
{
	static u8  B_initial=1;
	static u16 average;
	static u32 Sum;
	static u8 LB1,LB2;
	static u16 threshold;
	
	if(data<(average-threshold))
	{
		if(LB1<3)
			LB1++;
		else
			B_initial=1;
	}
	else
		LB1=0;

	if(data>(average+threshold))
	{
		if(LB2<3)
			LB2++;
		else
			B_initial=1;
	}
	else
		LB2=0;	
	
	if(B_initial)
	{
		B_initial--;
		average=data;
		Sum=average*Filter_depth;
		LB1=0;LB2=0;
	}
	Sum=Sum-average+data;
	average=Sum/Filter_depth;
	threshold=(average/100)*percent;
	
	return average;
}

时隔半年,发现上面的滤波函数需要进一步优化,下面是优化的原因

由于产品的功率大,di/dt较大,对ADC采样值造成干扰,ADC采样值有很多毛刺,为了使所有参数平滑变化,需要对所有参数进行滤波,例如温度,电流,电压,功率等等。

如果采用上述的函数,那么需要定义很多相同功能的函数,代码行数多,不方便阅读。

所以我采用结构体的方法,定义函数

filter.c文件

type_WSF ACV_Filter,ACI_Filter,ACW_Filter,ACI_disp_Filter,ACIl_disp_Filter;

type_WMF MT20BR5_REF_Filter,ACI_REF_Filter,ACV_REF_Filter;

u16 Sliding_filter(type_WSF *WSF,u16 data,u8 depth,u16 percent)
{
	if(data<(WSF->average-WSF->threshold))
	{
		if(WSF->LB1<d_LB_MAX)
			WSF->LB1++;
		else
			WSF->B_init=1;
	}
	else
		WSF->LB1=0;
	
	if(data>(WSF->average+WSF->threshold))
	{
		if(WSF->LB2<d_LB_MAX)
			WSF->LB2++;
		else
			WSF->B_init=1;
	}
	else
		WSF->LB2=0;
	if(WSF->B_init)
	{
		WSF->B_init--;
		WSF->average=data;
		WSF->Sum=WSF->average*depth;
		WSF->LB1=0;
		WSF->LB2=0;
	}
	WSF->Sum=WSF->Sum-WSF->average+data;
	WSF->average=WSF->Sum/depth;
	WSF->threshold=(WSF->average*percent)/100;
	return WSF->average;
}

void WSF_int(type_WSF *WSF)
{
	WSF->B_init=1;
	WSF->LB1=0;
	WSF->LB2=0;
	WSF->average=0;
	WSF->threshold=0;
	WSF->Sum=0;
	WSF->Sliding_filter=Sliding_filter;
}
/*************************************************************************************/
u16 Mean_filter(type_WMF *WMF,u16 data,u8 size)
{
	if(WMF->cnt<size)
	{
		WMF->cnt++;
		WMF->Sum+=data;
	}
	else
	{
		WMF->average=WMF->Sum/WMF->cnt;
		WMF->Sum=0;
		WMF->cnt=0;
	}
	return WMF->average;
}

void WMF_init(type_WMF *WMF)
{
	WMF->cnt=0;
	WMF->average=0;
	WMF->Sum=0;
	WMF->Mean_filter=Mean_filter;
}

filter.h

#ifndef FILTER_H
#define FILTER_H

#include "user_define.h"

#define d_LB_MAX	3

typedef struct Window_Sliding_Filter
{
	u8 B_init;
	u8 LB1;
	u8 LB2;
	u16 average;
	u16 threshold;
	u32 Sum;
  u16 (*Sliding_filter)(struct Window_Sliding_Filter *WSF,u16 data,u8 depth,u16 percent);
}type_WSF;


typedef struct Window_Mean_Filter
{
	u8 cnt;
	u16 average;
	u32 Sum;
	u16 (*Mean_filter)(struct Window_Mean_Filter *WMF,u16 data,u8 size);
}type_WMF;

extern type_WSF ACV_Filter,ACI_Filter,ACW_Filter,ACI_disp_Filter,ACIl_disp_Filter;
extern type_WMF MT20BR5_REF_Filter,ACI_REF_Filter,ACV_REF_Filter;

extern void WSF_int(type_WSF *WSF);
extern void WMF_init(type_WMF *WMF);
#endif

main.c

void main(void)
{
    system_init();
    WMF_init(&MT20BR5_REF_Filter);
   	WMF_init(&ACI_REF_Filter);
	WMF_init(&ACV_REF_Filter);
	WSF_int(&ACV_Filter);
	WSF_int(&ACI_Filter);
	WSF_int(&ACW_Filter);
	WSF_int(&ACI_disp_Filter);
	WSF_int(&ACIl_disp_Filter);
    while(1)
    {
        R_IAC_ADC_REF=ACI_REF_Filter.Mean_filter(&ACI_REF_Filter,R_Iac_rms,200);
         ADC_Calculation.V_LN=ACV_Filter.Sliding_filter(&ACV_Filter,V_LN,6,5);
    }
}

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值