Tastenkreuzabfrage mit LCD 2zeilig

  • Hallo,

    für eine Anzeige von diversen Messdaten, Zeit u.s.w. an einem "Terminal" z.B. im Anschußraum habe ich ein Tastenkreuz zusammengebaut und ein 2zeiliges I2C- LCD zum RPi3Aplus gekauft.

    Das ist für viele Fälle ausreichend und intuitiv zu bedienen. Denke da auch an eine Fernunterstützung, wenn mal jemand Ungeübte/r vor dem Ding steht und Messwerte durchgeben soll.

    Die Abfrage der Tasten und Anzeige von Pseudodaten habe ich mittlerweile nach Wochen hinbekommen. DANKE :danke_ATDE: an alle Leute mit interessanten Anwendungen und vor allem an die Profis hier im Forum. Ohne die vielen Tipps wäre ich untergegangen.

    Den Code habe ich angehängt. Dazu habe ich folgende Fragen:

    Stecken in dem Code noch versteckte Fehler, die mich ärgern können?

    Habe ich alle Tipps für einen korrekten Code umgesetzt?

    Wie kann ich die Global Variable taste_gedrueckt für die Interruptauswertung der Tasten vermeiden? Habe keinen anderen Weg gefunden, den Interrupt in das Hauptprogramm zu bekommen :(

    Bin für jeden Tipp zu haben. Vielleicht können auch andere von dem Grundaufbau profitieren und eine userfreundliche Menüführung gebrauchen.

  • Hallo,

    Zitat

    Wie kann ich die Global Variable taste_gedrueckt für die Interruptauswertung der Tasten vermeiden? Habe keinen anderen Weg gefunden, den Interrupt in das Hauptprogramm zu bekommen

    Indem du das, was beim Tastendruck gemacht werden soll, in die Funktion packst? Das aktuelle Vorgehen ist ein bisschen kompliziert und wegen `global` schlecht.

    Ansonsten: keine nackten `try...except` und aussagekräftige Variablennamen benutzen. Bei `temper` und `luftfeu` sind dir auf dem Weg dahin scheinbar die Buchstaben ausgegangen... ;) Und die überflüssigen Kommentare entfernen, macht den Quelltext besser lesbar. Wenn das z.b. `while True` steht, dann brauchst du davor nicht `#Schleife ` schreiben. Das hat null Mehrwert weil so was von offensichtlich.

    Gruß, noisefloor

  • Vielen Dank für eure Tipps, habe versucht, alles umzusetzen. Hier mal ein Zwischenstand:

    Der neue Code sieht schon besser aus. Blöde Kommentare entfernt, Variablen umgenannt, Global vermieden und Funktion für Tastenabfrage gebaut.

    Allerdings funktioniert er jetzt nicht mehr :( Die gedrückte Taste wird erkannt, jedoch nicht ausgewertet.

    Ich habe mir vor kurzem Thonny auf den RPi geladen und meinen Monitor/Tastatur angeschlossen, um schneller arbeiten zu können. Vorher hatte ich mit Geany den Code auf meinem PC geändert und per FTP auf den RPi geladen.

    Mit Thonny kann ich den Code in Einzelschritten abarbeiten und die Werte der Variablen beobachten.

    In der Abfragefunktion liegt wohl der Fehler, da immer für taste der Wert 'keine' zurückgegeben wird. Beim Debuggen wird z.B. der active_state einer Taste mit True gezeigt, wenn ich die Taste drücke, ansonsten False.


    Der ganze Code sieht jetzt so aus: (wie kriegt ihr die farbige Darstellung des Codes hin?)

  • Du speicherst hier das Ergebnis nicht: Tastenkreuzabfrage mit LCD 2zeilig

    Was dir sehr weiter helfen könnte/würde ist meine Erweiterung hier: Erweiterung für gpiozero

    Wie ich das ganze in der "Praxis" nutze kannst du dir hier ansehen: Kaffeemaschine automatische Abrechnung

    Was soll denn Zeile 115 bewirken?

    Zeile 8-14 würd ich die Variablen groß schreiben, da auf globaler Ebene und Konstanten.

  • Du speicherst hier das Ergebnis nicht: Tastenkreuzabfrage mit LCD 2zeilig

    wie meinst du das? Die Tastenevents? Sind die nicht so lange, wie die Taste gedrückt wird, das müsste doch zur Auswertung reichen,oder?

    Ich glaube aber, dass ich die Funktion Button_xxxxx.when_pressed == True da falsch reingebracht habe...

    Die gpiozero Doku habe ich auf dem PC und dem RPi. Die hilft schon manchmal, jedoch nicht bei der Einbindung der Funktionen ins Programm, wenn es komplizierter wird. Eine Taste steuert eine LED - na schön, das hab ich hingekriegt.

    Wie fasst man die Auswertung mehrerer Tasten in einer Funktion zusammen?

    Wie übergibt man das Ereignis an das Hauptprogramm?? kein Hinweis, ist ja auch kein Programmierkurs.

    Und viele Praxisbeispiele sind noch Python2 und rpi.gpio, das wollte ich nicht mehr.


    Was soll denn Zeile 115 bewirken?

    Leider bin ich noch nicht so fit in Python, dass ich fremden Code verstehe. Daher hatte ich auch in Zeile 115 die sinnlose Variable, ist gelöscht.

    Und die Erweiterung von dir kann ich ohne Anleitung nicht einbauen (zu doof dafür)

    Ich probiere weiter bis ich es rausgefunden habe, wie es geht. Danke dir.

    • Offizieller Beitrag

    Wir wäre es, wenn bevor Du taste = ('keine') in der main festlegst, erstmal nachfragst ob taste einen Wert hat? So ist imho taste immer = ('keine'). Bzw. taste = ('keine') wäre in Zeile 15 besser aufgehoben.

    from time import * Auch keine gute Idee. Importiere nur was Du wirklich brauchst.

    Bitte zeige immer den ganzen Code im Codeblock und mit einem Click auf das Wort Quellcode kannst Du dann auch die Syntax-Hervorhebung auf Python stellen.

    Ich glaube aber, dass ich die Funktion Button_xxxxx.when_pressed == True da falsch reingebracht habe...

    Wobei ich nicht so richtig verstehe, was die Funktion hol_taste für einen Sinn haben soll. Wie auch immer... Besser wäre aber imho die Variante:

    Indem du das, was beim Tastendruck gemacht werden soll, in die Funktion packst

  • Hallo,

    Zitat

    button_runter.when_pressed == True:

    Das kann auch nicht funktionieren. Mit `button.when_pressed = irgendwas` bindest du die Funktion `irgendwas` an das Event des Tastendrucks. Sprich, wenn `button` gedrückt wird, dann wird die Funktion aufgerufen.

    Wenn du abfragen willst, ob der Button jetzt gedrückt ist, dann wäre das

    Python
    if button.is_pressed:
        #do somesomthing

    Grundsätzlich ist der Ansatz in #4 auch nicht besser, weil du vom richtigen / besseren Event-getriebenen Ansatz in #1 auf Polling umgestiegen bist. Was in so fern schlechter, als dass dein Skript permanent "rennt", während es beim Event-getriebenen Ansatz tatsächlich auf die Tastendruckevents warten würde.

    Gruß, noisefloor

  • Habe eure Tipps ausgeführt, vielen Dank.

    Ich habe zuletzt versucht, mit den Interrupts direkt jeweils eine eigene Funktion für jede Taste aufzurufen, in der auch abgearbeitet wird.

    Da es 5 Tasten sind, wird es die Funktion 5mal in ähnlicher Weise geben. Sind viele doppelte Zeilen Code, hilft aber vermutlich, den Code übersichtlich zu halten. In der Abarbeitung ist das sicher kein zeitlicher Nachteil.

    Jetzt kennen die Funktionen zum Teil die Variablen nicht mehr :(. Und Global will ich ja vermeiden (schlechter Stil und so)

    Einige Fehlermeldungen sind neu für mich, dazu suche ich im Netz Erklärungen. Da werde ich noch lange dran sitzen... ich versuche es weiterhin.

    Unter https://www.python-kurs.eu/python3_funktionen.php lese ich weiter, in der https://gpiozero.readthedocs.io/en/stable/api_input.html#button suche ich Erklärungen für die GPIOZERO Module und hoffe, dies irgendwann zusammen zubringen...

    vielleicht finde ich auch noch was besseres als Thonny.

    Grüße

  • Hallo,

    im Zweifelsfall muss den Callback-Funktionen die Parameter über `partial` aus dem `functools` Modul mitgeben. Dazu gibt's auch Beispiele hier im Forum.

    Thonny hat mit deinen Problemen bzw. Schwierigkeiten nichts zu tun. Eine IDE macht das Programmieren zwar einfacher, aber Code nicht lauffähiger ;)

    python-kurs.eu hat in Teilen einen schlechten Ruf, weil da in manchen Kapiteln schlechtes, weil nicht-idomatisches Python gezeigt wird. Was man als Einsteiger aber nicht sieht und damit ggf. falsch lernt. Also: lieber die Finger davon lassen.

    Gruß, noisefloor

  • Hallo noisefloor,

    danke für die Infos. Habe ich eine Callback Funktion in Betrieb, von der ich nichts weiß? Muß erst danach suchen, was das bedeutet.

    In Thonny kann ich Code in Einzelschritten ausführen, das hilft mir schon weiter Vielleicht gibt es ein Tool mit mehr Funktionen oder Codevorschlägen für mich.

    Hab ja hier vieles gelesen, aber Python3 mit gpiozero ist noch nicht so vielfältig behandelt worden, leider. Und meigrafd s Github SampleCode habe ich noch nicht ganz durch...

    bis bald

    So

    habe jetzt zumindest die Abfrage und Anzeige wieder hinbekommen, allerdings wieder mit Globals :(

    Der Ablauf:

    Interrupt löst aus:

    Code
    Button_rechts.when_pressed = rechts

    der springt zur Bearbeitung

    Python
    def rechts():    
        global menu_nummer    
        global im_menu    
        im_menu = True    
        if menu_nummer < 4:        
        menu_nummer += 1    
        menu_anzeigen(menu_texte,menu_nummer)

    Der neue Menüpunkt wird angezeigt,

    das Gleiche mit Taste ok, wenn gedrückt, wird die angewählte Funktion ausgeführt z.B. Temperatur_anzeigen

    und die Variable im_menu wird auf False geändert, da die Anzeige nicht mehr im Menu steht.

    Wenn wieder ok gedrückt wird, wird ins Menü gesprungen und es beginnt von vorn :)

    Die Variablen im_menu und menu_nummer werden von den Tasten verändert, daher kann es nur über Global gehen , oder?

    Die Funktion z.B. rechts werden von dem Interrupt aufgerufen, da kann ich keine Variablen mitgeben.

    Die callback Funktion habe ich noch nicht gefunden, aber arbeite dran.:/

  • danke für die Infos. Habe ich eine Callback Funktion in Betrieb, von der ich nichts weiß?

    Die callback Funktion habe ich noch nicht gefunden, aber arbeite dran. :/

    ja, das ganze mit *.when_pressed und *.when_released

    aber Python3 mit gpiozero ist noch nicht so vielfältig behandelt worden, leider

    Aber dafür gibts ja das hier?!: https://gpiozero.readthedocs.io/en/stable/

    Und gpiozero kommt schon einige male hier vor...aber ich würd die offizielle Doku zur Hand nehmen und bei konkrete Fragen dann einfach Fragen.

    Wie ich die Menüführung mit Tastern gestaltet habe, kannst du dir hier Ansehen: Kaffeemaschine automatische Abrechnung

    (Ach den Link hab ich ja schon mal gepostet :P)

    EDIT: PS Bitte Doppelposts vermeiden

  • Hallo hofei,

    ja, das ganze mit *.when_pressed und *.when_released

    ach so, dass IST die callback-Funktion. Damit kann ich keine aktuellen Variablen mit Werten an die folgenden Funktionen übergeben.


    Aber dafür gibts ja das hier?!: https://gpiozero.readthedocs.io/en/stable/

    ja, kenn ich. Da stehen jedoch nicht die Erklärungen so umfangreich drin, dass man die Zusammenhänge versteht. Außerdem hab ich das technische Englisch nicht so drauf.

    Wie ich die Menüführung mit Tastern gestaltet habe, kannst du dir hier Ansehen: Kaffeemaschine automatische Abrechnung

    Ja, habe ich mir auch schon angesehen, das sieht sehr professionell aus. Einiges verstehe ich noch nicht in Python, das muss ich nachlesen.

    Mit einer class könnte ich vielleicht die global s vermeiden, das will ich versuchen.

    EDIT: PS Bitte Doppelposts vermeiden

    ich hab, glaub ich , nichts doppelt gepostet,oder?

  • Hab nochmal eine Frage zur Programmierung.

    Habe einen DHT22 an den Pi gesteckt um echte Werte anzeigen zu können.

    Bekomme es nicht hin, die Tasten mit GPIOZero unter Python3 abzufragen und dann den DHT22 mit Adafruit Bibliothek auszulesen.

    Einzeln klappt es mit den Programmen.

    Kann es sein, dass Adafruit nicht funktioniert, wenn auch GPIOZero aktiv ist ?

  • Ich meinte natürlich mit der Adafruit-Klasse im ORdner Adafruit_DHT den Sensor auslesen :shy:

    Die Fehlermeldungen in Thonny (was Besseres hab ich bis jetzt nicht) sagen:

    nach dem Start läuft noch die Anzeige und die Tastenabfrage.

    Wenn ich zur Funktion "luftfeuchte_anzeigen" komme, gibts die Meldungen...

    Ich habe mittlerweile Einiges versucht und viel geändert, es können jetzt noch weitere Fehler im Code sein :(

    Auch habe ich noch nicht aufgegeben, die Globals zu eliminieren. Da hab ich die Idee, die Tastenbehandlung in eine Klasse zu stecken...

    Das kommt später dran :)

  • Sieh mal ob das weiterhilft: http://www.ardutronic.microsoftsharepoint.de/2017/04/24/ard…ry_pi_2_driver/

    Zeile 21 luftfeuchte und temperatur müssen nicht in die funktion mit übergeben werden ;)

    Zeile 48, 49 sind ebenso überflüssig ...dafür musst du in Zeile 50 die Rückgabe speichern.

  • danke für die Hilfe, hat leider nicht viel gebracht, die Programmänderungen habe ich auch vorgenommen, jetzt sieht der Fehlerbericht so aus:

    Kann es wirklich nicht an den drei "Treibern" für die PIN Leiste liegen, dass die sich stören: LCD I2C, GPIOzero und Adafruit Eindrahtbus ???

    Der Assistant in Thonny sagt ausserdem:

    Da hab ich noch ne Menge zu richten... im neuen Code

  • die Programmänderungen habe ich auch vorgenommen, jetzt sieht der Fehlerbericht so aus:

    Aber nicht so wie gesagt:

    Zeile 21 luftfeuchte und temperatur müssen nicht in die funktion mit übergeben werden ;)

    siehe Zeile 51

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!