Taster auslesen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Taster auslesen

Beitragvon solaris1997 » Sonntag 12. Februar 2017, 20:44

Hallo,

Ich will am Raspberry Zero einen Taster auslesen, der an den GPIOs angeschlossen ist. Das funktioniert auch ganz gut mit folgendem Code:
  1. TASTER = 20
  2. AUSGANG = 15
  3.  
  4. GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  5. GPIO.setup(AUSGANG, GPIO.OUT)
  6.  
  7. while True:
  8.     tasterStatus = GPIO.input(TASTER)
  9.     if ((tasterStatus) == False):
  10.         print ("Test")


Jetzt wollte ich aber noch einen Änderung vornehmen, und zwar soll er, wenn der Schalter gedrückt wird solange warten, bis ich ihn wieder loslasse. Eine Lösung mit sleep ist für mich nicht akzeptabel. Ich habe also viele Foren durchsucht und unzählige Versuche gestartet. Leider erfolglos. Mein aktuellstes Script sieht so aus (Ich kann mir gut vorstellen, dass sich jetzt jeder, der einigermaßen was von programmieren die Hände über dem Kopf zusammenschlägt :D :D ):
  1. TASTER = 20
  2. AUSGANG = 15
  3.  
  4. GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  5. GPIO.setup(AUSGANG, GPIO.OUT)
  6.  
  7. def main():
  8.     while True:
  9.         tasterStatus = GPIO.input(TASTER)
  10.         if ((tasterStatus) == False):
  11.             print ("Test")
  12.             while True:
  13.                 taster = GPIO.input(TASTER)
  14.                 if ((taster) == False):
  15.                     time.sleep(.0001)
  16.                 else: return main

Wenn ich dieses Script ausführe dauert es ein wenig (Raspi Zero ist sehr langsam) und anschließend zeigt er wieder die normale Eingabezeile an und das Script ist beendet.

Kann mir bitte jemand helfen wie ich das Script schreiben muss!

PS: Bitte keine Kommentare alla "Benutze Google", ich habe bereits eine halbe Ewigkeit "gegooglet"! :D

Vielen Dank schonmal im Voraus
MfG Jakob :)
Zuletzt geändert von BlackJack am Sonntag 12. Februar 2017, 22:59, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Üpsilon
User
Beiträge: 167
Registriert: Samstag 15. September 2012, 19:23
Wohnort: Altschauerberg 8 in 91448 Emskirchen

Re: Taster auslesen

Beitragvon Üpsilon » Sonntag 12. Februar 2017, 21:54

Ohne groß Ahnung vom Pi zu haben, würde ich sagen, der Fehler liegt in der letzten Zeile. Vermutlich willst du dort else: break stehen haben, um aus der inneren Schleife auszusteigen. return main macht nämlich etwas völlig Anderes.

Die Klammern bei den ifs sind übrigens unnötig und statt variable==False kann man auch not variable schreiben.
PS: Die angebotene Summe ist beachtlich.
Benutzeravatar
BlackJack
Moderator
Beiträge: 32710
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Taster auslesen

Beitragvon BlackJack » Sonntag 12. Februar 2017, 23:51

@solaris1997: Man kann nicht nur ``not variable`` schreiben, man sollte sogar.

Die beiden `setup()`-Aufrufe gehören auch *in* die Hauptfunktion, oder zumindest nicht auf Modulebene.

Man sollte auch explizit dafür sorgen das am Ende des Programms die `GPIO.cleanup()`-Funktion aufgerufen wird.

Es macht in diesem Programm nicht viel Sinn zwei verschiedene Namen für den Tasterstatus zu verwenden. Die konventionelle Schreibweise wäre auch `taster_status`. Eigentlich braucht man überhaupt keine Namen dafür, weil die Werte sowieso nur in der jeweils nächsten Zeile in der Bedingung von ``if`` verwendet werden.

Bei der inneren Schleife kann man das ``if``/``else`` loswerden, weil man die Bedingung der Schleife mit dem Wert am Eingang ausdrücken kann.

Zwischen Funktionsname und öffnender Klammer beim Aufruf gehört kein Leerzeichen.

