GGG1101 发表于 2017-3-26 16:42:03

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

是这样的,我在论坛上看见十大滤波算法大全,上面的限幅滤波法怎么用在超声波测距上。我刚接触这个方面的东西,有些看不懂,耽误大家一点时间,我想问几个问题。

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

int Filter_Value;
int Value;

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

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

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

// 限幅滤波法(又称程序判断滤波法)
#define FILTER_A 1
int Filter() {
int NewValue;
NewValue = Get_AD();
if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    return Value;
else
    return NewValue;
}

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


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

GGG1101 发表于 2017-3-26 16:44:15

上面的int Filter_Value,Filter()啥意思呢

275891381 发表于 2017-3-26 19:39:19

GGG1101 发表于 2017-3-26 16:44
上面的int Filter_Value,Filter()啥意思呢

测距结果替换Get_AD();就可以了

GGG1101 发表于 2017-3-26 22:36:02

275891381 发表于 2017-3-26 19:39
测距结果替换Get_AD();就可以了

怎么替换,能不能给我详细的讲一下,兄弟

275891381 发表于 2017-3-27 11:54:20

GGG1101 发表于 2017-3-26 22:36
怎么替换,能不能给我详细的讲一下,兄弟

return random(295, 305); 这一句话换成测距结果就可以了

GGG1101 发表于 2017-3-27 17:52:17

前辈,谢谢你多次给我解答疑惑,麻烦你再看看 我写的这个正不正确。滤波部分是论坛10大滤波算法之一的算术平均滤波法(限幅滤波不怎么适合超声波,所以我换了一个)。这个原贴算术平均滤波法代码是这样的
/*
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));
   }
请你帮我看下我借鉴算术平均滤波法写的有没有问题,在液晶上面的显示也能显示的出来。但是我感觉测距结果还是和原来一样,同一个地方测距,放着不动,数值跳动有2CM上下浮动。 ,就这样的。好像不成功。我本意是在一个周期内多取几次超声波测量值,然后取平均值,显示在液晶上,这样想必稳定些,所以借鉴这个算术平均法,但情况不怎么理想,不知道是不是我理解错了。按道理取了平均值后,显示平均值在液晶上,跳动不会猛地变化,最少整数位不会出现2厘米浮动,小数位会变化。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。:)
   

      

GGG1101 发表于 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厘米浮动,同一个位置,超声波模块也没有拿在手上晃动。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。
   

275891381 发表于 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));
}

longget_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大滤波算法之一的算 ...

按你的意思应该是这样的

GGG1101 发表于 2017-3-28 11:15:36

275891381 发表于 2017-3-28 10:56
按你的意思应该是这样的

#include


谢谢前辈您帮代码整理的这么清晰,谢谢:)

275891381 发表于 2017-3-28 11:21:08

GGG1101 发表于 2017-3-28 11:15
谢谢前辈您帮代码整理的这么清晰,谢谢

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

GGG1101 发表于 2017-3-28 13:22:07

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

好,谢谢您提醒

GGG1101 发表于 2017-4-2 16:49:42

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

前辈,我今天又遇到一个不明白得地方,又得麻烦您帮我解答疑惑了。
是这样的,我看了下那个论坛上那个中位值平均滤波法。
中位值平均滤波法A、名称:中位值平均滤波法(又称防脉冲干扰平均滤波法)
B、方法:
    采一组队列去掉最大值和最小值后取平均值,
    相当于“中位值滤波法”+“算术平均滤波法”。
    连续采样N个数据,去掉一个最大值和一个最小值,
    然后计算N-2个数据的算术平均值。
    N值的选取:3-14。
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);
}

// 中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法1)
#define FILTER_N 100
int Filter() {
int i, j;
int filter_temp, filter_sum = 0;
int filter_buf;
for(i = 0; i < FILTER_N; i++) {
    filter_buf = Get_AD();
    delay(1);
}
// 采样值从小到大排列(冒泡法)
for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf > filter_buf) {
      filter_temp = filter_buf;
      filter_buf = filter_buf;
      filter_buf = filter_temp;
      }
    }
}
// 去除最大最小极值后求平均
for(i = 1; i < FILTER_N - 1; i++)
{
   filter_sum += filter_buf;
}
return filter_sum / (FILTER_N - 2);
}


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

275891381 发表于 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了

GGG1101 发表于 2017-4-2 20:49:13

275891381 发表于 2017-4-2 17:49
for(i = 1; i < FILTER_N - 1; i++)
{
   filter_sum += filter_buf;


谢谢,明白了

tianjitingyu 发表于 2017-8-9 10:18:48

用中位值平均滤波法应该效果好点吧?
页: [1]
查看完整版本: 新人求助怎么把限幅滤波算法应用在超声波测距上