Go Down

Topic: Ultrasonic distance sensor HC-SR04 lack of timeout problem (Read 66096 times) previous topic - next topic

docdoc

Yep, Tim, I agree it'd be a faulty sensor series (I already said I suspect the sensor is "too-much-chinese", no? :-) ), even if I have 3 of them, bought from two different ebay stores (none of them chinese), but other users also reported the same issue I experienced, so it's not so rare. So I solved definitely the problem buying some SRF05 instead of the cheaper SR04, but I wanted to make my library still compatible.

If you agree, I'd like to contribute to NewPing by suggesting you to add a workaround for those "faulty" sensors, to let it cover even such "chinenest" :-) ones: if SR04 is in this "locked" state it always returns zero "pulse duration" immediately, so this is what you could track down. This is the code portion of my workaround (looks similar to yours, I use "pulseDuration" variable you use "cm"), where the feature si activated if "Unlock" public variabile is set to true:

Code: [Select]

if ( Unlock && pulseDuration == 0 ) {
  // SR04 unlock
  pinMode(EchoPin, OUTPUT);
  digitalWrite(EchoPin, LOW);
  delay(100);
  pinMode(EchoPin, INPUT);
}


As I see no similar solution inside NewPing, I think you could include it in next NewPing release, if you want to. And adding an explicit reference to this issue, and how to fix it by setting "Unlock=true".
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

teckel

Yep, Tim, I agree it'd be a faulty sensor series (I already said I suspect the sensor is "too-much-chinese", no? :-) ), even if I have 3 of them, bought from two different ebay stores (none of them chinese), but other users also reported the same issue I experienced, so it's not so rare. So I solved definitely the problem buying some SRF05 instead of the cheaper SR04, but I wanted to make my library still compatible.

If you agree, I'd like to contribute to NewPing by suggesting you to add a workaround for those "faulty" sensors, to let it cover even such "chinenest" :-) ones: if SR04 is in this "locked" state it always returns zero "pulse duration" immediately, so this is what you could track down. This is the code portion of my workaround (looks similar to yours, I use "pulseDuration" variable you use "cm"), where the feature si activated if "Unlock" public variabile is set to true:

Code: [Select]

if ( Unlock && pulseDuration == 0 ) {
  // SR04 unlock
  pinMode(EchoPin, OUTPUT);
  digitalWrite(EchoPin, LOW);
  delay(100);
  pinMode(EchoPin, INPUT);
}


As I see no similar solution inside NewPing, I think you could include it in next NewPing release, if you want to. And adding an explicit reference to this issue, and how to fix it by setting "Unlock=true".

NewPing uses all port registers so that inside the library wouldn't be correct.  But, anyone could easily add the code I provided outside the library in their sketch.  Basically use NewPing as normal, but test for an invalid state and cycle the sensor (either by just cycling the power to the sensor or using the above method).

Doing it inside NewPing poses a few problems.  First, in the attempt to be as fast and small as possible, adding additional code for broken sensors seems a bit unwarranted. Also, as NewPing has methods which create event-driven pings, having something that breaks that for 100ms would also break your sketch or the ping polling process if multiple sensors are being pinged.  This would require the user to add additional code to their sketch to deal with this situation.

Instead, it seems more logical for the user to simply add a couple lines of code in their sketch if they happen to have a defective sensor and don't want to get a replacement.  Code in their sketch would be required anyway if they were polling multiple sensors in the background as I would *hightly* suggest anyway.

Then there's the problem of not having a defective sensor to be able to test any type of possible modification to the library.  Just dropping in some code that's not tested doesn't sound like the best idea.  Especially when using the ping_timer() method and associated sketches for multiple sensors in the background.

Anyway, here's what I would suggest doing for those that have a defective sensor and are using NewPing:

Code: [Select]
#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);   
  }
}


Just use the standard NewPing library as normal, but do a check for a bad state for your defective sensor and do the reset.  If this works, I can add a Wiki page for NewPing for people if they have a defective sensor that just shows a distance of 0 after getting no ping echo.

Again, I can't test this as all of my sensors work.  But, if someone could confirm this works, I'll be more than happy to build a Wiki page devoted to defective sensors.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

aisc

I have some of these HC-SR04 sensors. They are not all identical.
I actually run them in a sensor off an ATTiny85.

I would like to test for the fault being discussed.
Could someone please:
- post the minimal code that reveals the fault/problem
- describe the setup you are using
- how to check for the error

TIA.

teckel

I have some of these HC-SR04 sensors. They are not all identical.
I actually run them in a sensor off an ATTiny85.

I would like to test for the fault being discussed.
Could someone please:
- post the minimal code that reveals the fault/problem
- describe the setup you are using
- how to check for the error

TIA.
Using the NewPing library use the following sketch:

Code: [Select]
#include <NewPing.h>
NewPing sonar(11, 12);  // Trigger pin, echo pin.
void setup() {
  Serial.begin(115200);
}
void loop() {
  delay(50);
  Serial.println(sonar.ping_cm());
}


Sensor is connected to power, ground, pin 11 to trigger, and pin 12 to echo.  Monitor the distance measurement via the Serial Monitor in Arduino IDE.

To test for defective sensor, run the above sketch and you should get distance readings.  Then, point it in a direction it won't get an echo (nothing at least 5 meters away).  This will correctly give a zero (0) reading on the serial monitor.  Then, point the sensor back at something close to the sensor.  If the sensor is defective it will continue to report a zero (0) reading no matter where you point the sensor.  A working sensor will show zero (0) when there's no echo, but then show a reading when pointed towards something within close proximity.

I have over a dozen ultrasonic sensors, and all work correctly.  However, others have reported that they have many sensors and all fail using the above test.

Let me know if you have any questions.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

docdoc

To test for defective sensor, run the above sketch and you should get distance readings.  Then, point it in a direction it won't get an echo (nothing at least 5 meters away).  This will correctly give a zero (0) reading on the serial monitor.  Then, point the sensor back at something close to the sensor.  If the sensor is defective it will continue to report a zero (0) reading no matter where you point the sensor.
Exactly, this is my SR04s behavior. None of them are working, thus becoming almost useless. Unless I try to "recover" that deadlock, by either temporarily "physically" turning off the SR04, or with that software workaround I implemented in my SRF05 library.

By the way tonight I replaced my last SR04 with an SRF05 from one of my projects, so I'll definitely throw that away. I'm gonna buy a couple of SRF05 just to have a spare, I won't buy SR04 anymore,
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

aisc

Quote
Sensor is connected to power, ground, pin 11 to trigger, and pin 12 to echo.  Monitor the distance measurement via the Serial Monitor in Arduino IDE.

To test for defective sensor, run the above sketch and you should get distance readings.  Then, point it in a direction it won't get an echo (nothing at least 5 meters away).  This will correctly give a zero (0) reading on the serial monitor.  Then, point the sensor back at something close to the sensor.  If the sensor is defective it will continue to report a zero (0) reading no matter where you point the sensor.  A working sensor will show zero (0) when there's no echo, but then show a reading when pointed towards something within close proximity.

I have over a dozen ultrasonic sensors, and all work correctly.  However, others have reported that they have many sensors and all fail using the above test.

Let me know if you have any questions.

Tim
Thanks for the concise instructions. Now I just have to find somewhere with 5 metres of nothing - a tall order where I am :)

aisc

Well of my total of 5 sensors, I have 3 on hand and tested them. None have any problem being pointed to "infinity" (showing 0) then to something within range and displaying the distance.

Guess I must have gotten some from a "good batch" :)

I have saved the sketch as a "testing tool" - handy to have when buying more.
Thanks Tim.

SCION06

Tim I have tried your code with no avail. copied it directly.
Code: [Select]

#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);   
  }
}



Once the sensor returns to 0 (no echo) when something is in front of the sensor. it does not reset. Am I missing something?
thank you

teckel

Exactly, this is my SR04s behavior. None of them are working, thus becoming almost useless. Unless I try to "recover" that deadlock, by either temporarily "physically" turning off the SR04, or with that software workaround I implemented in my SRF05 library.

By the way tonight I replaced my last SR04 with an SRF05 from one of my projects, so I'll definitely throw that away. I'm gonna buy a couple of SRF05 just to have a spare, I won't buy SR04 anymore,

Could I have one of the defective SR04 sensors?  With it I could test and implement a deadlock recover in the NewPing library.

Also, if you have multiple sensors you're using in the same project, have you considered using the ping_timer() method with NewPing?  It would allow your sketch to never need to wait for the pings to process as it does everything in the background.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

teckel

Thanks for the concise instructions. Now I just have to find somewhere with 5 metres of nothing - a tall order where I am :)
Do you have "outside" where you are?  ;)

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

docdoc

Could I have one of the defective SR04 sensors?
Hm, sorry, I suspect it'd be an expensive test sending it from Italy to the States.. ;) Especially considering italian postal services efficiency.. ;)
Also, if you have multiple sensors you're using in the same project, have you considered using the ping_timer() method with NewPing?
No, I'll give it a try, but I think it won't make any difference because the problem seems to be on hardware side, and I don't have particular delays, the (in)famous "one second timeout", if I set a few milliseconds as a timeout (e.g. 50.000).

Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

docdoc

Once the sensor returns to 0 (no echo) when something is in front of the sensor. it does not reset. Am I missing something?
I think you should change the "if" Tim wrote.
When SR04 lis in deadlock, the Echo pin is stuck in HIGH state (that's why you get 0ms of high state delay!) so change it to:

Code: [Select]
  if (cm == 0 && digitalRead(ECHO_PIN) == HIGH) {
    pinMode(ECHO_PIN, OUTPUT);
    digitalWrite(ECHO_PIN, LOW);
    delay(100);
    pinMode(ECHO_PIN, INPUT);   
  }
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

aisc

Do you have "outside" where you are?  ;)

Tim
Lol - That was the plan, see reply #36.
Since my laptop's battery is shot, setting up outside with no nearby power source or extension lead was going to be a pain. Anyway the 8th floor window proved ideal.

SCION06

I think you should change the "if" Tim wrote.
When SR04 lis in deadlock, the Echo pin is stuck in HIGH state (that's why you get 0ms of high state delay!) so change it to:

Code: [Select]
  if (cm == 0 && digitalRead(ECHO_PIN) == HIGH) {
    pinMode(ECHO_PIN, OUTPUT);
    digitalWrite(ECHO_PIN, LOW);
    delay(100);
    pinMode(ECHO_PIN, INPUT);   
  }

Changed as you had suggested docdoc, But now it gives me very large numbers like in the hundreds when it is very close to my hand. I will go over my pins and make sure they are all correct. But that LOW to HIGH change worked.
Thank you.
Note, I am just testing singular sensors as I recently got some in the mail and just want them to work before I put them into a project.

docdoc

Changed as you had suggested docdoc, But now it gives me very large numbers like in the hundreds when it is very close to my hand.
Hm, what exactly gives you such large numbers? If it's the "cm" variable there's something wrong. If not, tell us where you read that (if you read hundreds, it'd be some time measure in microseconds?).
Quote
But that LOW to HIGH change worked. Thank you.
Good.
Quote
Note, I am just testing singular sensors as I recently got some in the mail and just want them to work before I put them into a project.
Hope you succeed, otherwise replace "put them into a project" with "throw them in a waste bin". :D And buy SRF05.
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

Go Up