极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: GGG1101

新人求助怎么把限幅滤波算法应用在超声波测距上

[复制链接]
发表于 2017-3-26 16:42:03 | 显示全部楼层 |阅读模式
是这样的,我在论坛上看见十大滤波算法大全,上面的限幅滤波法怎么用在超声波测距上。我刚接触这个方面的东西,有些看不懂,耽误大家一点时间,我想问几个问题。

  1. /*
  2. A、名称:限幅滤波法(又称程序判断滤波法)
  3. B、方法:
  4.     根据经验判断,确定两次采样允许的最大偏差值(设为A),
  5.     每次检测到新值时判断:
  6.     如果本次值与上次值之差<=A,则本次值有效,
  7.     如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
  8. C、优点:
  9.     能有效克服因偶然因素引起的脉冲干扰。
  10. D、缺点:
  11.     无法抑制那种周期性的干扰。
  12.     平滑度差。
  13. E、整理:shenhaiyu 2013-11-01
  14. */

  15. int Filter_Value;
  16. int Value;

  17. void setup() {
  18.   Serial.begin(9600);       // 初始化串口通信
  19.   randomSeed(analogRead(0)); // 产生随机种子
  20.   Value = 300;
  21. }

  22. void loop() {
  23.   Filter_Value = Filter();       // 获得滤波器输出值
  24.   Value = Filter_Value;          // 最近一次有效采样的值,该变量为全局变量
  25.   Serial.println(Filter_Value); // 串口输出
  26.   delay(50);
  27. }

  28. // 用于随机产生一个300左右的当前值
  29. int Get_AD() {
  30.   return random(295, 305);
  31. }

  32. // 限幅滤波法(又称程序判断滤波法)
  33. #define FILTER_A 1
  34. int Filter() {
  35.   int NewValue;
  36.   NewValue = Get_AD();
  37.   if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
  38.     return Value;
  39.   else
  40.     return NewValue;
  41. }

  42. 这个是我转自论坛上大神写的限幅滤波算法代码。但我不知道怎么用在超声波测距上。

复制代码

这个超声波测距有时候数据跳动比较大,我想让其平稳些.
怎么把超声波测距的数值放进上面这个滤波代码中呢?
回复

使用道具 举报

 楼主| 发表于 2017-3-26 16:44:15 | 显示全部楼层
上面的int Filter_Value,Filter()啥意思呢
回复 支持 反对

使用道具 举报

发表于 2017-3-26 19:39:19 | 显示全部楼层
GGG1101 发表于 2017-3-26 16:44
上面的int Filter_Value,Filter()啥意思呢

测距结果替换Get_AD();就可以了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-26 22:36:02 | 显示全部楼层
275891381 发表于 2017-3-26 19:39
测距结果替换Get_AD();就可以了

怎么替换,能不能给我详细的讲一下,兄弟
回复 支持 反对

使用道具 举报

发表于 2017-3-27 11:54:20 | 显示全部楼层
GGG1101 发表于 2017-3-26 22:36
怎么替换,能不能给我详细的讲一下,兄弟

return random(295, 305); 这一句话换成测距结果就可以了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-27 17:52:17 | 显示全部楼层
前辈,谢谢你多次给我解答疑惑,麻烦你再看看 我写的这个正不正确。滤波部分是论坛10大滤波算法之一的算术平均滤波法(限幅滤波不怎么适合超声波,所以我换了一个)。这个原贴算术平均滤波法代码是这样的
  1. /*
  2. A、名称:算术平均滤波法
  3. B、方法:
  4.     连续取N个采样值进行算术平均运算:
  5.     N值较大时:信号平滑度较高,但灵敏度较低;
  6.     N值较小时:信号平滑度较低,但灵敏度较高;
  7.     N值的选取:一般流量,N=12;压力:N=4。
  8. C、优点:
  9.     适用于对一般具有随机干扰的信号进行滤波;
  10.     这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
  11. D、缺点:
  12.     对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
  13.     比较浪费RAM。
  14. E、整理:shenhaiyu 2013-11-01
  15. */

  16. int Filter_Value;

  17. void setup() {
  18.   Serial.begin(9600);       // 初始化串口通信
  19.   randomSeed(analogRead(0)); // 产生随机种子
  20. }

  21. void loop() {
  22.   Filter_Value = Filter();       // 获得滤波器输出值
  23.   Serial.println(Filter_Value); // 串口输出
  24.   delay(50);
  25. }

  26. // 用于随机产生一个300左右的当前值
  27. int Get_AD() {
  28.   return random(295, 305);
  29. }

  30. // 算术平均滤波法
  31. #define FILTER_N 12
  32. int Filter() {

  33.   int filter_sum = 0;
  34.   int i=0;
  35.   for( i = 0; i < FILTER_N; i++) {
  36.     filter_sum += Get_AD();
  37.     delay(1);
  38.   }
  39.   return (int)(filter_sum / FILTER_N);
  40. }


  41. 我写的是下面的

  42. #include <LiquidCrystal.h>
  43. LiquidCrystal lcd(12,11,5,4,3,2);
  44.   int TrigPin = 9;
  45.   int EchoPin =8;
  46. double Time_Echo_us;


  47. void setup()
  48. {
  49. lcd.begin(16,2);
  50. lcd.print("Welcom to Use");
  51. pinMode(TrigPin, OUTPUT);
  52. pinMode(EchoPin, INPUT);
  53. }


  54. void loop()
  55. {
  56.    
  57.    
  58.    digitalWrite(TrigPin,LOW);
  59.    delayMicroseconds(2);
  60.    digitalWrite(TrigPin,HIGH);
  61.    delay(1);
  62.    digitalWrite(TrigPin,LOW);
  63.    
  64.    Time_Echo_us= pulseIn(EchoPin,HIGH);
  65.    
  66.     if(( Time_Echo_us <= 23530)&&(Time_Echo_us > 175))
  67.     {
  68.         
  69.       
  70.       
  71.        lcd.print( Filter());
  72.       
  73.        delay(600);
  74.        lcd.clear();
  75.        lcd.home();
  76.     }
  77.     else
  78.     {
  79.       lcd.clear();
  80.       
  81.     }
  82. }
  83.   
  84.     #define FILTER_N 10
  85.   int Filter()
  86.    {
  87.      
  88.     int filter_sum = 0;
  89.     for(int i = 0; i < FILTER_N; i++)
  90.     {
  91.       filter_sum +=( Time_Echo_us*0.017);
  92.       delay(1);
  93.      }
  94.     return ((int)(filter_sum / FILTER_N));
  95.    }
复制代码

请你帮我看下我借鉴算术平均滤波法写的有没有问题,在液晶上面的显示也能显示的出来。但是我感觉测距结果还是和原来一样,同一个地方测距,放着不动,数值跳动有2CM上下浮动。 ,就这样的。好像不成功。我本意是在一个周期内多取几次超声波测量值,然后取平均值,显示在液晶上,这样想必稳定些,所以借鉴这个算术平均法,但情况不怎么理想,不知道是不是我理解错了。按道理取了平均值后,显示平均值在液晶上,跳动不会猛地变化,最少整数位不会出现2厘米浮动,小数位会变化。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。
     

      
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-27 18:55:29 | 显示全部楼层
275891381 发表于 2017-3-27 11:54
return random(295, 305); 这一句话换成测距结果就可以了
/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 算术平均滤波法
#define FILTER_N 12
int Filter() {

  int filter_sum = 0;
  int i=0;
  for( i = 0; i < FILTER_N; i++) {
    filter_sum += Get_AD();
    delay(1);
  }
  return (int)(filter_sum / FILTER_N);
}


我写的是下面的

#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,5,4,3,2);
  int TrigPin = 9;
  int EchoPin =8;
double Time_Echo_us;


void setup()
{
lcd.begin(16,2);
lcd.print("Welcom to Use");
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
}


void loop()
{
   
   
   digitalWrite(TrigPin,LOW);
   delayMicroseconds(2);
   digitalWrite(TrigPin,HIGH);
   delay(1);
   digitalWrite(TrigPin,LOW);
   
   Time_Echo_us= pulseIn(EchoPin,HIGH);
   
    if(( Time_Echo_us <= 23530)&&(Time_Echo_us > 175))
    {
        
      
      
       lcd.print( Filter());
      
       delay(600);
       lcd.clear();
       lcd.home();
    }
    else
    {
      lcd.clear();
      
    }
}
  
    #define FILTER_N 10
  int Filter()
   {
     
    int filter_sum = 0;
    for(int i = 0; i < FILTER_N; i++)
    {
      filter_sum +=( Time_Echo_us*0.017);
      delay(1);
     }
    return ((int)(filter_sum / FILTER_N));
   }


前辈,谢谢你多次给我解答疑惑,麻烦你再看看 我写的这个正不正确。滤波部分是论坛10大滤波算法之一的算术平均滤波法(限幅滤波不怎么适合超声波,所以我换了一个)。这个原贴算术平均滤波法代码是这样的


请你帮我看下我借鉴算术平均滤波法写的有没有问题,在液晶上面的显示也能显示的出来。但是我感觉测距结果还是和原来一样,同一个地方测距,放着不动,数值跳动有2CM上下浮动。 ,就这样的。好像不成功。我本意是在一个周期内多取几次超声波测量值,然后取平均值,显示在液晶上,这样想必稳定些,所以借鉴这个算术平均法,但情况不怎么理想,不知道是不是我理解错了。按道理取了平均值后,显示平均值在液晶上,跳动不会猛地变化,最少整数位不会出现2厘米浮动,同一个位置,超声波模块也没有拿在手上晃动  。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。
     
回复 支持 反对

使用道具 举报

发表于 2017-3-28 10:56:21 | 显示全部楼层
GGG1101 发表于 2017-3-27 18:55


#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int TrigPin = 9;
int EchoPin = 8;
double Time_Echo_us;

void setup()
{
        lcd.begin(16, 2);
        lcd.print("Welcom to Use");
        pinMode(TrigPin, OUTPUT);
        pinMode(EchoPin, INPUT);
}


void loop()
{
        lcd.print( Filter());
        delay(1000);
        lcd.clear();
        lcd.home();
}

#define FILTER_N 10
long Filter()
{
        float filter_sum = 0;
        for(int i = 0; i < FILTER_N; i++)
        {
                filter_sum += ( get_juli() * 0.017);
                delay(10);
        }
        return ((long)(filter_sum / FILTER_N));
}

