• 单片机ADC常见的几种滤波方法


    如今传感器的种类越来越多,数量也越来越多,而这些传感器很多都会用到模拟量,模拟量就离不开ADC。

    然而,我们单片机ADC采集的模拟量基本都会经过“滤波”处理才能使用,下面给大家分享一些常见的ADC滤波算法。

    一、限幅滤波

    1、方法

    • 根据经验判断两次采样允许的最大偏差值A

    • 每次采新值时判断:若本次值与上次值之差<=A,则本次有效;若本次值与上次值之差>A,本次无效,用上次值代替本次。

    2、优缺点

    • 克服脉冲干扰,无法抑制周期性干扰,平滑度差。

    3、代码

    1. /* A值根据实际调,Value有效值,new_Value当前采样值,程序返回有效的实际值 */
    2. #define A 10
    3. char Value;
    4. char filter()
    5. {
    6.   char new_Value;
    7.   new_Value = get_ad();                                        //获取采样值
    8.   ifabs(new_Value - Value) > A)   return Value;             //abs()取绝对值函数
    9.   return new_Value;
    10. }

    二、中位值滤波

    1、方法

    • 连续采样N次,按大小排列

    • 取中间值为本次有效值

    2、优缺点

    • 克服波动干扰,对温度等变化缓慢的被测参数有良好的滤波效果,对速度等快速变化的参数不宜。

    3、代码

    1. #define N 11
    2. char filter()
    3. {
    4.  char value_buf[N];
    5.  char count,i,j,temp;
    6.  for(count = 0;count < N;count++)                                //获取采样值
    7.  {
    8.   value_buf[count] = get_ad();
    9.   delay();
    10.  }
    11.  for(j = 0;j<(N-1);j++)
    12.   for(i = 0;i<(n-j);i++)
    13.   if(value_buf[i]>value_buf[i+1])
    14.   {
    15.    temp = value_buf[i];
    16.    value_buf[i] = value_buf[i+1];
    17.    value_buf[i+1] = temp;
    18.   }
    19.  return value_buf[(N-1)/2];
    20. }

    三、算数平均滤波

    1、方法

    • 连续采样N次,取平均

    • N较大时平滑度高,灵敏度低

    • N较小时平滑度低,灵敏度高

    • 一般N=12

    2、优缺点

    • 适用于存在随机干扰的系统,占用RAM多,速度慢。

    3、代码

    1. #define N 12
    2. char filter()
    3. {
    4.  int sum = 0;
    5.  for(count = 0;count
    6.   sum += get_ad();
    7.  return (char)(sum/N);
    8. }

    四、递推平均滤波

    1、方法

    • 取N个采样值形成队列,先进先出

    • 取均值

    • 一般N=4~12

    2、优缺点

    • 对周期性干扰抑制性好,平滑度高

    • 适用于高频振动系统

    • 灵敏度低,RAM占用较大,脉冲干扰严重

    3、代码

    1. /* A值根据实际调,Value有效值,new_Value当前采样值,程序返回有效的实际值 */
    2. #define A 10
    3. char Value;
    4. char filter()
    5. {
    6.   char new_Value;
    7.   new_Value = get_ad();                                        //获取采样值
    8.   ifabs(new_Value - Value) > A)   return Value;             //abs()取绝对值函数
    9.   return new_Value;
    10. }

    五、中位值平均滤波

    1、方法

    • 采样N个值,去掉最大最小

    • 计算N-2的平均值

    • N= 3~14

    2、优缺点

    1. 融合了中位值,平均值的优点

    2. 消除脉冲干扰

    3. 计算速度慢,RAM占用大

    3、代码

    1. char filter()
    2. {
    3.  char count,i,j;
    4.  char Value_buf[N];
    5.  int sum=0;
    6.  for(count=0;count
    7.   Value_buf[count]= get_ad();
    8.  for(j=0;j<(N-1);j++)
    9.   for(i=0;i<(N-j);i++)
    10.    if(Value_buf[i]>Value_buf[i+1])
    11.    {
    12.      temp = Value_buf[i];
    13.      Value_buf[i]= Value_buf[i+1];
    14.       Value_buf[i+1]=temp;
    15.    }
    16.    for(count =1;count-1;count++)
    17.     sum += Value_buf[count];
    18.    return (char)(sum/(N-2));
    19. }

    六、限幅平均滤波

    1、方法

    • 每次采样数据先限幅后送入队列

    • 取平均值

    2、优缺点

    • 融合限幅、均值、队列的优点

    • 消除脉冲干扰,占RAM较多

    3、代码

    1. #define A 10
    2. #define N 12
    3. char value,i=0;
    4. char value_buf[N];
    5. char filter()
    6. {
    7.  char new_value,sum=0;
    8.  new_value=get_ad();
    9.  if(Abs(new_value-value)
    10.   value_buf[i++]=new_value;
    11.  if(i==N)i=0;
    12.  for(count =0 ;count
    13.   sum+=value_buf[count];
    14.  return (char)(sum/N);
    15. }

    七、一阶滞后滤波

    1、方法

    • 取a=0~1

    • 本次滤波结果=(1-a)* 本次采样 + a * 上次结果

    2、优缺点

    • 良好一直周期性干扰,适用波动频率较高场合

    • 灵敏度低,相位滞后

    3、代码

    1. /*为加快程序处理速度,取a=0~100*/
    2. #define a 30
    3. char value;
    4. char filter()
    5. {
    6.  char new_value;
    7.  new_value=get_ad();
    8.  return ((100-a)*value + a*new_value);
    9. }

    八、加权递推平均滤波

    1、方法

    • 对递推平均滤波的改进,不同时刻的数据加以不同权重,通常越新的数据权重越大,这样灵敏度高,但平滑度低。

    2、优缺点

    • 适用有较大滞后时间常数和采样周期短的系统,对滞后时间常数小,采样周期长、变化慢的信号不能迅速反应其所受干扰。

    3、代码

    1. /* coe数组为加权系数表 */
    2. #define N 12
    3. char code coe[N]={1,2,3,4,5,6,7,8,9,10,11,12};
    4. char code sum_coe={1+2+3+4+5+6+7+8+9+10+11+12};
    5. char filter()
    6. {
    7.  char count;
    8.  char value_buf[N];
    9.  int sum=0;
    10.  for(count=0;count
    11.  {
    12.   value_buf[count]=get_ad();
    13.  }
    14.  for(count=0;count
    15.   sum+=value_buf[count]*coe[count];
    16.  return (char)(sum/sum_coe);
    17. }

    九、消抖滤波

    1、方法

    • 设置一个滤波计数器

    • 将采样值与当前有效值比较

    • 若采样值=当前有效值,则计数器清0

    • 若采样值不等于当前有效值,则计数器+1

    • 若计数器溢出,则采样值替换当前有效值,计数器清0

    2、优缺点

    • 对变化慢的信号滤波效果好,变化快的不好

    • 避免临界值附近的跳动,计数器溢出时若采到干扰值则无法滤波

    3、代码

    1. #define N 12
    2. char filter()
    3. {
    4.  char count=0,new_value;
    5.  new_value=get_ad();
    6.  while(value!=new_value)
    7.  {
    8.   count++;
    9.   if(count>=N) return new_value;
    10.   new_value=get_ad();
    11.  }
    12.  return value;
    13. }

    十、限幅消抖滤波

    1、方法

    • 先限幅 后消抖

    2、优缺点

    • 融合了限幅、消抖的优点

    • 避免引入干扰值,对快速变化的信号不宜

    3、代码

    1. #define A 10
    2. #define N 12
    3. char value;
    4. char filter()
    5. {
    6.  char new_value,count=0;
    7.  new_value=get_ad();
    8.  while(value!=new_value)
    9.  {
    10.   if(Abs(value-new_value)
    11.   {
    12.   count++;
    13.   if(count>=N) return new_value;
    14.   new_value=get_ad();
    15.   }
    16.  return value;
    17.  }
    18. }
  • 相关阅读:
    JVM 架构解释 + 垃圾回收机制 详解(基于JDK8版本)
    【Ant Design Pro】使用ant design pro做为你的开发模板(八)开发第一个完整的后台页面
    【CSS基础】
    springboot停车场车辆定位管理可视化分析系统的设计与实现毕业设计源码101702
    拼图小游戏
    使用uniapp开发时自定义tabbar
    “30岁,当一名游戏技术总监去”
    【八大经典排序算法】快速排序
    高效处理海量慢SQL日志文件:Java与JSQLParser去重方案详解
    一篇全面而且透彻的RabbitMQ性能优化指南
  • 原文地址:https://blog.csdn.net/m0_61687959/article/details/127877704