Taster auslesen

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

Hallo,

Ich will am Raspberry Zero einen Taster auslesen, der an den GPIOs angeschlossen ist. Das funktioniert auch ganz gut mit folgendem Code:

Code: Alles auswählen

TASTER = 20
AUSGANG = 15

GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(AUSGANG, GPIO.OUT)

while True:
    tasterStatus = GPIO.input(TASTER)
    if ((tasterStatus) == False):
        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 ):

Code: Alles auswählen

TASTER = 20
AUSGANG = 15

GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(AUSGANG, GPIO.OUT)

def main():
    while True:
        tasterStatus = GPIO.input(TASTER)
        if ((tasterStatus) == False):
            print ("Test")
            while True:
                taster = GPIO.input(TASTER)
                if ((taster) == False):
                    time.sleep(.0001)
                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 Anonymous am Sonntag 12. Februar 2017, 22:59, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

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.
BlackJack

@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:

Code: Alles auswählen

import time
from Rpi import GPIO

TASTER = 20
AUSGANG = 15
 
 
def main():
    try:
        GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(AUSGANG, GPIO.OUT)
        while True:
            if not GPIO.input(TASTER):
                print('Test')
                while GPIO.input(TASTER):
                    time.sleep(.0001)
    finally:
        GPIO.cleanup()


if __name__ == '__main__':
    main()
Was Du eigentlich machen willst, ist auf die fallende Flanke zu warten:

Code: Alles auswählen

def main():
    try:
        GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(AUSGANG, GPIO.OUT)
        while True:
            GPIO.wait_for_edge(TASTER, GPIO.FALLING)
            print('Test')
    finally:
        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.
solaris1997
User
Beiträge: 9
Registriert: Sonntag 12. Februar 2017, 20:25

@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: 9
Registriert: Sonntag 12. Februar 2017, 20:25

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:

Code: Alles auswählen

def main():
    try:
        GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(AUSGANG, GPIO.OUT)
        while True:
            GPIO.wait_for_edge(TASTER, GPIO.FALLING)
            print('Test')
            time.sleep(0.3)      <-----------------------
    finally:
        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 Anonymous am Montag 13. Februar 2017, 17:34, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@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.
solaris1997
User
Beiträge: 9
Registriert: Sonntag 12. Februar 2017, 20:25

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: 281
Registriert: Dienstag 8. Mai 2012, 13:40

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

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
BlackJack

@solaris1997: Du musst es so integrieren das nicht irgendeine Fehlermeldung kommt. ;-)
lackschuh
User
Beiträge: 281
Registriert: Dienstag 8. Mai 2012, 13:40

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

Code: Alles auswählen

from RPi import GPIO
import signal


PINS = [15, 20]


def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PINS, GPIO.IN)


def do_smt(channel):
    print("Taster wurde gedrückt")
    

def main():
    setup_gpio()
    try:
        GPIO.add_event_detect(20, GPIO.RISING, callback=do_smt, bouncetime=500)
        signal.pause()
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()
solaris1997
User
Beiträge: 9
Registriert: Sonntag 12. Februar 2017, 20:25

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

Code: Alles auswählen

from RPi import GPIO
import signal


TASTER = 15
AUSGANG = 20

def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(TASTER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(AUSGANG, GPIO.OUT)


def do_smt(channel):
    print('Taster wurde gedrueckt')


def main():
    setup_gpio()
    try:
        GPIO.add_event_detect(TASTER, GPIO.FALLING, callback=do_smt, bouncetime=200)
        signal.pause()
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()
Nochmals vielen Dank :)
Gruß Jakob
Zuletzt geändert von Anonymous am Dienstag 14. Februar 2017, 13:22, insgesamt 1-mal geändert.
Antworten