现实中的物理量都是连续的模拟量,其变化需要一定时间,且在短时间内的变化量有一个合理的限度。例如气温,短时间内前后两个采样值的差值必定有个最大范围,基于这个条件可以对其中明显受到干扰的无效值进行剔除。本次的无效采样值排除后,再根据前面数据的变化趋势,预测一个合理的数据替代本次的问题值,而不是直接使用上次的结果。
1、 什么样的采样值为无效值
根据物理量的检测范围,和在采样间隔内最大的变化可能来定义,如气温检测,可定义温度在正负50度之间,如果采样间隔是1分钟,那气温在1分钟内最多变化5度。实际应用需要根据使用场景来确定,范围越小对异常值的判断排除越准确。
2、 如何根据趋势预测合理值
还是以气温为例,连续3次采样结果分别是t1,t2,t3,假设温度在短时间内的变化趋势相同,t2-t1=t3-t2,转换后得出t3=2*t2-t1,即在合适的范围内,可以根据前面2个历史值预测出当前采样值。采样间隔越小预测值越准确,在采样频率很小的情况下,结果可能存在一定误差。
确定了原理,那算法就可以出来了。
//设定温度变化范围和最大变化趋势
#define SAMPLE_MIX -50
#define SAMPLE_MAX 50
#define DIFF_MAX 5
int history[2];//历史值,其中history[1]为最近的记录
int filter(void)
{
int current;
int valid=1;
current=read_sample();//更新采样值
if((current-history[1]>DIFF_MAX)||(history[1]-current>DIFF_MAX))
{
valid=0;
}
if((current<SAMPLE_MIX)||(current>SAMPLE_MAX))
{
valid=0;
}
if(valid==0)//表示本次采样值无效
{
current=2*history[1]-history[0];
if(current<SAMPLE_MIX)
{
current=SAMPLE_MIX;
}
else if(current>SAMPLE_MAX)
{
current=SAMPLE_MAX;
}
}
history[0]=history[1];
history[1]=current;
return current;
}
缺点:只能过滤偶发的异常数据。