GPIO

Entfernung messen mit Ultraschallsensor HC-SR04 – Raspberry Pi

Beim vielen (Außen-)Projekten ist eine Abstandsmessung nötig oder von Vorteil. Diese kleinen Module gibt es bereits ab 1-2€ und können die Entfernung bis zu 4,5m per Ultraschall messen und sind dabei erstaunlich genau. Der Anschluss und die Ansteuerung wird in diesem Tutorial gezeigt.



 

Zubehör

 

Aufbau

Auf dem Ultraschall Modul sind 4 Pins, die an das Raspberry angeschlossen werden:

  • VCC an Pin 2 (VCC)
  • GND an Pin 6 (GND)
  • TRIG an Pin 12 (GPIO18)
  • an ECHO wird der 330Ω Widerstand angeschlossen.  An dessen Ende geht eine Verbindung zu Pin 18 (GPIO24) und über den 470Ω Widerstand eine Verbindung zu Pin6 (GND).

Dies machen wir, da die GPIO Pins nur max. 3.3V vertragen. Die Verbindung zu GND ist aufgrund dessen, damit ein eindeutiges Signal an GPIO24 anliegt. Wird kein Impuls gesendet ist durch die Verbindung mit GND das Signal auf 0, bei einem Signal 1. Wäre keine Verbindung zu GND hergestellt, wäre bei fehlendem Signal der Zustand undefiniert (je nach Zufall 0 oder 1), also nicht eindeutig.

Hier noch der Aufbau als Schaubild:

ultraschall_Steckplatine
 

Skript zur Ansteuerung

Zu erst einmal sollte die Python GPIO Library installiert sein. Ist dies nicht der Fall, kannst du am Anfang dieses Tutorials nachlesen, wie dies geht.

Um das Modul nutzen zu können erstellen wir also ein neues Skript

sudo nano ultraschallsensor_entfernung.py

mit folgendem Inhalt:

Danach führen wir noch aus:

sudo python ultraschallsensor_entfernung.py

Damit wird nun jede Sekunde der Abstand gemessen, bis das Skript mittels STRG+C abgebrochen wird.
Das war es auch schon. Die Einsatzorte sind zahlreich, wer noch größere Abstände messen will, müsste auf ein Lasermessgerät zurückgreifen, welche allerdings um einiges teurer sind.



, , , , ,


