新人求助怎么把限幅滤波算法应用在超声波测距上
是这样的,我在论坛上看见十大滤波算法大全,上面的限幅滤波法怎么用在超声波测距上。我刚接触这个方面的东西,有些看不懂,耽误大家一点时间,我想问几个问题。/*
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;
}
这个是我转自论坛上大神写的限幅滤波算法代码。但我不知道怎么用在超声波测距上。
这个超声波测距有时候数据跳动比较大,我想让其平稳些.
怎么把超声波测距的数值放进上面这个滤波代码中呢? 上面的int Filter_Value,Filter()啥意思呢 GGG1101 发表于 2017-3-26 16:44
上面的int Filter_Value,Filter()啥意思呢
测距结果替换Get_AD();就可以了 275891381 发表于 2017-3-26 19:39
测距结果替换Get_AD();就可以了
怎么替换,能不能给我详细的讲一下,兄弟 GGG1101 发表于 2017-3-26 22:36
怎么替换,能不能给我详细的讲一下,兄弟
return random(295, 305); 这一句话换成测距结果就可以了 前辈,谢谢你多次给我解答疑惑,麻烦你再看看 我写的这个正不正确。滤波部分是论坛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厘米浮动,小数位会变化。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。:)
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厘米浮动,同一个位置,超声波模块也没有拿在手上晃动。我估计是把程序写错了,根本没有取到平均值,麻烦您给我指导整理一下,感激不尽。
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大滤波算法之一的算 ...
按你的意思应该是这样的
275891381 发表于 2017-3-28 10:56
按你的意思应该是这样的
#include
谢谢前辈您帮代码整理的这么清晰,谢谢:) GGG1101 发表于 2017-3-28 11:15
谢谢前辈您帮代码整理的这么清晰,谢谢
filter_sum +=( Time_Echo_us*0.017);像有这一句 filter_sum就不能int 了只能float了,不然小数部分都没了,细节多注意一点 275891381 发表于 2017-3-28 11:21
filter_sum +=( Time_Echo_us*0.017);像有这一句 filter_sum就不能int 了只能float了,不然小数部分都 ...
好,谢谢您提醒 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);
}
他这个采用冒泡法将值从小到大排列后,程序里面是怎么去掉的最大值和最小值的,这个部分不是很 明白。
能不能帮我讲解一下。我也不知道这个程序能不能把最大值最小值过滤掉。 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了 275891381 发表于 2017-4-2 17:49
for(i = 1; i < FILTER_N - 1; i++)
{
filter_sum += filter_buf;
谢谢,明白了 用中位值平均滤波法应该效果好点吧?
页:
[1]