long  get_juli(void)
{
        digitalWrite(TrigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(TrigPin, HIGH);
        delay(1);
        digitalWrite(TrigPin, LOW);

        Time_Echo_us = pulseIn(EchoPin, HIGH);

        if(( Time_Echo_us <= 23530) && (Time_Echo_us > 175))
                return Time_Echo_us;
        else
                return 0;
}

前辈,谢谢你多次给我解答疑惑,麻烦你再看看 我写的这个正不正确。滤波部分是论坛10大滤波算法之一的算 ...


按你的意思应该是这样的

回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-28 11:15:36 | 显示全部楼层
275891381 发表于 2017-3-28 10:56
按你的意思应该是这样的

#include

谢谢前辈您帮代码整理的这么清晰,谢谢
回复 支持 反对

使用道具 举报

发表于 2017-3-28 11:21:08 | 显示全部楼层
GGG1101 发表于 2017-3-28 11:15
谢谢前辈您帮代码整理的这么清晰,谢谢

filter_sum +=( Time_Echo_us*0.017);像有这一句 filter_sum就不能int 了  只能float了,不然小数部分都没了,细节多注意一点
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-28 13:22:07 | 显示全部楼层
275891381 发表于 2017-3-28 11:21
filter_sum +=( Time_Echo_us*0.017);像有这一句 filter_sum就不能int 了  只能float了,不然小数部分都 ...

好,谢谢您提醒
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-4-2 16:49:42 | 显示全部楼层
275891381 发表于 2017-3-28 11:21
filter_sum +=( Time_Echo_us*0.017);像有这一句 filter_sum就不能int 了  只能float了,不然小数部分都 ...

前辈,我今天又遇到一个不明白得地方,又得麻烦您帮我解答疑惑了。
是这样的,我看了下那个论坛上那个中位值平均滤波法。
中位值平均滤波法
  1. A、名称:中位值平均滤波法(又称防脉冲干扰平均滤波法)
  2. B、方法:
  3.     采一组队列去掉最大值和最小值后取平均值,
  4.     相当于“中位值滤波法”+“算术平均滤波法”。
  5.     连续采样N个数据,去掉一个最大值和一个最小值,
  6.     然后计算N-2个数据的算术平均值。
  7.     N值的选取:3-14。
  8. C、优点:
  9.     融合了“中位值滤波法”+“算术平均滤波法”两种滤波法的优点。
  10.     对于偶然出现的脉冲性干扰,可消除由其所引起的采样值偏差。
  11.     对周期干扰有良好的抑制作用。
  12.     平滑度高,适于高频振荡的系统。
  13. D、缺点:
  14.     计算速度较慢,和算术平均滤波法一样。
  15.     比较浪费RAM。
  16. E、整理:shenhaiyu 2013-11-01
  17. */

  18. int Filter_Value;

  19. void setup() {
  20.   Serial.begin(9600);       // 初始化串口通信
  21.   randomSeed(analogRead(0)); // 产生随机种子
  22. }

  23. void loop() {
  24.   Filter_Value = Filter();       // 获得滤波器输出值
  25.   Serial.println(Filter_Value); // 串口输出
  26.   delay(50);
  27. }

  28. // 用于随机产生一个300左右的当前值
  29. int Get_AD() {
  30.   return random(295, 305);
  31. }

  32. // 中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法1)
  33. #define FILTER_N 100
  34. int Filter() {
  35.   int i, j;
  36.   int filter_temp, filter_sum = 0;
  37.   int filter_buf[FILTER_N];
  38.   for(i = 0; i < FILTER_N; i++) {
  39.     filter_buf = Get_AD();
  40.     delay(1);
  41.   }
  42.   // 采样值从小到大排列(冒泡法)
  43.   for(j = 0; j < FILTER_N - 1; j++) {
  44.     for(i = 0; i < FILTER_N - 1 - j; i++) {
  45.       if(filter_buf[i] > filter_buf[i + 1]) {
  46.         filter_temp = filter_buf[i];
  47.         filter_buf[i] = filter_buf[i + 1];
  48.         filter_buf[i + 1] = filter_temp;
  49.       }
  50.     }
  51.   }
  52.   // 去除最大最小极值后求平均
  53.   for(i = 1; i < FILTER_N - 1; i++)
  54.   {
  55.      filter_sum += filter_buf[i];
  56.   }
  57.   return filter_sum / (FILTER_N - 2);
  58. }
复制代码


他这个采用冒泡法将值从小到大排列后,程序里面是怎么去掉的最大值和最小值的,这个部分不是很 明白。
能不能帮我讲解一下。我也不知道这个程序能不能把最大值最小值过滤掉。
回复 支持 反对

使用道具 举报

发表于 2017-4-2 17:49:02 | 显示全部楼层
GGG1101 发表于 2017-4-2 16:49
前辈,我今天又遇到一个不明白得地方,又得麻烦您帮我解答疑惑了。
是这样的,我看了下那个论坛上那个中 ...


for(i = 1; i < FILTER_N - 1; i++)
  {
     filter_sum += filter_buf;
  }
  return filter_sum / (FILTER_N - 2);

这地方去掉的呀,第一个最后一个没要,数量也-2了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-4-2 20:49:13 | 显示全部楼层
275891381 发表于 2017-4-2 17:49
for(i = 1; i < FILTER_N - 1; i++)
  {
     filter_sum += filter_buf;

谢谢,明白了
回复 支持 反对

使用道具 举报

发表于 2017-8-9 10:18:48 | 显示全部楼层
用中位值平均滤波法应该效果好点吧?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 09:37 , Processed in 0.045095 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表