100 Kommentare

  1. Martin Bruckner sagt:

    Guten Tag,

    wie lange darf das Kabel vom Pi zum Sensor maximal sein?

    mfg,
    Martin

    • Felix sagt:

      Hallo,

      das kommt hauptsächlich auf das Kabel an. Bei normalen Jumper Kabel sind 20-30cm ideal, bei höherwertigen Kabeln evtl. auch mehr. Das hat mit dem Spannungsabfall zu tun, daher würde ich es individuell testen.

      LG
      Felix

  2. Michael sagt:

    Hi,
    schöne Beschreibung nur eine Frage
    funktioniert mit 1 k und 2 k Wiederstand aber sehr ungenau
    bei 330 — 470 Ohm überhaupt nicht

    Eine Idee ?

    • Florian sagt:

      Hallo Michael,

      bei mir ist das selbe Problem. Ich habe auch einen Spannungsteiler von 330ohm und 470ohm benutzt und bekomme an meinem Raspberry Pi B + ständig nur folgenden Fehler.

      UboundLocalError: local varable ‚StopZeit‘ referenced before assignment

      Kann hier jemand weiterhelfen?

    • Felix sagt:

      Hi,
      versuche mal die zweite Zeile hiervon hinzuzufügen (Zeile 25):

        StartZeit = time.time()
        StopZeit = time.time()

      Habe das oben aktualisiert.

    • Daniel sagt:

      Hallo Florian,

      hat der Tipp von Felix bei Dir funktioniert oder hast Du eine andere Lösung gefunden?

      Gruß Daniel

  3. Maxe sagt:

    wenn ich jetzt aber öfters in der sekunde messem möchte z.B. alle 0.001 sekunden oder so wie mache ich das und komme ich irgendwann an die grenezen der technik?

    • Felix sagt:

      Hi Maxe,
      ich hatte mal einen Test mit den GPIOs und der Motorsteuerung gemacht, wobei die maximale Grenze mit Python bei 0.005 Sekunden waren (soviel ich mich erinnere). Evtl. ist mit C/C++ noch ein wenig mehr drin, aber wie du richtig gesagt hast, stößt man dann auch an die Grenzen der Hardware.

    • Maxe sagt:

      ok danke aber wie bringe ich das ich den code?

      etwa so?

        try:
          while True:
            abstand = distanz()
            print ("Gemessene Entfernung = %.1f cm" % abstand)
            time.sleep(0.005)
       
        # Beim Abbruch durch STRG+C resetten
        except KeyboardInterrupt:

      oder wo dann?

    • Felix sagt:

      Ja das würde klappen, wobei du die Zeit des Ultraschalls mit einberechnen musst. Hast du also z.B. einen Gegenstand der 3.5m weit weg ist würde die „Berechnung“ nochmal ca. 0.02 Sekunden dauern (350/34300 * 2). Je nach Abstand kann das variieren.

    • Skippy1411 sagt:

      Ja der Schall braucht ja schon länger als das was du sagst ^^

  4. Pippo sagt:

    Sehr schönes Tutorial, hat dank guter Erklärung auf anhieb geklappt.

    Ist es möglich die gemessenen Werte in einer Datei abzuspeichern? Wenn ja, wie kann ich dies bewerkstelligen?

    lg
    pippo

  5. Pippo sagt:

    Erst einmal Danke für deine Schnelle Antwort, Felix!

    Wo genau würde ich diesen Block im Skript einfügen, ist Zeile 50 richtig?

    Leider ist mir auch nicht ganz klar wie ich es hin bekomme, dass die gemessen Abstände in die txt.Datei geschrieben werden.

    lg
    Pippo

    • Felix sagt:

      Eine Möglichkeit wäre so:

      if __name__ == '__main__':
        try:
          file_out = open("Testdatei.txt","a")
          while True:
            abstand = distanz()
            print ("Gemessene Entfernung = %.1f cm" % abstand)
            file_out.write("%.1f cm\n" % abstand)
            time.sleep(1)
       
        # Beim Abbruch durch STRG+C resetten
        except KeyboardInterrupt:
          print("Messung vom User gestoppt")
          GPIO.cleanup()
          file_out.close()

      Du musst die Datei erst einmal öffnen. Mit dem file_out.write("test") schreibst du „test“ in das Dokument (Achtung: es macht danach keinen Zeilenumbruch). Danach schließt du die Datei, um zu speichern.
      Beim Öffnen gibt es verschiedene Modi wie „r“ (nur zum lesen), „w“ (zum Schreiben, allerdings wird dadurch der vorherige Inhalt der Datei gelöscht) und „a“ (zum Schreiben am Ende der Datei, ohne dass das vorherige gelöscht wird).
      Zum Einfügen eines Zeilenumbruchs fügst du ein „\n“ an das Ende jeder Zeile hinzu (siehe Beispiel oben).

  6. Pippo sagt:

    Ich danke dir vielmals! Genauso hatte ich mir das vorgestellt. :)

  7. Raspi_newbie sagt:

    Kurze Verständnis-Frage: Du schreibst oben im Abschnitt „Aufbau“, dass „an ECHO wird der 330Ω Widerstand angeschlossen. An dessen Ende geht eine Verbindung zu Pin 16 (GPIO23)“ aber im Bild und im Script ist von GPIO.ECHO=24 die Rede. Muss es daher nicht „an ECHO wird der 330Ω Widerstand angeschlossen. An dessen Ende geht eine Verbindung zu Pin 16 (GPIO24)“ heissen?

    • Felix sagt:

      Du hast vollkommen recht, das war ein Tippfehler der mir so nicht aufgefallen ist. Der Code und das Bild stimmen, die Nummer habe ich eben verbessert. Vielen Dank für den Hinweis.

  8. David sagt:

    Hallo,

    vielen Dank für Deine Ausführungen!
    Könntest Du noch erklären, wie genau sich die 330 und 470 Ohm ergeben, ausgehend vom vorgeschlagenen 5V/2mA Bauteil?
    Warum die parallele Anordnung des 470Ohm Widerstands?
    Benötigt der Trigger keine 5V sondern nur die 3,3V des Pins? Aber das Echo schickt 5V zurück?

    Ich hoffe meine Fragen sind nicht zu konfus! Vielen Dank für die Antworten von einem lernwilligen Laien!

    • Felix sagt:

      Hallo David,
      der erste Widerstand (330Ohm) ist dazu, dass keine zu große Spannung auf den GPIO kommt, da maximal 3.3V erlaubt sind. Der zweite Widerstand folgt dem Prinzip des Pull-Down, wenn nämlich keine Spannung an den GPIO gelangt, spuckt er zufällig entweder 0 oder 1 aus. Um das zu verhindern nehmen wir einen größeren Widerstand und verbinden ihn zu Ground, wodurch immer entweder eine positive oder „negative“ Spannung an den GPIO kommt.

    • David sagt:

      Vielen Dank für die Antwort mit Link.
      Das sind sehr interessante Details, in die ich mich einlesen werde!

  9. Jon sagt:

    Danke für das Tutorial, du hast das echt sehr gut erklärt. Besonders dieses Projekt ist als Anfänger (wie ich es bin) leicht umzusetzen!

  10. Thale sagt:

    Hallo,
    muss der Trigegr an den GPIO 18 angeschlossen werden und könnte man auch mehrere Modulle anschließen?

    • Felix sagt:

      Hallo,
      wenn du jeweils im Code die Nummer änderst kannst du auch mehrere Module anschließen.

  11. Matze sagt:

    Hi,

    erstmal Danke für das coole Tutorial! :)
    Allerdings klappt das bei mir noch nicht so recht. Habe alles wie beschrieben angeschlossen und das Skript als Superuser im Terminal ausgeführt.
    Sobald das Skript startet, ist der Cursor im Terminal zu sehen und die RAM-Auslastung ist bei 100%. Mehr passiert aber auch nicht. :( Ich kann das Skript dann maximal mit STRG+C stoppen (Der Code-Teil geht also).
    Hat jemand nen Tipp, wo das Problem liegen könnte??
    (Nutze im Übrigen das 2015-02-16 Raspbian Wheezy Image und nen Raspberry Pi Model B+ V1.2)

    Die besten Grüße
    Matze

    • Felix sagt:

      Bist du alle Anschlüsse nochmal durchgegangen und nutzt die richtigen Widerstandsgrößen? Oftmals hängt sich der Pi aufgrund falsch angeschlossener Pins auf.

    • Matze sagt:

      Die Widerstände und Anschlüsse passen soweit.Gibts ne Möglichkeit die Pins auf Funktionsfähigkeit zu testen (rein softwareseitig)? LEDs hab ich gerade nicht auf Lager. 😐

    • Felix sagt:

      Rein softwareseitig wüsste ich nichts, aber du könntest z.B. einige Pins als Input deklarieren und über einen, als Output deklarierten Pin kurz mal Signale senden und alle Input Pins loggen, nachdem du den Output Pin mit allen Input Pins verbunden hast. Erkennen es alle richtig, weißt du, dass sie funktionieren.

  12. Matze sagt:

    Manchmal trifft Kopf -> Tischkante. -.- Ich dachte echt, ich hab alles 5 mal gecheckt. Aber der erste Widerstand hing hinter dem GND vom Sensor, statt hinter ECHO… Jedenfalls funktioniert jetzt alles. 😀

    Beste Dank und viele Grüße,
    Matze

  13. Matze sagt:

    Hi,

    nachdem der Ultraschallsensor tut was er soll, wollte ich mal probieren, ob ich in Abhängigkeit der gemessenen Entfernung, den Raspi durch die Gegend fahren lassen kann. Habe dazu das in diesem Tutorial vorgestellte Skript (insbesondere die while-Schleife) etwas erweitert:

    #GPIO-Pins zuweisen
    GPIO_M1v = 7
    GPIO_M2v = 13
    GPIO_M1r = 11
    GPIO_M2r = 15
    
    #Richtung der GPIO-Pins festlegen (IN / OUT)
    GPIO.setup(GPIO_M1v, GPIO.OUT)
    GPIO.setup(GPIO_M2v, GPIO.OUT)
    GPIO.setup(GPIO_M1r, GPIO.OUT)
    GPIO.setup(GPIO_M2r, GPIO.OUT)
    
    def distanz():
    ...
    
    #Zeit initialisieren
    AddTime = [0]
    	 
    try:
      while True:
        #Ausgabe der Entfernung aller Sekunde
        CurrentTime = [int(time.time())]
        AddTime = AddTime + CurrentTime
        abstand = distanz()
        if max(AddTime) > AddTime[-2]:
            print ("Gemessene Entfernung = %.1f cm" % abstand)
        else:
    	pass
    
        #Wenn Abstand groeßer 50 cm, dann geradeaus fahren
        if abstand => 50:
    	GPIO.output(7,True)
    	GPIO.output(13,True)
    	time.sleep(0.1)
    	GPIO.output(7,False)
    	GPIO.output(13,False)
    	time.sleep(0.001)
         #Sonst: 90 Grad Rechtsdrehung
         else:
    	GPIO.output(7,True)
    	GPIO.output(15,True)
    	time.sleep(0.97)
    	GPIO.output(7,False)
    	GPIO.output(15,False)
    	time.sleep(0.001)
    			
    # Beim Abbruch durch STRG+C resetten
    except KeyboardInterrupt:
       print("Messung vom User gestoppt")
       GPIO.cleanup()
    

    Da ich allerdings blutiger Python-Anfänger bin, sieht das ganze sicher optimierungsbedürftig aus (zumal er im Live-Betrieb trotzdem „nur“ die Entfernung misst, aber nicht fährt 😀 ).
    Habe den Raspi mit einem L298N verbunden, der als Controller für die beiden Wechselstrommotoren fungiert. Daher ergeben sich auch die Pin-Zuweisungen (z.B. „GPIO_M1v = 7“ steuert den 1. Motor vorwärts).

    Hat zufällig jemand ne Idee, was im Skript noch verbessert werden könnte, damit die „Karre“ auch tatsächlich fährt? 😀 …Oder ist es besser den Kram schnellstmöglich zu vergessen, den ich geschrieben habe und nochmal neu zu coden. :)

    Die besten Grüße,
    Matze

    • Felix sagt:

      Vorweg zwei Dinge: Du weißt GPIO_M1v = 7 usw. zu, aber benutzt trotzdem GPIO.output(7,True). Der Sinn der Variablen Zuweisung ist, dass du eben keine Nummern mehr benutzen musst. Zweitens: Wieso initialisierst du Addtime als Array/Liste? ein einfaches time.time() reicht vollkommen. Die Zeile if max(AddTime) > AddTime[-2]: ist mir auch ein wenig schleierhaft.

      Benutzt du einen Schrittmotor? Wenn ja wie viele Schritte hat er? Falls nur vier, sollte es funktionieren, da du ja nur einen Schritt (also 90°) machst. Falls er wie die üblichen Motoren mehr Schritte hat, musst du auch mehr Schritte machen, um 90° zu erreichen. Schau dir am besten dazu nochmal dieses Tutorial an: Schrittmotor steuern mittels L293D / ULN2003A

      PS: Falls du es neu coden willst, schreib nochmal bitte kurz was es machen soll (und in welcher Reihenfolge vor allem), damit ich besser helfen kann.

    • Matze sagt:

      Ziele sind:
      1. Der fahrende Roboter soll mittels Sensor ständig (also pro Schleifendurchlauf 1mal) die Entfernung messen, aber nur aller Sekunde im Terminal ausgeben (daher das Initialisieren von AddTime als Liste und die dazugehörige spätere if-Bedingung).
      2. Beträgt die gemessene Entfernung mehr als/gleich 50 cm, soll der Robo einfach geradeaus fahren. (Ich nutze im Übrigen keinen Wechselstrommotor *facepalm*, sondern einen Gleichstrom-Getriebemotor.)
      3. Ist der Abstand zum Hindernis kleiner als 50 cm, soll der Robo einen Motor vorwärts und einen rückwärts laufen lassen und somit eine 90°-Drehung machen.

      Mehr soll er eigentlich erstmal nicht können. Was die time.sleep()-Zeiten bei den Motoren angeht, hab ich mich ein wenig von diesem Tutorial inspieren lassen: https://www.youtube.com/watch?v=AZSiqj0NZgU

    • Felix sagt:

      Am besten du definierst dir erst einmal Funktionen mit Parametern, die die Aufgaben erledigen (Fahren, Bewegen, messen, etc.)
      In deiner Hauptfunktion rufst du dann über eine Endlosschleife einmal die Distanz-Funktion auf und überprüfst ob der zurückgegebene Wert unter 50cm ist. Falls ja führst die Motor-Bewegungen aus, falls nein wird die Weiterfahr-Funktion aufgerufen.
      Wenn du bei den Funktionen Hilfe brauchst, sag Bescheid.

      LG Felix

  14. Klaus100000 sagt:

    Hallo,
    erstmal eine tolle Sache.

    Besteht eine einfache Möglichkeit das Programm im Hintergrund laufen zulassen und von einem anderen Programm die daten anzufordern??

    Also das Mess modul warte auf anforderung.

    Hautprogramm sagt mess mal
    Messmodul sagt ok
    misst
    und gibt die messung zurück.

    Warum

    ich finde es einfacher wenn alle Sensoren in kleine Programme laufen,
    und die Hauptprogramme das system fragen welche Sensoren sind online und man brauch sich nicht immer darum kümmern.

    Ich hoffe ich habe mich verständlich ausgedrückt.

    Gruss Klaus100000

    • Felix sagt:

      Du kannst ein extra Skript (Python oder bash) erstellen, welches du bei Bedarf aufrufst und dir die Daten zurück gibt.
      Falls es im Hintergrund laufen soll, kannst du alle X Zeiteinheiten (einfache Schleife z.B.) die erhobenen Daten in eine Datei schreiben. Schau dir dazu am besten screen an und wie man ein Skript automatisch beim booten startet.

  15. Torsten sagt:

    Hallo Felix,

    danke für das schöne Tutorial. Mich würde das Schaubild für den Anschluss von zwei Modulen interessieren. Dein Beispiel funktioniert bei mir tadellos. Ich vermute, dass ich „einfach“ einen weiteren „Trigger-Pin“ nutze. Leider habe ich als blutiger Anfänger keinen Schimmer, wie ich das ganze dann verkable – bzw. wo ich die Widerstände platziere.

    Grüße,
    Torsten

    • Felix sagt:

      Hallo Torsten,
      der Aufbau eines zweiten Moduls wäre identisch mit dem des ersten (für ECHO und TRIGGER müssen natürlich freie GPIOs verwendet werden), Widerstände inklusive. 5V und Ground werden parallel an alle Module angeschlossen. Den Code müsstest du mit den enstprechend gewählten GPIOs erweitern.
      LG Felix

  16. jo hann sagt:

    Hallo,
    danke erst mal für die Anleitung.
    Ich habe ein Problem. Und zwar spuckt er mir immer folgende Fehlermeldung aus:

    Traceback (most recent call last):
    File „/home/pi/ultraschallsensor_entfernung.py“, line 13, in
    GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
    RuntimeError: No access to /dev/mem. Try running as root!

    Ich habe auch schon die Datei mem für alle frei gegeben und es als root gestartet. Hilft alles nichts.
    Es ist alles richtig angeschlossen und setup hab ich auch installiert.
    Es kommt immer wieder die selbe Fehlermeldung.

    Danke und viele Grüße
    Johann

  17. Christian sagt:

    Hallo,

    kann man nur das Programm mit der Konsole starten oder auch irgendwie über Python? Ich möchte es nämlich gerne in ein anderes Programm einschleusen und über eine GUI via Button starten, damit später auch andere einfach das System nutzen können.
    Kann mir da jemand weiterhelfen?

    Danke
    Chris

    • Felix sagt:

      Über die Konsole starten kannst du es sowieso: sudo python ultraschallsensor_entfernung.py
      Du kannst es auch in anderen Skripten einbinden, dann musst du allerdings folgendes löschen (und daruffolgende Tabs):

      if __name__ == '__main__':

      Das bewirkt, dass der nachfolgende Code nur ausgeführt wird, falls die Datei direkt aufgerufen wurde und nicht, falls in einem anderen Skript eingebunden.

  18. Peter sagt:

    Hallo Felix,
    ich möchte gerne zwei Sensoren über einen Button im GUI starten lassen. Es klappt schonmal, dass ich zeitgleich von beiden Sensoren die Werte bekomme, wenn ich es normal starte.
    Wenn ich jedoch einen Button damit belegen will, komme ich auf Probleme, da ein Button nur eine Funktion abfragen kann. Wenn ich mit ‚and‘ die Funktionen verbinde, bekomme ich nur den ersten Wert von der ersten Funktion aus.
    Ich habe jetzt ja drei Funktionen. Zwei für die Sensoren und die ‚main‘ für die Ausgabe und Speichung in einer Datei.
    Hast du da eine Lösung?

    Besten Dank vorweg für deine Hilfe,

    Peter

    • Felix sagt:

      Ein paar mehr Infos wären gut: Hast du zwei unabhängige Skripte für die Abfrage der Sensoren? Ist es eine Python GUI oder webbasiert?
      Ruf mit dem einen Button z.B. eine Fkt aus, mit dem anderen eine andere.

    • peter sagt:

      ich habe alles in einem Skript geschrieben in einer Python GUI. Mein Ziel ist es, das mit einem Button beide bzw. später möglichst vier Sensoren zeitgleich mit der Messung starten, da sie jede Sekunde zur selben Zeit und somit am richtigen Ort messen sollen.

      Ich habe es so versucht, alles in einer Funktion zu schreiben, dann wird aber die Startzeit der Messung an der zweiten Stelle (Beispiel unten: StartTime2) um ca. 0.001 eher gestartet, was für mich unerklärlich ist. Und bei dem Sensor kommen somit zu große Distanzen heraus und teilweise auch wirre Ergebnisse von -324,423 m.

      Ich habe schon so viele verschiede Sachen ausprobiert, komme aber leider nicht weiter. Bin leider auch nicht der beste Programmierer :)

      from tkinter import *
      from tkinter import messagebox
      #from time import sleep
      import picamera
      import os
      import time
      
      
      ######################
      
      import RPi.GPIO as GPIO
      
      # define GPIO pins
      GPIOTrigger1 = 18
      GPIOEcho1    = 24
      GPIOTrigger2 = 17
      GPIOEcho2    = 23
      
      Temperatur = 25   #### Hier aktuelle Temperatur eingeben in °C ######
      
      
       
      
      #############################################
      
      #==============================================================
      # Declaration of Constants
      # none used
      
      #==============================================================
      
      class Application(Frame):
          """ GUI Application for taking photos. """
      
          def __init__(self, master):
              super(Application, self).__init__(master)  
              self.grid()
              self.create_widgets()
          #    self.setup_camera()
      
          def create_widgets(self):
              """ Create widgets. """    
      
              # create variable for radio buttons to share to note which mode has been selected
              self.mode = StringVar()
              self.mode.set(None)
      
             
              
      ######## BUTTON fuer Distanzmessung   ################
              
      ##        # create 'distance' button
      ##        Button( self,
      ##                text = "Distanz messen",
      ##                command = self.DistanzMessung,
      ##                bg='yellow',
      ##                ).grid(row=5, column = 0, sticky = W+E+N+S, columnspan=1)
      
              Button( self,
                      text = "Distanz berechnen",
                      command = self.main2,
                      bg='yellow',
                      ).grid(row=6, column = 0, sticky = W+E+N+S, columnspan=1)
      
      #########           #########
              
      
      #######################################
      
      ##    
      ##
      ##    def DistanzMessung(self):
      ##    
      ##  # function to measure the distance1
      ##    #def MeasureDistance1(self):
      ##        global Distance1
      ##  # set trigger to high
      ##        GPIO.setmode(GPIO.BCM)
      ##        GPIO.setup(GPIOTrigger1, GPIO.OUT)
      ##        GPIO.output(GPIOTrigger1, True)
      ##
      ##  # set trigger after 10µs to low
      ##        time.sleep(0.00001)
      ##        GPIO.output(GPIOTrigger1, False)
      ##
      ##  # store initial start time
      ##        StartTime1 = time.time()
      ##
      ##  # store start time
      ##        GPIO.setup(GPIOEcho1, GPIO.IN)
      ##        while GPIO.input(GPIOEcho1) == 0:
      ##          StartTime1 = time.time()
      ##
      ##  # store stop time
      ##        while GPIO.input(GPIOEcho1) == 1:
      ##          StopTime1 = time.time()
      ##
      ##  # calculate distance
      ##  #Temperatur = 24
      ##        TimeElapsed1 = StopTime1 - StartTime1
      ##        Distance1 = (TimeElapsed1 * (331.5+(0.6*Temperatur))) / 2
      ##        
      ##        return Distance1
      ##        
      ##    #MeasureDistance1()
      ### function to measure the distance2
      ##    #def MeasureDistance2(self):
      ##        global Distance2
      ##          # set trigger to high
      ##        GPIO.setmode(GPIO.BCM)
      ##        GPIO.setup(GPIOTrigger2, GPIO.OUT)
      ##        GPIO.output(GPIOTrigger2, True)
      ##
      ##  # set trigger after 10µs to low
      ##        time.sleep(0.00001)
      ##        GPIO.output(GPIOTrigger2, False)
      ##
      ##  # store initial start time
      ##        StartTime2 = time.time()
      ##
      ##  # store start time
      ##        GPIO.setup(GPIOEcho2, GPIO.IN)
      ##        while GPIO.input(GPIOEcho2) == 0:
      ##            StartTime2 = time.time()
      ##
      ##  # store stop time
      ##        while GPIO.input(GPIOEcho2) == 1:
      ##            StopTime2 = time.time()
      ##
      ##  # calculate distance
      ##  #Temperatur = 24 ## Hier aktuelle Temperatur eingeben in °C
      ##        TimeElapsed2 = StopTime2 - StartTime2
      ##        Distance2 = (TimeElapsed2 * (331.5+(0.6*Temperatur))) / 2
      ##
      ##        return Distance2
      
                   
      #=================================================================
      # main
      #=================================================================
      ###########################
      
      
      
      # main function
          def main2(self):
                time.sleep(0.1) 
                try:
                  file_out = open("MesswerteDistanz.txt","w") # w=ueberschreiben, a=anhaengen der Daten
                  while True:
                       
          
        # function to measure the distance1
          #def MeasureDistance1(self):
              #global Distance1
        # set trigger to high
                    GPIO.setmode(GPIO.BCM)
                    GPIO.setup(GPIOTrigger1, GPIO.OUT)
                    GPIO.output(GPIOTrigger1, True)
                    GPIO.setup(GPIOTrigger2, GPIO.OUT)
                    GPIO.output(GPIOTrigger2, True)
      
        # set trigger after 10µs to low
                    time.sleep(0.00001)
                    GPIO.output(GPIOTrigger1, False)
                    GPIO.output(GPIOTrigger2, False)
                    
        # store initial start time
                    StartTime1 = time.time()
                    StartTime2 = time.time()
      
        # store start time
                    GPIO.setup(GPIOEcho1, GPIO.IN)
                    while GPIO.input(GPIOEcho1) == 0:
                      StartTime1 = time.time()
      
                    GPIO.setup(GPIOEcho2, GPIO.IN)
                    while GPIO.input(GPIOEcho2) == 0:
                      StartTime2 = time.time()
      
        # store stop time
                    while GPIO.input(GPIOEcho1) == 1:
                      StopTime1 = time.time()
      
                    while GPIO.input(GPIOEcho2) == 1:
                      StopTime2 = time.time()
        # calculate distance
        #Temperatur = 24
                    TimeElapsed1 = StopTime1 - StartTime1
                    Distance1 = (TimeElapsed1 * (331.5+(0.6*Temperatur))) / 2
      
                    TimeElapsed2 = StopTime2 - StartTime2
                    Distance2 = (TimeElapsed2 * (331.5+(0.6*Temperatur))) / 2
                    
                    #return Distance1
                    #Distance1 = MeasureDistance1()
                    print("gemessene Distanz1 = %.4f m" % Distance1)
                    file_out.write("d1 %.4f m     " % Distance1)
      
                    #Distance2 = MeasureDistance2(self)
                    print("gemessene Distanz2 = %.4f m" % Distance2)
                    file_out.write("d2 %.4f m\n" % Distance2)
            
                    time.sleep(1) # Wiederholung der Messung in Sek.
      
        # reset GPIO settings if user pressed Ctrl+C
                except KeyboardInterrupt:
                  print("Measurement stopped by user")
                  GPIO.cleanup()
      
      
          if __name__ == '__main2__':
      
        # use GPIO pin numbering convention
                GPIO.setmode(GPIO.BCM)
      
        # set up GPIO pins
                GPIO.setup(GPIOTrigger1, GPIO.OUT)
                GPIO.setup(GPIOEcho1, GPIO.IN)
      
                GPIO.setup(GPIOTrigger2, GPIO.OUT)
                GPIO.setup(GPIOEcho2, GPIO.IN)
      
        # set trigger to false
                GPIO.output(GPIOTrigger1, False)
                GPIO.output(GPIOTrigger2, False)
      
        # call main function
                #main2()
      
      ##################################
      
      
      
      
      
      root = Tk()                             # Create the GUI root object
      root.title("Image Capture V1.0")
      app = Application(root)                 # Create the root application window
      root.mainloop()
  19. hajo sagt:

    @Peter: Gleichzeitig starten heist aber auch, dass alle Sender einen Impuls aussenden und alle Empfänger _jeden_ Impuls hören (Echo). Natürlich funktioniert „gleichzeitig“ in einem sequenziellen System nicht, also ergeben sich für die Sender auch unterschiedliche Startzeitpunkte. Wenn jetzt z.B. der Empfänger 4 den Impuls von Sender 1 hört, gibt das natürlich komplett falsche (und sehr seltsame) Ergebnisse.

  20. Johanens sagt:

    Hallo,

    ich habe ein Problem mit meinem Programm. Und zwar möchte ich alle halbe Sekunde einen Wert haben von meinen beiden Sensoren. (Sie behindern sich nicht gegenseitig, da noch genug zwischen den beiden Sensoren zwischen ist)
    Mein Problem ist jetzt, dass das Programm zwischendurch hängen bleibt. Dies kann nach 5 min passieren aber auch mal erst nach 2 std. Nach meinen Forschungen müsste es in der Messung liegen. Also bei def MessureDistance1() bzw. def MessureDistance2(). Hatte jemand das Problem zufällig auch schon oder hat eine Idee woran es liegen könnte?
    Gibt es sonst eine Möglichkeit zu sagen: „Wenn Programm >2 Sek nichts macht, starte es neu“? Das würde mir schon helfen und reichen.

    http://pastebin.com/eq7spWS9

    • Felix sagt:

      Ohne deinen Code genauer angesehen zu haben bzgl deiner letzten Frage:
      Du kannst z.B. jede Sekunde eine Ausgabe in deinem Mess-Skript machen. Dieses Skript bindest du in einem anderen Skript ein und überprüfst wann die letzte Ausgabe war und vergleichst sie mit der Ausgabe davor (entweder du lässt die Uhrzeit ausgeben oder speicherst den timestamp). Dann kannst du überprüfen, ob das Skript nicht mehr reagiert (bzw. wie lange nicht) und ggf. neustarten.

  21. Johanens sagt:

    Okay, danke. Das hört sich erstmal gut an. Nur bin ich noch kein Profi im Programmieren und weiß nicht wirklich wie ich das alles umsätzen kann. Hast du da ein Beispiel oder Ähnliches parat?

  22. Andre sagt:

    Hallo

    Habe einen Raspberry PI 2 und bei mir erfolgt keine Messung das Script
    startet zwar aber es passiert nichts.Mehrmals neu verkabelt andere Pins
    probiert nichts.
    Der Sensor ist in Ordnung am Arduino getestet.
    Gibt es vielleicht Probleme mit Raspi 2 und python
    Andre

    • Felix sagt:

      Das sollte es eigentlich nicht. Du kannst ja mal die python Konsole öffnen (sudo python) und die Befehle von Hand testen. Welche Fehler werden denn ausgegeben?
      Die Python RPi.GPIO Bibliothek hast du aber oder?

  23. Simon sagt:

    Hi,
    ich arbeite in der Schule an einem Projekt bei dem wir versuchen unsere eigene Drohne zusammenzubauen und ich hab dank diesem Tutorial hier den Sensor zum laufen gebracht. Jetzt hab ich aber die Frage, ob ich das Programm irgendwie in ein anderes einbinden kann, sodass dieses dann quasi die Anweisung gibt, dass der Sensor jetzt die Entfernung messen soll. Da das Hauptprogramm das unsere einzelnen Teile steuert jedoch in Java ist müsste ich das irgendwie umwandeln. Geht das und wenn ja wie?

    mfg
    Simon
    P.S. Ihr habt ’ne Woche Zeit zum antworten, bin nicht da 😛

  24. Andre sagt:

    Hi Felix

    Fehler werden keine ausgegeben ein Bewegungssender den ich auch angeschlossen habe und auch über Python ansteuere funktioniert ebenfall ein Temperatursensor DS1820B
    Einfach Python Konsole öffnen und die Befehle die im Script sind aufrufen
    wie import RPi.GPIO as GPIO danach schritt für schritt weiter bis ein Fehler auftritt
    ??
    Spannung liegt am Sensor an (gemessen) und eine LED auch noch zwischengeschalten die brennt.

    Andre

    • Felix sagt:

      Die anderen Module funktionieren oder funktionieren auch nicht?
      Ja, versuch mal alle Befehle aus dem Skript so in die Konsole einzugeben.

  25. Sebastian sagt:

    Wenn das Script läuft, und man den Sensor abzieht, dann hängt das Script in einer ewig-Schleife.
    Es ware gut, wenn die while-Schleifen irgendwie nach einer definierten Zeit mit einem definierten Fehler abbrechen würden.

    • Felix sagt:

      Hallo Sebastian,
      genau das passiert doch, sobald du STRG+C drückst (except Block). Das Skript wird gestoppt und eine Meldung wird ausgegeben. Oder meinst du etwas anderes?
      LG Felix

  26. Sebastian sagt:

    Das Script läuft bei mir per Cron und piped das Ergebnis in eine Datei als log. Wenn es dann hängt, dann ist keiner da um STRG+C zu drücken 😉
    Ich lese die letzte Zeile der Datei mittels xymon (bb, hobbit) aus um es ins monitoring einzupflegen und um den Verlauf graphisch darzustellen.
    Wenn der Sensor jetzt einen Fehler hat (simunliert durch abziehen der Verbindung) dann kommt einfach kein Wert mehr.
    Das kann ich über das Alter der Datei zwar tracken, ist aber unpraktisch.
    Hinzu kommt, dass der Cron mir mehr und mehr python prozesse startet die den PI langsam lahmlegen.
    Ich habe als workaround den py-prozess in den Hintergrund geschickt, warte 6 sec und schiesse ihn dann ab (sollte er noch laufen).
    Aber ein richtiges error-handling im py-script würde ich vorziehen.
    Ich bin eher der basch & perl Mensch, sonnst hätte ich gleich im Code was probiert 😉

  27. Sebastian sagt:

    ach so, die while-schleife habe ich natürlich weggelassen …

  28. Sebastian sagt:

    Hi, hab mich bischen in python eingelesen und das Script leicht erweitert, man kann jetzt folgende Parameter einstellen:
    – Endlosschleife oder Einzel-Lauf
    – Pause zwischen den Schleifendurchläufen
    – Sensor Konnektivität timeout – verhindert „Hängenbleiben“ bei Sensorfehler

    Hier der entsprechende Code:

    root@raspberrypi:/home/pi# cat /usr/lib/hobbit/server/ext/ultraschall.py
    #http://tutorials-raspberrypi.de/gpio/entfernung-messen-mit-ultraschallsensor-hc-sr04/
    #Bibliotheken einbinden
    import RPi.GPIO as GPIO
    import time
    import datetime
    
    #GPIO Modus (BOARD / BCM)
    GPIO.setmode(GPIO.BCM)
    
    #GPIO Pins zuweisen
    GPIO_TRIGGER = 18
    GPIO_ECHO = 24
    
    # infinte Loop oder einmalig?
    infinite = 0 # 0 = einmalig ; 1 = infinite
    pause = 1 # Pause zwischen den Schleifendurchlaeufen in Sekunden
    timeout = 5 # Anzahl der sec die auf den Sensor gewartet wird
    
    #Richtung der GPIO-Pins festlegen (IN / OUT)
    GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
    GPIO.setup(GPIO_ECHO, GPIO.IN)
    
    def distanz():
      # setze Trigger auf HIGH
      GPIO.output(GPIO_TRIGGER, True)
    
      # setze Trigger nach 0.01ms aus LOW
      time.sleep(0.00001)
      GPIO.output(GPIO_TRIGGER, False)
    
      StartZeit = time.time()
      StopZeit = time.time()
      timeIN = time.time()
      timeout_done = 0
      # speichere Startzeit
      while ((GPIO.input(GPIO_ECHO) == 0)) :
        StartZeit = time.time()
        if (( StartZeit - timeIN ) > timeout ) :
          print "TimeOut Startzeit, breche ab"
          timeout_done += 1
          break
    
      # speichere Ankunftszeit
      while ((GPIO.input(GPIO_ECHO) == 1)) :
        StopZeit = time.time()
        if (( StopZeit - timeIN ) > timeout ) :
          print "TimeOut Stopzeit, breche ab"
          timeout_done += 1
          break
    
      if (timeout_done > 0) :
        print ("Konnte nicht richtig zum Sensor verbinden, timeout %.0f" % timeout)
        return -1
      else :
        # Zeit Differenz zwischen Start und Ankunft
        TimeElapsed = StopZeit - StartZeit
        # mit der Schallgeschwindigkeit (34300 cm/s) multiplizieren
        # und durch 2 teilen, da hin und zurueck
        distanz = (TimeElapsed * 34300) / 2
        return distanz
    
    if __name__ == '__main__':
      try:
        while True :
          abstand = distanz()
          print ("%s Gemessene Entfernung = %.1f cm " % (str(time.strftime("%Y-%m-%d %H:%M:%S")), abstand))
          if not (infinite):
            break
          else :
            time.sleep(pause)
    
      # Beim Abbruch durch STRG+C resetten
      except KeyboardInterrupt:
        print("Messung vom User gestoppt")
      GPIO.cleanup()
    
    root@raspberrypi:/home/pi#
    • Martin sagt:

      Hallo,
      um die Signallaufzeiten, bzw die Anstiegszeiten bei längeren Leitungen zu kompensieren, würde ich den Triggereingang auf der Sensorseite mit einer zusätzlichen
      Leitung auf einen weiteren Gpio zurückführen, dann ergibt t1in – t2in die exakte Zeitdifferenz.

  29. MErich sagt:

    Hallo,
    Welche Entfernungen Sensor – Pi wurden erfolgreich getestet?
    Sind ca 7m machbar?
    Gruß Erich

    • Felix sagt:

      Hallo Erich,
      ich habe es innerhalb des Hauses getestet, dabei waren es um die 4-5 Meter. Allerdings macht er große Öffnungswinkel Probleme, da das Signal im Bereich von ca. 20° zurückgeworfen werden kann. D.h. selbst wenn am Rand ein nahes Objekt ist, kann es sein, dass jene Entfernung erkannt wird.
      Ich denke 7 Meter sollten bei freier Sicht machbar sein, aber ich kann es dir nicht garantiren. Einfach mal ausprobieren :)

  30. MErich sagt:

    Hallo Felix,
    Danke für Deine Nachricht.
    Ich habe eine Pelletbehälter 600x700mm und Höhe 1000mm.
    Dieser B. ist mit einem Deckel verschlossen. Meine Vorstellung geht dahin,
    mit diesem Sensor den Verbrauch zu erfassen.
    Zwischenwerte Voll, Halb, Viertel, Nachfüllen sollten wenn möglich ausgegeben werden.
    Ist es möglich den Sensor an einer Behälterwand zu befestigen oder sollter er zentrisch
    platziert werden.
    Übrigens der Reedkontakt und der Magnet ist noch nicht eingetroffen.
    Gruß Erich

    • Felix sagt:

      Hallo Erich,
      ich denke eine zentrale Positionierung wird bessere Ergebnisse liefern. Der Sensor hat eben einen Öffnungswinkel von 15°, da musst du drauf achten.
      Ansonstne würde ich es einfach mal testen und schauen, wie genau die Werte sind (bei zentraler Positionierung).
      LG Felix

  31. Peter sagt:

    Hallo zusammen,
    vielen Dank für die Anleitung, hat bei mir auf Anhieb sehr gut funktioniert.
    Auch die Diskussionsbeiträge konnten mir bereits sehr helfen.
    Da ich ein blutiger Anfäger in Sachen Python bin, würde ich gerne wissen, wie man in das vorhandene Script z.B. eine Mittelwertbildung integrieren kann.

    Beispielsweise könnten innerhalb der Endlosschleife jeweils 20 Messwerte erfasst und davon der Mittelwert ausgegeben werden. Bei einem Messwert pro Sekunde würde jeweils ein Mittelwert nach 20 sec ausgegeben werden.
    Danke für die Hilfe.
    Gruß Peter

    • Felix sagt:

      Hallo Peter,
      Du könntest entweder python Listen verwenden (liste = []) und dann wie ein Array darauf zugreifen oder aber du nimmst Numpy, was ich bevorzuge.

      import numpy as np
      import time
      ...
      liste = np.zeros (20)
      while ... :
        for i in range(20)
          liste[0] = ...
          time.sleep(1)
        print liste.mean()
    • Peter sagt:

      Hallo Felix,
      Danke für deine Antwort, habe es mit der Liste hinbekommen.

      Mir ist gerade noch eine Idee in den Sinn gekommen…vielleicht ist es ja für jemanden in der Runde von Interesse:
      Um im Außenbereich bis 4m Entfernung möglichst genau (+-0,5 cm) messen zu können, wäre eventuell eine zusätzlicher Anschluss eines Thermo-Sensors sinnvoll, da die Schallgeschwindigkeit in Luft ziemlich temperaturabhängig ist. Luftfeuchte und -Druck können wohl schon eher vernachlässigt werden.
      Hat vielleicht jemand Erfahrungen mit dem Anschluss mehrerer Sensoren zugleich? Was ist dabei zu beachten? Reicht die Versorgungsspannung des Pi dazu prinzipiell aus?

    • Felix sagt:

      Hallo Peter,
      wenn du nur die Temperatur messen willst, schau am besten mal hier vorbei:
      Temperatur mittels Sensor messen (mehrere 1-Wire Sensoren hintereinander sind auch möglich)
      ALternativ:
      Luftfeuchtigkeit und Temperatur mit DHT11 / DHT22 und dem Raspberry Pi messen
      Raspberry Pi und I2C Luftdrucksensor BMP180

  32. Horst sagt:

    Hallo zusammen,

    kennt jemand eine Möglichkeit, die berechneten Abstandswerte aus dem Skript auf den I2C-Bus mit einer definierten Adresse z.B. 0x12 zu übergeben?

    Danke für eure Hilfe!

    Gruß Horst

  33. Ingo sagt:

    Hallo,
    das mit dem Mittelwert interessiert mich auch.
    Leider bin ich zu blöd, um rauszufinden, wo genau der numpy-Code-Schnipsel eingesetzt werden muß.

    Kannst du mir da den entscheidenden Tip geben?

    Im übrigen habe ich ein altes VGA-Kabel mit 1 Meter Länge zu einem Verbindungskabel Pi Sensor umgelötet.
    Ich habe das Gefühl, als wenn der Sensorbei dieser Länge einige Zeit braucht, um einen Wert zu erzeugen.
    Diese Kabelart scheint noch nicht optimal zu sein…
    Gruß Ingo

  34. Ingo sagt:

    Ach ja, richtig tricky wäre, wenn bei den 20 Messungen der höchste und der niedrigste Wert nicht berücksichtigt würden.

    • Felix sagt:

      Ich schreibe mal einen einfachen Code, wie man Messungen mit Numpy speichern kann und die Werte auslesen:

      import numpy as np
      array = np.zeros(20) # 20 Messwerte
      for i in range(20):
        ... # Messen
        array[i] = ... # Messwert
      mean = array.mean()
      mean2 = array[1:-1] # ab dem zweiten Wert bis zum vorletzten

      Das schöne an Numpy sind die vielen vorgefertigten Funktionen, die alle sehr performant sind (da C-Code)

      Es kann sein, dass bei deinem langen Kabel die Spannung abfällt und daher der Sensor nicht mehr ordnungsgemäß reagiert. Das solltest du ggf. messen. Und wieso genau ein VGA Kabel?

  35. Ingo sagt:

    Hallo Felix,
    ich habe den Sensor erst mit einem Steckboard und Jumperkabeln ausprobiert.
    Erst mal ein dickes Lob! Das hat alles auf Anhieb funktioniert!
    (Bis auf, daß ich den Sensor erst seitenverkehrt gesteckt habe :) )
    Dann habe ich alles auf eine Platine gelötet. Da das Ganze irgendwann in einem 6m² Wassertank landen könnte, wollte ich ein längeres Kabel austesten. Ein VGA-Kabel hat ganz viele Pins also müssen da auch mind. 4 Kabel drin sein. Und da ich noch ein paar Kabel im Schrank liegen hatte, wurde mal eben eins gekillt.
    Stecker drangelötet und schon konnte es los gehen.
    Interessant ist, daß der PI eine Weile braucht um die ersten Messwerte auszulesen. Hat er aber erst mal einen Anfang gefunden, kommen die Werte relativ zügig hintereinander weg…..

    Bei dem neuen Code ( mean2 = array[1:-1] # ab dem zweiten Wert bis zum vorletzten )
    würde ich als Laie jetzt herauslesen, dass der erste und letzte Wert nicht berücksichtigt werden. Ich fände es aber besser wenn der höchste und niedrigste Zahlenwert nicht berücksichtigt würde.

    Und wo genau müsste der Code in das Python-Programm eingefügt werden?

    Gruß

    Ingo

    • Felix sagt:

      Hallo Ingo,
      dann kannst du das Array vorher sortieren und dann den niedrigsten (ersten) und höchsten (letzten) Wert raus schmeißen:

      mean2 = np.sort(a)[1:-1]

      Eventuell solltest du dir auch mal den Median anschauen.
      LG Felix

  36. Ingo sagt:

    Hallo,
    Es tut mir echt leid, aber ich bekomme es nicht hin.. :(

    Was ich gerade noch schaffe, ist am Anfang:
    ‚import numpy as np‘
    einzusetzten.
    Der Rest verschließt sich mir leider…
    Könntest du mir ggf. nochmal unter die Arme greifen…?
    Gruß Ingo

    • Felix sagt:

      Wo hängst du genau? Zu einzelnen Funktionen solltest du dir die Docs mal ansehen. Oder ist etwas an dem von mir geposteten Code unverständlich?

  37. Ingo sagt:

    Na ja…..
    ich kann nicht herrauslesen, wo zwischen ich den Code setzten muß. Dieses Python verschließt sich mir etwas.
    Ich bin BASIC vom VC-20 gewohnt… :)

    Optimalerweise müsste ich den Bereich vor dem Codeschnipsel sehn und dann den Code.
    Also ungefähr so:

     timeIN = time.time()
      timeout_done = 0
      # speichere Startzeit
      while ((GPIO.input(GPIO_ECHO) == 0)) :
        StartZeit = time.time()
        if (( StartZeit - timeIN ) > timeout ) :
          print "TimeOut Startzeit, breche ab"
          timeout_done += 1
    
    import numpy as np
    array = np.zeros(20) # 20 Messwerte
    for i in range(20):
      ... # Messen
      array[i] = ... # Messwert
      ...
    mean = array.mean()
    mean2 = np.sort(a)[1:-1] # ab dem zweiten Wert bis zum vorletzten
    
     # speichere Ankunftszeit
      while ((GPIO.input(GPIO_ECHO) == 1)) :
        StopZeit = time.time()
        if (( StopZeit - timeIN ) > timeout ) :
          print "TimeOut Stopzeit, breche ab"
          timeout_done += 1
          break

    Das ist wohl nicht zufällig die richtige stelle :)

    Ich will dir aber nicht deine Zeit stehlen…..

    Gruß Ingo

    • Felix sagt:

      Also imports kommen normalerweise an den Anfang der Datei.
      das Array kannst du auch irgendwo am Anfang initiliaiseren. Den Mean bestimmst du nachdem du alle Werte gespeichert hast, also am Ende. Eigentlich kommt fast der gesamte Code in die For-Schleife. Du musst die Entfernung wie im Tutorial berechnen und dann speichern.
      Achja, die Punkte (…) sind als Denkansatz, da musst du deinen Code entsprechend einfügen 😉

  38. Ingo sagt:

    Hallo, ich lasse gerade den US-Sensor über ein ca. 15 Meter langes 4-adriges Telefonkabel laufen.
    Läuft gut mit stabilen Werten.

    Gruß Ingo

  39. Tim sagt:

    Gerade das Tutorial nachgebaut. Bei mir kommt aber keine Nachricht an, hoffe hab nichts kaputt gemacht. Es werden einfach keine Ergebnisse geschrieben ich kann das Script jedoch über Strg+C beenden, dann kriege ich auch die Message fürs Beenden

    Übrings der Link im Abschnitt „Zu erst einmal sollte die Python GPIO Library installiert sein. Ist dies nicht der Fall, kannst du am Anfang dieses Tutorials nachlesen, wie dies geht.“ zeigt auf diesen Artikel (self-reference)

    • Felix sagt:

      Hi Tim,
      der Link ist aktualisiert: Raspberry Pi Ampelschaltung mit GPIO Teil 1
      Dein Problem klingt sehr danach, dass nichts ankommt und daher er while Schleife der Funktion stecken bleibt. Die Verkabelung stimmt aber soweit und das Modul ist auch in Ordnung?

    • Tim sagt:

      Hallo,

      danke für die Antwort, ich konnte meinen Fehler noch finden. Und zwar bin ich oben von der Skizze des Raspberry ausgegangen und habe gesehen die Pins müssen (nach meiner ersten Auffassung wiefolgt gesteckt werden:
      Obere Reihe:
      1. von links = Strom
      3. von links = Ground
      6. von links = Trig
      5. von rechts = Echo <–
      später fiel mir auf, dass in der Zeichnung garnicht alle Pins gezeigt sind und daher die herangehensweise (X Pins von rechts/links) dumm von mir war.

  40. Robin sagt:

    Hallo zusammen,

    Vielen Dank für das tolle anschauliche Tutorial, hat alles auf Anhieb geklappt!
    Leider funktioniert das Ultraschallsystem nur sehr „ungenau“, sprich: möchte man die Entfernung zu einem Menschen messen, geht fast jede zweite Messung ab einer Distanz von 2 Metern daneben (der Ultraschall „trifft“ nicht das Objekt und es werden extrem hohe Werte ausgegeben). Welche Möglichkeiten gibt es, das System zu verbessern? Würde es Sinn machen einen zweites Ultraschall Modul zu verwenden um ein Objekt besser zu erfassen? oder gibt es eine einfachere, technische Möglichkeit (Sensor vergrößern etc..)?
    Vielen Dank schonmal!
    LG Robin

    • Felix sagt:

      Hallo Robin,
      die Ungenauigkeit ist ein Problem des US Sensors, da es einen Öffnungswinkel von 15° hat. Das bedeutet, der Ultraschall wird vom nähesten Objekt innerhalb dieser 15° reflektiert. Für kritische Anwendungen würde ich kein US Modul nehmen. Es gibt Laser-Range-Scanner (LIDAR etc.), was allerdings sehr teuer ist. Darüber hinaus kann man Abstände auch mit Stereo Vision (OpenCV) erkennen, allerdings wird das Tutorial dazu erst in 2-3 Monaten erscheinen.
      Als letzte Möglichkeit gibt es auch noch Infrarot Abstandsmesser, welche sehr genau arbeiten (+-2cm). Dazu schreibe ich gerade ein Tutorial, welches in ca. 2 Wochen erscheint. Wenn du möchtest, kannst du dich ja zum Newsletter eintragen, dann wirst du informiert, sobald es fertig ist.

  41. Patrick sagt:

    Hallo zusammen,
    ich habe eine html Webseite mit 2 Buttons erstellt, jeweils zum Auf- und Zufahren eines Rollladens. Mit Hilfe zwei php Skripts steuer ich die beiden Relais an.

    Nun möchte ich mit Hilfe eines Ultraschallsensors der unten am Ende des Rollladens auf einem Brett angebracht ist, die Entfernung zwischen dem Rollladenpanzer und dem Sensor ermitteln. Das funktioniert mit dem hier veröffentlichtem Skript sehr gut. :) Der gemessene Abstand wird in der Datei Abstand.txt ausgeben.

    Nun möchte ich auf der Webseite ausgeben ob der Rollladen geschlossen oder geöffnet ist, indem ich die Abstand.txt Datei auslese und als eine Art optische Anzeige auf der Webseite darstelle. Weis jemand wie das funktionieren könnte?
    Vielen Dank schon mal

    Schöne Grüße
    Patrick

    • Felix sagt:

      Wenn du den Abstand hast, kannst du es z.B. mit einer „Progress Bar“ recht einfach realisieren. Dazu ist ein wenig CSS nötig (einfach hier nachlesen oder nach „CSS Progress Bar“ googlen). Du definierst einen maximalen Abstand und einen minimalen (0), dann schaust du wie viel Prozent davon erreicht sind und setzt den Balken dementsprechend.

    • Patrick sagt:

      Danke für die schnelle Antwort :)
      weist du zufälligerweise wie man des Skript von dir oben umschreiben kann, so dass er zwar ständig die Entfernung misst aber nur den maximalen oder den minimalen Abstand also 0 in die Datei Abstand.txt ausgibt?

    • Felix sagt:

      Dauerhaft: Mit einer Endlosschleife (while True:).
      Nur Abstand größer als Null: if abstand > 0: und dann in die Datei schreiben.
      Wenn du die HTML Datei auch automatisch aktualisieren möchtest, musst du das mit Javscript machen (jede Sekunde den Wert neu einlesen und die Progress Bar anpassen.
      LG Felix

    • Patrick sagt:

      Könntest du mir sagen, wo geau ich den Befehl: if abstand > 0:
      eingeben muss, da ich immer nen Fehler bekomm
      Danke

      if __name__ == '__main__':
        try:
          file_out = open("Abstand.txt","w")
          while True:
            abstand = distanz()
            print ("Gemessene Entfernung = %.1f cm" % abstand)
            file_out.write("%.1f cm\n" % abstand)
            time.sleep(3)
      
        # Beim Abbruch durch STRG+C resetten
        except KeyboardInterrupt:
          print("Messung vom User gestoppt")
          GPIO.cleanup()
          file_out.close()
    • Felix sagt:

      Bevor du es speicherst. Sprich:

            ...
            print ("Gemessene Entfernung = %.1f cm" % abstand)
            if abstand > 0:
              file_out.write("%.1f cm\n" % abstand)
            time.sleep(3)
  42. Patrick sagt:

    Vielen Dank, jetzt klappts :)

    LG Patrick

  43. Patrick sagt:

    hab jetzt mal gemacht: if Abstand > 5:
    print…

    Der schreibt mir dann immer die Werte untereinander. Ist es auch möglich das er keinen Zeilenumbruch macht sondern den letzten Wert überschreibt und ich somit in der .txt Datei immer nur einen Wert stehen habe?

    Dann wär die andere Frage: Wie kann ich es genau machen, dass er z.b bei einem Wert 65 in eine andere .txt Datei?

    Nochmals vielen Dank! :)
    sorry das ich hier grad alles voll schreibe aber du bist gerade der einzige der mir dabei helfen kann

  44. Sebastian sagt:

    Sehr guter Beitrag und das einzige Script was bei mir richtige Funktionier hat. Mach weiter!

  45. Werner sagt:

    Ich verwende dieses Script bei 3 Verschiedenen Sensoren unter Raspbian. Bei einem scheint es problemlos zu laufen. Bei den zwei anderen läuft es anfangs, nach einer Weile (manchmal Sekunden manchmal Stunden) bleibt es in der ersten While schleife hängen.
    Nach etwas Googlen hab ich herausgefunden dass das wohl an den SR-04 Sensoren liegt und es da wohl irgendwie ein Problem mit dem ECHO geben soll.
    Kennst du dieses Problem zufällig und kennst ein passenden Workaround dazu?

    Danke schon mal

    • Felix sagt:

      Hallo Werner,
      ich kann das Problem bestätigen: Zwar hatte es bei mir nur selten (1 von 100) Probleme, aber es kommt dennoch vor. Teilweise gibt es qualitativere Sensoren, die aber auch etwas mehr kosten. Ansonsten würde ich einen Timeout setzen: Da Entfernungen über 10m sehr unrealistisch damit zu messen sind bzw. die Genauigkeit ab ca. 5m nachlässt, würde ich einen Timeout setzen.Je nachdem wie weit du den maximalen Abstand haben willst (X in Metern) setzt du ihn auf 2*X/343 Sekunden(2 mal weil hin und zurück). Ist mehr Zeit vergangen kann die Schleife abgebrochen werden und es gibt einfach keine Messung (-1 oder so).
      LG Felix

  46. Andreas sagt:

    Hallo,

    hier wurde sich fleissig von deinem Script bedient…
    dracarysdiy.wordpress.com/smart-mirror-5-video/
    allerdings nimmt der Kollege viel grössere Wiederstände… Kannst Du da etwas Licht ins Dunkel bringen?

    • Felix sagt:

      Hi Andreas,
      der größere Widerstand ist nur dazu gedacht, dass eine bestimmte Spannung (in dem Fall Minus) anliegt. Normalerweise nimmt man einen größeren Widerstand wie z.B. 10k. Als ich das Tutorial erstellt habe, hatte ich keinen 10k Widerstand zur Hand, daher 470 verwendet. Es sollte aber auch mit Zwischenwerten (1k, 4.7k, usw) funktionieren. Wichtig ist nämlich nur, dass wenn vom ECHO keine Spannung kommt, der Pi ein Signal von GND bekommt und da reicht es aus, wenn es auch nur sehr gering ist.
      Warum er allerdings 4.7k Ohm als Vorwiderstand nimmt ist mir schleierhaft, da man ja ausrechnen kann wie viel Volt abgeleitet werden müssen (5.5 – 3.3 = 1.7).

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Blog abonnieren

Abonniere Tutorials-RaspberryPi, um kein Tutorial mehr zu verpassen!