HC-SR04 with NewPing library returning numbers other than zero when out of range

I have tried 4 different HC-SR04 sensors, and 2 different Arduino Uno boards, and when the ping is out of range, I normally get 0cm (as I should with NewPing). However, sprinkled in with the 0cm readings are 5cm, 6cm, 7cm, 8cm, 9cm readings. I have tried changing the delay from 30 mS to 100 mS, and get the same variation when out of range.

I am powering the ultrasonic sensor with +5V from the Arduino, and using a 2 wire system. The sensor works fine when in range.

Any ideas?

Here is my test code:

#include <NewPing.h>
     
#define TRIGGER_PIN  2
#define ECHO_PIN     3
#define MAX_DISTANCE 200
int distance;
    
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
     
void setup() {
  Serial.begin(115200);
}
     
void loop() {
  distance = (sonar.ping_cm());
      
  while (distance == 0) //NewPing is supposed to return 0
  {                     //when ping is out of range
    distance = (sonar.ping_cm());
    delay(50);
  }
  Serial.print(distance);  
  Serial.println("cm");
  delay(50);
}

Ok, after much googling, and more testing, I found my problem is related to the “Timeout Problem” as related here:

Using the code shown above, I found that my sensors have a 180 mS timeout when out of range.

See attachment.

It seems that sometimes after the timeout, the sensor will return a very short echo after the next request. This is what is causing the 5 cm or other short readings.

I have tried Tim’s code from the “Timeout” thread:

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
  delay(50);                     // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int cm = sonar.ping_cm();
  Serial.print("Ping: ");
  Serial.print(cm); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");

  if (cm == 0 && digitalRead(ECHO_PIN) == LOW) {
    pinMode(ECHO_PIN, OUTPUT);
    digitalWrite(ECHO_PIN, LOW);
    delay(100);
    pinMode(ECHO_PIN, INPUT);   
  }
}

For my case, this doesn’t help. Changing the ECHO pin to output just masks the echo signal, and it returns to high after the 100 mS delay. Even changing the delay to 200 mS to cover my full 180 mS timeout still allows the next reading to come through with a 5cm (or 6cm or other small number) value.

Next I am going to try using the Arduino digital output pin to provide power to the HC-SR04, and shut off the sensor if out of range.

The idea of powering the HC-SR04 from an Arduino output is working perfectly for me.

I used Tim’s code from post #31, modified with with DocDoc’s correction on the “If” (change “LOW” to “HIGH”)

and refinements for my particular sensors. The following code adds only 110 mS for a power reset on the sensor when an out of range is detected.

Notice, inside the IF loop, the section “delay(60); sonar.ping_cm();” may be deleted if your sensors do not return false echo after reset. I have 2 that do not need it. Total time added for reset is then only 50 mS.

#include <NewPing.h>

#define TRIGGER_PIN  2  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     3  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define USPOWER_PIN  4
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  pinMode(USPOWER_PIN, OUTPUT);
  digitalWrite(USPOWER_PIN, HIGH);
}

void loop() {
  unsigned int cm = sonar.ping_cm();
  Serial.print("Ping: ");
  Serial.print(cm); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  delay(30);                     // Wait 30ms between pings (about 30 pings/sec). 29ms should be the shortest delay between pings.
  
  if (cm == 0 && digitalRead(ECHO_PIN) == HIGH) {
    digitalWrite(USPOWER_PIN, LOW);
    delay(50);     // 50 mS is the minimum Off time to get clean restart
    digitalWrite(USPOWER_PIN, HIGH); // Adjust this value if your sensors don't read after reset
    delay(60);     // Some sensors throw out a very short false echo after timeout
    sonar.ping_cm(); // 5cm-10cm value.  If your sensors do not throw out
                   // this false echo, you can get rid of this delay and ping after power HIGH
  }                // Conversely, if you still get a false echo, you may need to increase
}                  // the delay.

I have a problem regarding do while loop in my arduino and I don’t know what it is…

#include <Servo.h>
#include <NewPing.h>

NewPing sonar(10, 11, 20);

Servo myservo;

void setup()
{
myservo.attach(8);
myservo.write(0);
myservo.detach();
delay(50);
}
void loop()
{
if (sonar.ping_cm() > 1)
{
myservo.attach(8);
myservo.write(90);
delay(1000);

do {
delay(1000);
}while (sonar.ping_cm!=0);

myservo.write(0);
delay(2000);
myservo.detach();