Ultrasonic sensor HC-SR04 delivers wrong distance

Hi together,

since this is my first post on the arduino forum I want to introduce myself. My name is Stefan, I am from Austria and I am a newbie in programming arduino. I have some experience in programming actually it is even my occupation but I work with Siemens Step7 which is a different story to arduino.

Now my problem: I have an ultrasonic sensor hc-sr04 but the data I get back is totally wrong . For example: The display shows 26,7cm but if I measure it manuallly I have 31cm.
Also it´s range seems to be wrong, according to the datasheet should be 2cm-4500cm, but if I try to point the sensor in direction of a wall, which is approximately 3000cm away, the numbers go crazy. I never see a stable value and also it want exceed about 1800cm.
I think the numbers for conversion are wrong but theese are the only ones I could find according to my sensor.

Here is my sketch:
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int trigger = 7; //output trigger
int echo = 8; //input echo
long duration, cm, inches;
int cmdec, indec;
int cmconv = 59; // ratio between pulse width and cm
int inchconv = 147; // ratio between pulse width and inches
//the numbers 59 and 147 i got from the Internet not sure if
//they are right, the range of the sensor is 2cm-4500cm (1,2inch-177inch)
String s1, s2;

void setup()
{
lcd.begin(16, 2);
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);
}

void loop()
{
//pulses for the input Trigger
digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW);

duration = pulseIn(echo, HIGH); //read return echo pulse lenght

// convert the time into the distances
cm = microsecondsToCentimeters(duration);
cmdec = (duration - cm * cmconv) * 10 / cmconv;
inches = microsecondsToInches(duration);
indec = (duration - inches * inchconv) * 10 / inchconv;

//printing data on LCD
s1 = String(cm) + “.” + String(cmdec) + “cm” + " ";
s2 = String(inches) + “.” + String(indec) + “inch” + " ";
lcd.setCursor(0, 0); // print cm on line 0
lcd.print(s1);
lcd.setCursor(0,1); // print inches on line 1
lcd.print(s2);

delay(100);
}

long microsecondsToCentimeters(long microseconds)
{
return microseconds / cmconv;
}

long microsecondsToInches(long microseconds)
{
return microseconds / inchconv;
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Thank´s for every help in advance and greetings

Stefan

Hi stefan

The Hc-sr04 is never 100% accurate normally about 1 cm out as for your measurement it depends where you are starting your manual measurement so i think that the range it is getting is correct.

also i havent used your type of conversion before but why dont you use the conversion type under examples/sensor/ ping from your IDE it work great for me the max distance I get is around 3.8m-4m it probably also depends on the density of the wall you targeting.

M...

but the data I get back is totally wrong . For example: The display shows 26,7cm but if I measure it manuallly I have 31cm.

Have you accurately calibrated the speed of sound at your location?

Hi,

I wrote a small piece of code to test mine one: here you have:

//////////////// PRUEBA DEL HC - SR04 //////////////

// Prueba del sensor de distancia por ultrasonidos HC - SR04

// Harware: Uno, HC - SR04 conectado "directamente" a los pines:

//  GND - GND
//  13  - Echo
//  12  - Trigger
//  11  - Vcc
//  
//(Se hace así para poder conectar el HC - SR04 directamente sobre el conector del "uno").

// CONSTANTES //

const int Anode = 11;
const int Echo = 13;
const int Trigger = 12;

float distance;
unsigned long duration;

void setup() 
{

Serial.begin(115200); 
  
pinMode(Anode, OUTPUT);
digitalWrite(Anode, HIGH);

pinMode(Trigger, OUTPUT);
digitalWrite(Trigger, LOW);

pinMode(Echo, INPUT);
}

void loop() {

digitalWrite(Trigger, HIGH);
delayMicroseconds (50);
digitalWrite(Trigger, LOW);



duration = pulseIn(Echo, HIGH);
distance = duration / 58.0;

Serial.print ("duration: ");
Serial.print (duration);
Serial.print ("   distance: ");
Serial.println (distance,1);
  
delay(2000);
  
}

I dont remember where the constant came from ... Any case, it works fine: I have deducted that the reference for measuring is the PCB itself.

Good luck.

Sorry, change "PCB" for "the front of the sensor 'eyes'" (the position of the mesh that protects the emitter and receiver).

I've mounted it again to check the accuracy: it gives me a +-2 mm resolution / accuracy very reasonable in beetwen 5.0 - 30.0 cm (every 5,0 cm -except for 20,0 cm that gives 20,8 cm, I dont know why).

I guess that the measure depends heavily on the surface of the reflecting object. Any case, I wonder what the manufacturer precision (if any :D) was intended; I dont think that the device has other use different from hobby one.

Regards

Hi together

thank´s for your answers. No I haven´t calibrated the speed of sound in my location. How to do this. And thanks for the sketch I will try it out. I am totally new in programming arduino and try to learn. Sry for the short statement but I am short in time!

Greetings Stefan

Have you accurately calibrated the speed of sound at your location?

Frankly, I have no notice of sound speed changing so much (in air) as to give such a big mistaken measure.

Regards.

Another thread on the subject:

http://forum.arduino.cc/index.php?topic=268473.0;topicseen

I can not say thank you as much as you guys try to support me with my problem. You´re awsome!!! It´s really nice getting help from all over the world

With a little deviation I can live that´s not a problem but mine is really bad and also it´s very unstable but now I have some points to start at for troubleshooting. I don´t think the surface is the problem since I tried a lot of different ones and always the same result. But I will try it with a peace of metal that should reflect sound very good. (I think). I´ll let you know if I am making progress on the problem.

@vffgaston: I hope I find the time tomorrow for trying out your sketch. Today I´m quite exhausted so I don´t have the energy anymore.

Greetings to all from Austria

Stefan

Greetings to all from Austria

A lot of Austria is some considerable height above sea-level - that's got to be worth calibrating-out.

A lot of Austria is some considerable height above sea-level - that's got to be worth calibrating-out.

The guy on the other thread uses the formula "c = 331.3 + T(Celcius) * 0.606 m/s" to correct the speed according to the air temperature. For a 10 ºC (or ºF) variation it gives 6.06 m/s, that is 2%, say 2 cm by m (meter of distance measured).

I do insist in the usage intended for this device (hobby). Nevertheless, I would use mine one (after testing; not calibrating) to detect a person passing by my desk or something similar; I can't imagine a duty that can be trusted to this device that is too crucial as to need calibration.

It's a matter, I think, of usage; I do not try to correct anyone on theoretical concerns.

@vffgaston: I hope I find the time tomorrow for trying out your sketch. Today I´m quite exhausted so I don´t have the energy anymore.

Pin assignation is made so you can connect the IR device directly to pins 11-12-13-GND of a UNO board (no need for anything else different of the two PCB's :D).

Regards

I was having problems with my HC-SR04 sensor readings jumping about everywhere and producing a lot of outliers.

I’ve managed to code around that by detecting if the jumps in the distance measured is to great, and just a once off.

if the distance difference between last reading and this reading is > 20cm and it’s the first time that difference has been measured then it’s counted as an outlier.

Note, I’m using this library - had nothing to do with my outlier readings though: GitHub - JRodrigoTech/Ultrasonic-HC-SR04: Ultrasonic HC-SR04 library for Arduino IDE

The Code:

#include <Ultrasonic.h>

// HR-SC04 SENSOR
#define TRIGGER_PIN   3
#define ECHO_PIN      2

Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN);

void setup() {
  Serial.begin(9600); 
}

// Global variables
int lastDistance = 0;
int thisDistance = 0;

void loop()
{
  // Copy over last distance
  lastDistance = thisDistance;
  
  // Get new this distance
  thisDistance = ultrasonic.Ranging(CM);
  
  if (outlierCheck(lastDistance, thisDistance)) {
    Serial.println("Outlier found: " + String(thisDistance));
  } else {
    Serial.println(String(thisDistance) + " cm");
  }
  
  delay(10);
}

// Check for significant jumps and outliers in sensor reading
bool outlierCheck(int lastDistance, int thisDistance) {

  // if the difference between measures is greater then 20cm, outlier found
  if ((lastDistance - thisDistance) > 20) {
    return true;
  } else {
    return false;
  }
}

The example output:

51 cm
51 cm
51 cm
51 cm
51 cm
Outlier found: 5
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
51 cm
Outlier found: 4
51 cm
51 cm

I have seen just too many posts highlighting the erroneous distance reports from the Ultrasonic distance sensor. This being my first day with the Arduino and the sensor, I was quite alarmed at this when I too got similar results. Well it didn't take long to put my finger on the culprit, it is the wide angle of the ultrasonic beam and the physical surroundings of the sensor that together play this mischief. If your test setup is in an anechoic chamber or if the sensor is a laser beam, you are certain to get rock steady readings. So in short, to make things work satisfactorily, just make sure that there are no extraneous objects/surfaces in a cone of 90 degrees between the sensor and the surface of intended object of measurement. Now you will be good to go on.