随机误差以及滤波算法


在这里插入图片描述

【 1. 限幅滤波 】

A、方法:
  根据经验判断,确定两次采样允许的最大偏差值(设为A)
  每次检测到新值时判断:
  如果本次值与上次值之差<=A,则本次值有效
  如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值
B、优点:
  能有效克服因偶然因素引起的脉冲干扰
C、缺点
  无法抑制周期性的干扰
  平滑度差

/***限幅滤波**/
#define A 10 //设置两次采样允许的最大偏差值
char value;  //上次采用后的有效值变量
char filter_1(void)
{
    char  new_value;  //本次采样值变量
    new_value=get_ad();  //读入本次采样值
    if((new_value-value>A)||(value-new_value>A)) //比较是否超出最大偏差值
        return  value; //如果超出,返回上次的有效值作为本次的有效值
    return  new_value;// 如果没有超出,返回本次的采样值作为本次的有效值
}

【 2. 中位值滤波 】

A、方法:
  连续采样N次(N取奇数)
  把N次采样值按大小排列
  取中间值为本次有效值
B、优点:
  能有效克服因偶然因素引起的波动干扰
  对温度、液位的变化缓慢的被测参数有良好的滤波效果
C、缺点:
  对流量、速度等快速变化的参数不宜

/***中位值滤波法***/
#define N 11 //设置连续采样的次数

char filter_2(void)
{
    char  value_buf[N]; //缓存N次采样值的存储变量
    char  count,i,j,temp; //i,j是冒泡排序的下标变量,count是采样数据读入的下标变量
                      //temp是临时变量
    for(count=0;count<N;count++) //连续读入N个采样值
    {
      value_buf[count]=get_ad();
      delay();
    }
    for(j=0;j<N-1;j++) //气泡排序,由小到大
    {
        for(i=0;i<N-1-j;i++)
        {
           if(value_buf[i]>value_buf[i+1])
         {
           temp=value_buf[i];
           value_buf[i]=value_buf[i+1];
           value_buf[i+1]=temp;
         }
        }
     }
     return value_buf[(N-1)/2]; //将排序后N个采样值的中间值作为最后结果返回
}

【 3. 算术平均滤波 】

A、方法:
  连续取N个采样值进行算术平均运算
  N值较大时:信号平滑度较高,但灵敏度较低
  N值较小时:信号平滑度较低,但灵敏度较高
  N值的选取:一般流量,N=12;压力:N=4
B、优点:
  适用于对一般具有随机干扰的信号进行滤波
  这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动
C、缺点:
  对于测量速度较慢或要求数据计算速度较快的实时控制不适用
  比较浪费RAM

/**算数平均滤波法**/
/* N为进行平均运算的每组采样值的数量,依据实际情况可以改变*/
#undef N
#define N 12 //设置每组参与平均运算的采样值个数

char filter_3()
{
    int  sum=0; //求和变量,用于存储采样值的累加值
    char count;//采样数据读入的下标变量
    for(count=0;count<N;count++) //连续读入N个采样值,并累加
    {
      sum+=get_ad();
      delay();
    }
    return (char)(sum/N); //讲累加值进行平均计算作为返回值
}

【 4. 递推平均滤波(滑动平均滤波) 】

A、方法:
  把连续取N个采样值看成一个队列
  队列的长度固定为N
  每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)
  把队列中的N个数据进行算术平均运算,就可获得新的滤波结果
  N值的选取:流量,N=12;压力:N=4;液面,N=412;温度,N=14
B、优点:
  对周期性干扰有良好的抑制作用,平滑度高
  适用于高频振荡的系统
C、缺点:
  灵敏度低
  对偶然出现的脉冲性干扰的抑制作用较差
  不易消除由于脉冲干扰所引起的采样值偏差
  不适用于脉冲干扰比较严重的场合
  比较浪费RAM

/**递推平均滤波法**/
#undef N
#define N 12 //设置FIFO队列的长度
char  value_buf[N];//FIFO队列变量
char  i=0; //队列的下标变量

char filter_4(){
    char count;
	int  sum=0;
	value_buf[i++]=get_ad();
	if(i==N)  i=0;
    for(count=0;count<N;count++)
      sum+=value_buf[count];
    return(char)(sum/N);
}

【 5. 中位值平均滤波(防脉冲干扰平均滤波)】

A、方法:
  相当于“中位值滤波法”+“算术平均滤波法”
  连续采样N个数据,去掉一个最大值和一个最小值
  然后计算N-2个数据的算术平均值
  N值的选取:3~14
B、优点:
  融合了两种滤波法的优点
  对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差
C、缺点:
  测量速度较慢,和算术平均滤波法一样
  比较浪费RAM

/**中位值平均滤波法**/
/* 采样值N为每组采样值的数量,依据实际情况可以改变*/
#undef N
#define N 12 //设置每组采样值的数量
char filter_5()
{
   char count,i,j,temp; //i,j是冒泡排序的下标变量,count是采样数据读入的下标变量
   char value_buf[N]; // 缓冲N个采样值的存储变量
   int  sum=0; //求和变量,用于存储采样值的累加值
   for  (count=0;count<N;count++) //连续读入N个采样值
   {
      value_buf[count] = get_ad();
      delay();
   }
   for (j=0;j<N-1;j++) //气泡排序,由小到大
   {
      for (i=0;i<N-j;i++)
      {
         if ( value_buf[i]>value_buf[i+1] )
         {
            temp = value_buf[i];
            value_buf[i] = value_buf[i+1];
             value_buf[i+1] = temp;
         }
      }
   }
   for(count=1;count<N-1;count++)
    sum += value_buf[count]; //去掉两端的最小和最大采样值,对中间的N-2个采样值求和
   return (char)(sum/(N-2));// 返回中间N-2个采样值的平均值
}

【 6. 限幅平均滤波 】

A、方法:
  相当于“限幅滤波法”+“递推平均滤波法”
  每次采样到的新数据先进行限幅处理,
  再送入队列进行递推平均滤波处理
 B、优点:
  融合了两种滤波法的优点
  对于偶然出现 的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差
 C、缺点:
  比较浪费RAM

/**限幅平均滤波法**/
/* A值可以根据实际情况调整,value为上次采样的有效值,new_value为当前采样值 */
/* N为进行平均运算的每组采样值的数量,依据实际情况可以改变*/
#undef A
#undef N
#define A 10 //设置两次采样允许的最大偏差值
#define N 12 //设置每组参与平均运算的采样值个数
char value;  //上次采用后的有效值变量

char filter_6()
{
    char  new_value;  //本次采样值变量
    int  sum=0; //求和变量,用于存储采样值的累加值
    char count;//采样数据读入的下标变量
	for(count=0;count<N;count++)
    {
		new_value=get_ad();  //读入本次采样值
      	if((new_value-value>A)||(value-new_value>A)) //比较是否超出最大偏差值
      		new_value=value; //如果超出,返回上次的有效值作为本次的有效值
      	sum+=new_value; //累加采样的有效值
      	value=new_value;
      	delay();
    }
    return (char)(sum/N); //将累加值进行平均计算作为返回值
}

【 7. 一阶滞后滤波 】

A、方法:
  取a=0~1
  本次滤波结果=(1-a)本次采样值+a上次滤波结果
B、优点:
  对周期性干扰具有良好的抑制作用
  适用于波动频率较高的场合
C、缺点:
  相位滞后,灵敏度低
  滞后程度取决于a值大小
  不能消除滤波频率高于采样频率的1/2的干扰信号

/**一阶滞后滤波法**/
/* 为加快程序处理速度假定基数为100,a=0~100 */
#define COE 50 //定义加权系数
char value; //上一个采样值变量
char filter_7()
{
   char  new_value; //本次采样值变量
   new_value = get_ad();
   return (100-COE)*value + COE*new_value; //返回的本次滤波结果
}

【 8、加权递推平均滤波 】

A、方法:
  是对递推平均滤波法的改进,即不同时刻的数据加以不同的权
  通常是,越接近现时刻的数据,权取得越大。
  给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低
B、优点:
  适用于有较大纯滞后时间常数的对象
  和采样周期较短的系统
C、缺点:
  对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号,不能迅速反应系统当前所受干扰的严重程度,滤波效果差

/**加权递推平均滤波法**/
/* coe数组为加权系数表,存在程序存储区。*/
#undef N
#define N 12  //设置FIFO队列的长度

char code coe[N] = {1,2,3,4,5,6,7,8,9,10,11,12}; //加权系数
char code sum_coe = 1+2+3+4+5+6+7+8+9+10+11+12;
char filter_8()
{
   char count; //采样数据读入的下标变量
   char value_buf[N]; //缓存N个采样值的存储变量
   int  sum=0; //求和变量,用于存储采样值的累加值
   for (count=0;count<N;count++)
   {
      value_buf[count] = get_ad(); //读入采样值
      delay();
   }
   for (count=0;count<N;count++)
      sum += value_buf[count]*coe[count]; //累加采样值和系数的乘积
   return (char)(sum/sum_coe); //累加值与系数和相除作为返回结果
}

【 9、消抖滤波 】

A、方法:
  设置一个滤波计数器
  将每次采样值与当前有效值比较:
  如果采样值=当前有效值,则计数器清零
  如果采样值 ≠ 当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出)
  如果计数器溢出,则将本次值替换当前有效值,并清计数器
B、优点:
  对于变化缓慢的被测参数有较好的滤波效果,
  可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动
C、缺点:
  对于快速变化的参数不宜
  如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统

/**消抖滤波法**/
#undef N
#define N 12 //设置计数器溢出值
char filter_9()
{
   char count=0; //计数变量
   char new_value; //本次采样值变量
   new_value = get_ad(); //读入本次采样值
   while (value !=new_value);
   {
      count++; //计数器加1
      if (count>=N)   return new_value; //如果本次采样值与当前有效值不相等,
//且计数器溢出,返回本次采样值
       delay();
      new_value = get_ad();
   }
   return value; //如果本次采样值与当前有效值相等,则返回当前有效值
}

【 10、限幅消抖滤波 】

A、方法:
  相当于“限幅滤波法”+“消抖滤波法”
  先限幅,后消抖
B、优点:
  继承了“限幅”和“消抖”的优点
  改进了“消抖滤波法”中的某些缺陷,避免将干扰值导入系统
C、缺点:
  对于快速变化的参数不宜

/**限幅消抖滤波法**/

/* A值可以根据实际情况调整,value为上次采样的有效值,new_value为当前采样值 */
/* N为计数器的溢出值*/
#undef A
#undef N
#define A 10 //设置两次采样允许的最大偏差值
#define N 12 //设置计数器溢出值
int value;  //有效值变量

int filter_10()
{
   int count=0; //计数变量
   int new_value; //本次采样值变量
   new_value = get_ad(); //读入本次采样值
   if((new_value-value>A)||(value-new_value>A)) //比较是否超出最大偏差值
		new_value=value; //如果超出,返回有效值作为本次的采样有效值
   while (value !=new_value);
   {
      count++; //计数器加1
      if (count>=N)   return new_value; //如果本次采样值与当前有效值不相等,
										//且计数器溢出,返回本次采样值
       delay();
      new_value = get_ad();
   }
   return value; //如果本次采样值与当前有效值相等,则返回当前有效值
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MR_Promethus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值