Ultraschallsensor misst nur einmal, danach verrent sich Skript in While

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Kaktus5947
User
Beiträge: 2
Registriert: Freitag 8. Juli 2022, 07:36

Moin Moin,
Ich möchte gerne einfach nur einen Ultraschallsensor auslesen... Dazu nutze ich den vorgefertigten Skript auf https://tutorials-raspberrypi.com/raspb ... r-hc-sr04/ der aussieht wie folgt:

Code: Alles auswählen

#Libraries
import RPi.GPIO as GPIO
import time
 
#GPIO Mode (BOARD / BCM)
GPIO.setmode(GPIO.BCM)
 
#set GPIO Pins
GPIO_TRIGGER = 18
GPIO_ECHO = 24
 
#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
 
def distance():
    # set Trigger to HIGH
    GPIO.output(GPIO_TRIGGER, True)
 
    # set Trigger after 0.01ms to LOW
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)
 
    StartTime = time.time()
    StopTime = time.time()
 
    # save StartTime
    while GPIO.input(GPIO_ECHO) == 0:
        StartTime = time.time()
 
    # save time of arrival
    while GPIO.input(GPIO_ECHO) == 1:
        StopTime = time.time()
 
    # time difference between start and arrival
    TimeElapsed = StopTime - StartTime
    # multiply with the sonic speed (34300 cm/s)
    # and divide by 2, because there and back
    distance = (TimeElapsed * 34300) / 2
 
    return distance
 
if __name__ == '__main__':
    try:
        while True:
            dist = distance()
            print ("Measured Distance = %.1f cm" % dist)
            time.sleep(1)
 
        # Reset by pressing CTRL + C
    except KeyboardInterrupt:
        print("Measurement stopped by User")
        GPIO.cleanup()
Wenn ich den Raspberry Pi reboote funktioniert dieses Skript genau ein Mal normal, eine Messung wird durchgeführt und ausgegeben, danach kommt er nicht mehr über die zweite while-schleife drüber. Reset hilft auch nichts, nur ein reboot, und dann auch nur einmal. Mein Sensor ist derselbe wie der auf der Website. Hat jemand eine Idee?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Auch wenn das Skript grauenvoll ist, ein fundamentales Problem, dass das erklärt, damit sehe ich erstmal nicht. Ich habe aber in der Vergangenheit Probleme mit diesen Sensoren gehabt, weil sie 5V haben wollen. Und such wenn der ECHO-Kanal durch den Spannungsteiler adaptiert wird, der Trigger ist es nicht. Ein Versuch könnte also ein bi-direktionaler Level-Shifter sein.

Wirklich Debuggen kann man das nur mit einem Oszilloskop oder Logicanalyzer in meinen Augen. Denn du musst verstehen, wie die Signale da aussehen.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Variablennamen schreibt man nach Konvention klein.
GPIO.cleanup darf nicht nur bei CTRL+C aufgerufen werden, sondern muß immer bei Programmende aufrgerufen werden.
Busy-Loops sind schlecht, und machen die Messung noch etwas ungenauer.
Du hast keinen Timeout.
Der Funktionsname `distance` ist sehr schlecht, weil es verhindert, dass Du der Variable einen ordentlichen Namen geben kannst.

Code: Alles auswählen

from RPi import GPIO
import time

TRIGGER_PIN = 18
ECHO_PIN = 24


def initialize():
    #GPIO Mode (BOARD / BCM)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(TRIGGER_PIN, GPIO.OUT)
    GPIO.setup(ECHO_PIN, GPIO.IN)


def measure_distance():
    GPIO.output(TRIGGER_PIN, True)
    time.sleep(0.00001)
    GPIO.output(TRIGGER_PIN, False)

    channel = GPIO.wait_for_edge(ECHO_PIN, GPIO.BOTH, timeout=200)
    if channel is None:
        print("Ultrasonic sensor timed out (pre-echo).")
        return None
    start = time.time()
          
    GPIO.wait_for_edge(ECHO_PIN, GPIO.BOTH,  timeout=400)
    if channel is None:
        print("Ultrasonic sensor timed out (post-echo).")
        return None
    stop = time.time()
   
    elapsed = stop - start
    return elapsed * 34300 / 2 # Using speed of sound at 20C


def main():
    try:
        initialize()
        while True:
            distance = measure_distance()
            print(f"Measured Distance = {distance:.1f} cm")
            time.sleep(1)
 
    except KeyboardInterrupt:
        print("Measurement stopped by User")
    finally:
        GPIO.cleanup()


if __name__ == '__main__':
    main()
Kaktus5947
User
Beiträge: 2
Registriert: Freitag 8. Juli 2022, 07:36

@Sirius3:
/home/pi/Desktop/pythonforum.py:11: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(TRIGGER_PIN, GPIO.OUT)
Ultrasonic sensor timed out (pre-echo).
Traceback (most recent call last):
File "/home/pi/Desktop/pythonforum.py", line 51, in <module>
main()
File "/home/pi/Desktop/pythonforum.py", line 41, in main
print(f"Measured Distance = {distance:.1f} cm")
TypeError: unsupported format string passed to NoneType.__format__
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie ich schon sagte: es liegt nicht an deinem Code. Sirius3 Umschreibung ist vielleicht schoener und besser, aber aendert immer noch nichts am eigentlichen Problem: wenn die Flanke nicht kommt, misst du nunmal nix. Und kann daher auch kein besseres Verhalten erzwingen.

Darum: lies nochmal meinen Post, und versuch das.
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Auch wenn das Problem hier nicht der Code ist, möchte ich dennoch das viel schönere gpiozero ins Spiel bringen. Das bringt auch schon etwas für diesen Sensor mit: https://gpiozero.readthedocs.io/en/stab ... nce-sensor :wink:
Alles was wir sind ist Sand im Wind Hoschi.
Antworten