Damit landen wir ungefähr hier:
  1. import time
  2. from Rpi import GPIO
  3.  
  4. TASTER = 20
  5. AUSGANG = 15
  6.  
  7.  
  8. def main():
  9.     try:
  10.         GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  11.         GPIO.setup(AUSGANG, GPIO.OUT)
  12.         while True:
  13.             if not GPIO.input(TASTER):
  14.                 print('Test')
  15.                 while GPIO.input(TASTER):
  16.                     time.sleep(.0001)
  17.     finally:
  18.         GPIO.cleanup()
  19.  
  20.  
  21. if __name__ == '__main__':
  22.     main()


Was Du eigentlich machen willst, ist auf die fallende Flanke zu warten:
  1. def main():
  2.     try:
  3.         GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  4.         GPIO.setup(AUSGANG, GPIO.OUT)
  5.         while True:
  6.             GPIO.wait_for_edge(TASTER, GPIO.FALLING)
  7.             print('Test')
  8.     finally:
  9.         GPIO.cleanup()


Sooo langsam ist der Raspi Zero nun auch wieder nicht. Die CPU ist auf 1Ghz getaktet. Damit ist der schneller als der Raspi 1 (A und B) und immer noch höher getaktet als der Raspi 2, der allerdings vier Kerne hat. Aber auch der 1er war schon als Mediacenter und Server bei mir im Einsatz. Mein C64 ist sehr langsam. Nicht nur 1000 mal langsamer getaktet als der Raspi Zero sondern auch ein 8-Bit-, statt eines 32-Bit-Prozessors. :-)

Ich würde mir an Deiner Stelle auch mal die `gpiozero`-Bibliothek anschauen.
“XML combines all the inefficiency of text-based formats with most of the unreadability of binary formats :-)” — Oren Tirosh, c.l.p, 2002
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Re: Taster auslesen

Beitragvon solaris1997 » Montag 13. Februar 2017, 16:06

@BlackJack:

Hallo,

vielen Dank für die ausführliche Antwort! Es funktioniert fast einwandfrei, bis auf das, dass er warten soll bis ich den Taster losgelassen habe. Sobald ich drücke, zeigt es mir auf einen Schlag viele "Test" an! Könnten Sie vielleicht nochmal schauen, wie ich das beheben kann :o

Vielen Dank!!
Gruß Jakob :)
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Re: Taster auslesen

Beitragvon solaris1997 » Montag 13. Februar 2017, 16:47

Hallo,

Habe es mittlerweile durch ein sleep geschafft, da der Taster anscheinend nicht schnell genug trennt und somit pro Tasterbetätigung immer ca. 4x Test angezeigt worden ist:
  1. def main():
  2.     try:
  3.         GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  4.         GPIO.setup(AUSGANG, GPIO.OUT)
  5.         while True:
  6.             GPIO.wait_for_edge(TASTER, GPIO.FALLING)
  7.             print('Test')
  8.             time.sleep(0.3)      <-----------------------
  9.     finally:
  10.         GPIO.cleanup()


Das einzige was noch nicht passt, dass sowohl beim Tasterdruck als auch beim loslassen ein Test geschrieben wird. Habe im Internet was gelesen, indem man bei

Code: Alles auswählen

GPIO.wait_for_edge(TASTER, GPIO.FALLING)
das FALLING durch RISING ersetzt, allerdings bekomme ich auch hier immer 2 Meldungen!? :?

Wie kann ich das noch beheben?

Vielen Dank
Jakob :)
Zuletzt geändert von BlackJack am Montag 13. Februar 2017, 17:34, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
BlackJack
Moderator
Beiträge: 32710
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Taster auslesen

Beitragvon BlackJack » Montag 13. Februar 2017, 17:57

@solaris1997: Du willst wahrscheinlich nach dem `print()` das gleiche noch mal mit `GPIO.RISING` machen. Oder objektorienterte Programmierung verwenden und auf beide Flanken per „callback“ in einer eigenen Klasse reagieren.

Oder Du schaust Dir mal die `gpiozero`-Bibliothek an.
“XML combines all the inefficiency of text-based formats with most of the unreadability of binary formats :-)” — Oren Tirosh, c.l.p, 2002
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Re: Taster auslesen

Beitragvon solaris1997 » Montag 13. Februar 2017, 18:22

Hallo,

Nein ich möchte nur auf das Drücken reagieren! Also dass wenn ich drücke "Test" angezeigt wird und wenn ich loslasse einfach nichts passiert.

Lg Jakob :)
lackschuh
User
Beiträge: 259
Registriert: Dienstag 8. Mai 2012, 13:40

Re: Taster auslesen

Beitragvon lackschuh » Montag 13. Februar 2017, 19:12

Dann schau dir die ``add_event_detect()`` Funktion an.
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Re: Taster auslesen

Beitragvon solaris1997 » Montag 13. Februar 2017, 20:03

Hallo,

Ich weiß ich bin nervig aber wie muss ich das add_event_detect() integrieren?
Ich habe es nach mehreren Internetseiten versucht aber es kommt immer irgendeine Fehlermeldung :cry: :cry:

Gruß Jakob
Benutzeravatar
BlackJack
Moderator
Beiträge: 32710
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Taster auslesen

Beitragvon BlackJack » Dienstag 14. Februar 2017, 00:34

@solaris1997: Du musst es so integrieren das nicht irgendeine Fehlermeldung kommt. ;-)
“XML combines all the inefficiency of text-based formats with most of the unreadability of binary formats :-)” — Oren Tirosh, c.l.p, 2002
lackschuh
User
Beiträge: 259
Registriert: Dienstag 8. Mai 2012, 13:40

Re: Taster auslesen

Beitragvon lackschuh » Dienstag 14. Februar 2017, 08:31

@solaris1997
Das steht alles in der Doku ;)
https://sourceforge.net/p/raspberry-gpi ... ki/Inputs/


  1. from RPi import GPIO
  2. import signal
  3.  
  4.  
  5. PINS = [15, 20]
  6.  
  7.  
  8. def setup_gpio():
  9.     GPIO.setmode(GPIO.BCM)
  10.     GPIO.setup(PINS, GPIO.IN)
  11.  
  12.  
  13. def do_smt(channel):
  14.     print("Taster wurde gedrückt")
  15.    
  16.  
  17. def main():
  18.     setup_gpio()
  19.     try:
  20.         GPIO.add_event_detect(20, GPIO.RISING, callback=do_smt, bouncetime=500)
  21.         signal.pause()
  22.     except KeyboardInterrupt:
  23.         pass
  24.     finally:
  25.         GPIO.cleanup()
  26.  
  27. if __name__ == '__main__':
  28.     main()
solaris1997
User
Beiträge: 6
Registriert: Sonntag 12. Februar 2017, 20:25

Re: Taster auslesen

Beitragvon solaris1997 » Dienstag 14. Februar 2017, 13:20

Hallo,

Danke an alle!!
habe das Script von lackschuh noch leicht angepasst und jetzt geht es einwandfrei!
Hier der Code falls jemand mal vor einem ähnlichen Problem stehen sollte :D
  1. from RPi import GPIO
  2. import signal
  3.  
  4.  
  5. TASTER = 15
  6. AUSGANG = 20
  7.  
  8. def setup_gpio():
  9.     GPIO.setmode(GPIO.BCM)
  10.     GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  11.     GPIO.setup(AUSGANG, GPIO.OUT)
  12.  
  13.  
  14. def do_smt(channel):
  15.     print('Taster wurde gedrueckt')
  16.  
  17.  
  18. def main():
  19.     setup_gpio()
  20.     try:
  21.         GPIO.add_event_detect(TASTER, GPIO.FALLING, callback=do_smt, bouncetime=200)
  22.         signal.pause()
  23.     except KeyboardInterrupt:
  24.         pass
  25.     finally:
  26.         GPIO.cleanup()
  27.  
  28. if __name__ == '__main__':
  29.     main()


Nochmals vielen Dank :)
Gruß Jakob
Zuletzt geändert von BlackJack am Dienstag 14. Februar 2017, 13:22, insgesamt 1-mal geändert.

Zurück zu „Raspberry Pi und Co.“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder