How do I remove outliers in the data provided by the HC-SR04 ultrasonic sensor?

Whenever I use the project, I get large outliers, like 2000 cm+. This happens in between while i am moving and the next value that is recieved.

/*
 * This ESP8266 NodeMCU code was developed by newbiely.com
 *
 * This ESP8266 NodeMCU code is made available for public use without any restriction
 *
 * For comprehensive instructions and wiring diagrams, please visit:
 * https://newbiely.com/tutorials/esp8266/esp8266-ultrasonic-sensor-lcd
 */

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27 (from DIYables LCD), 16 column and 2 rows

#define TRIG_PIN D5 // The ESP8266 pin connected to Ultrasonic Sensor's TRIG pin
#define ECHO_PIN D7 // The ESP8266 pin connected to Ultrasonic Sensor's ECHO pin

float duration_us, distance_cm;

void setup() {
  lcd.init();               // Initialize the LCD I2C display
  lcd.backlight();          // open the backlight
  pinMode(TRIG_PIN, OUTPUT); // config trigger pin to output mode
  pinMode(ECHO_PIN, INPUT);  // config echo pin to input mode
}

void loop() {
  // Produce a 10-microsecond pulse to the TRIG pin.
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Measure the pulse duration from the ECHO pin
  duration_us = pulseIn(ECHO_PIN, HIGH);

  // calculate the distance
  distance_cm = 0.017 * duration_us;

  lcd.clear();
  lcd.setCursor(0, 0); // start to print at the first row
  lcd.print("Distance: ");
  lcd.print(distance_cm);

  delay(500);
}

A median filter is one popular approach.

ignore the value if it's too different from the previous one and make a note that you ignored a value (and after ignoring N values in a row, consider it might be right and go for it)

But, the maximum distance the sensor can get is 400 cm, 2000 cm is obviously wrong.

Do you recommend any libraries?

Example code can be found by web search, using the phrase "arduino median filter".

maximum distance the sensor can get is 400 cm

Then ignore any values over 400.

Try NewPing.

It does all the maths and pinging for you.

Tom... :smiley: :+1: :coffee: :australia:

Thanks, will try

Could you please provide an example?

Hi, @shivamhegadi

When you install the library, it will have examples.
Also the site I gave you has connection documentation as well.

Tom.. :smiley: :+1: :coffee: :coffee: :australia:

Did you not notice that the NewPing library has a median filter built in?

It's almost like there should be a button or trigger of some kind.

Sorry, I dont understand, i am new to arduino

If the device only collects data when a button or trigger is pressed or if it stops collecting when a button or trigger is pressed

then a button or trigger would control data collection one way or the other.

Then when you want to move the device you would make it stop collecting. I would go with collecting when triggered, point and trigger to get data and let up before moving it. But the other way it would need a press before moving and start collecting when let up. Either way you control when data is collected... hold the button to stop works when you want to walk away and still collect but if press means collect you can set it down and not collect.

That's two ways to cover two ways to use the device with only one button or trigger. Those aren't the only ways but they are the most simple... a double-click could make it work opposite for example. I think that I'd want a led that blinks whenever the device is collecting, the blink showing that the code isn't stuck.

This isn't specific to Arduino, it is user interface technique used in devices and computers going back over 50+ years!

I found the following to work very well.

  1. Take an odd number of readings I chose 9
  2. Use the sort utility to sort the 9 data points
  3. delete the highest two and lowest two
    4 Average the remaining data.

This works because any averaging of a over range reading will skew the data. My suggestion simply deletes the out of range numbers, without having to "test" each value for out of range.

Sort the data but not test for wildly out of range?

A close relative of the median filter.

1 Like

Perhaps a cousin :slight_smile: