5

I have implemented 3 HC-SR04 ultrasonic-distance sensors into my hobby-project, and they are working randomly, meaning they sometimes give me anywhere between 1-12 readings from the sensors and then suddenly hang in the code. I am using 1 gpio pin to trigger all 3 sensors, but taking readings using multiple gpio pins (I have also tested with just one trigger and one echo and am getting the same error):

(Using 1k Ohm resistors btw)

enter image description here

enter image description here

import RPi.GPIO as GPIO
import time
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO_TRIGGER = 4
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)

ECHOS = {"ECHO_LEFT": 17, "ECHO_MIDDLE": 27, "ECHO_RIGHT": 22}
for e in ECHOS:
  GPIO.setup(ECHOS[e], GPIO.IN)

def distance(e):
  GPIO.output(GPIO_TRIGGER, True)
  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)

  while GPIO.input(e) == 0:
    pass
  start_time = time.time()

  while GPIO.input(e) == 1:
    pass
  end_time = time.time()

  time_elapsed = end_time - start_time
  dist = (time_elapsed * 34300) / 2
  return dist

  def run_distance():
    sensors = []
    for e in ECHOS:
      dist = distance(ECHOS[e])
      sensors.append("{}: {}".format(e, dist))
      time.sleep(1)
    return sensors

if __name__ == "__main__":
  while True
    print(run_distance())

It seems the problem occurs at this line: while GPIO.input(e) == 0:, for some reason it is getting stuck in an endless loop. Has anyone dealt with this issue before or maybe have an idea of what could be going wrong? I have done days worth of Googling but cannot come up with a solid solution.

All contributions to a solution are greatly appreciated!

UPDATED:

This code has been updated with a counter, that if reached within the problematic while-loop will break the process and start a new. The results are posted below as well:

import RPi.GPIO as GPIO
import time
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO_TRIGGER = 4
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)

ECHOS = {"ECHO_LEFT": 17, "ECHO_MIDDLE": 27, "ECHO_RIGHT": 22}
for e in ECHOS:
  GPIO.setup(ECHOS[e], GPIO.IN)

def distance(e):
  new_reading = False
  counter = 0
  GPIO.output(GPIO_TRIGGER, True)
  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)

  while GPIO.input(e) == 0:
    pass
    counter += 1
    if counter == 5000:
      new_reading = True
      break
  start_time = time.time()

  if new_reading:
    return False

  while GPIO.input(e) == 1:
    pass
  end_time = time.time()

  time_elapsed = end_time - start_time
  dist = (time_elapsed * 34300) / 2
  return dist

  def run_distance():
    sensors = []
    for e in ECHOS:
      dist = distance(ECHOS[e])
      sensors.append("{}: {}".format(e, dist))
      time.sleep(1)
    return sensors

if __name__ == "__main__":
  while True
    print(run_distance())

Results:

[{'ECHO_RIGHT': '-24.013984203338623'}, {'ECHO_MIDDLE': '-22.828209400177002'}, {'ECHO_LEFT': '-25.18749237060547'}]
[{'ECHO_RIGHT': '-24.422872066497803'}, {'ECHO_MIDDLE': '-22.32118844985962'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': '-22.341632843017578'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': '-23.98127317428589'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
[{'ECHO_RIGHT': 'False'}, {'ECHO_MIDDLE': 'False'}, {'ECHO_LEFT': 'False'}]
  • Should I just make the switch the Lidar? I am reading that it is more accurate than ultrasonic-distance sensors. – Ctpelnar1988 Apr 15 '18 at 3:59
  • 1
    I do not understand how you are getting negative readings. – joan Apr 19 '18 at 12:18
  • Also, it was a bad idea to use 1 trigger for all 3 sensors. If you think about it, when the trigger sends out a signal, all 3 sensors send out an ultrasonic distance pulse. Now in your while-loop you're listening for the echo to return to a specific sensor (middle sensor), but there is a possibility that your middle sensor picks up the pulse from the left or right sensor due to reflection, and gives you an incorrect reading. – Ctpelnar1988 Jul 16 '18 at 19:44
1

That's a known bug with that code. It seems to be copied with the bug included again and again. If you think about it you will hit that bug sooner or later. Both those while loops are faulty. You need to guard each with a timeout or similar.

  • Thank you for the reply Joan! I tried to implement a counter that, if reached within the problematic while-loop would break the current process and begin a new reading, triggering another ping and starting over again. The problem I encountered with that strategy is that the sensor never seemed to be able to pick up another reading/echo again after that, or does so extremely infrequently. I will update my code with the implementation I used. Actually, the idea came from one of your other threads on this subject ;) – Ctpelnar1988 Apr 15 '18 at 15:10
1

TLDR; I was using the wrong tool to take ultrasonic-distance calculations. The Arduino Uno is much, MUCH more accurate and reliable.

It seems since the Raspberry-Pi is not a micro-controller, it is unable to read the echos in "real-time", hence having to use a while-loop to listen for the echo, creating the possibility of completely missing it in some cases. Using a micro-controller like an Arduino to take the readings in "real-time" with functions like pulseIn(echo_pin_number, HIGH) and then sending those readings via serial communication to the Raspberry-Pi was the best course of action for me and now everything is working perfectly!

  • Amazing the difference Arduino makes despite its relatively dinky processor. However, depending upon where you're going with this, Arduino will run out of horsepower due to hardware, and there's just no solution for that. Raspberry Pi OTOH, has hardware horsepower in spades - it's the OS that cripples it for complex real time tasks. Anyway... before you get in too deep, you might consider an OS designed for this sort of thing. I'm looking at ChibiOS, no experience yet, but this link might help. Good luck. – Seamus Apr 22 '18 at 21:52
0

Try my program in C language, it deal with accidental loss of pulses and the noise:

http://kempny.stanpol.com.pl/examples/hcsr/dist.c

Compile it with wiringPi library:

cc dist.c -o dist -lwiringPi

Desciption of its operation (polish version only, perhaps google translation will help): http://kempny.stanpol.com.pl/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.