Mit gpiozero.Button.when_pressed mehrere Aktionen gleichzeitig ausführen ?

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hallo liebe Community,

    Ich würde gerne per gpiozero.Button mit dem Befehl button.when_pressed mehrere Ausgänge gleichzeitig schalten. Leider funktioniert keine meiner getesteten Ansätze und ich finde auch kein Beispiel dazu, weder in der Dokumentation von gpiozero oder sonst wo im Internet.

    Ich habe mittlerweile Versucht:

    Eine simple "and" Verküpfung (wie aktuell im Code) -> dies führt dazu, dass nur der zweite Befehl ausgeführt wird.

    Ich habe versucht beide Ausgänge in einer Funktion zu vereinen und die Funktion zu schalten -> bei dieser Version wird keiner der beiden Ausgänge geschalten.

    Und dann habe ich noch versucht mit zusätzlichen if button.is_pressed: schleifen zu arbeiten -> dies führt je nach dem auch dazu, dass nur der letztgenannte oder keiner der Ausgänge geschalten wird.

    Hätte wer hierzu eine Idee? :conf: (Hab mal meine Ansätze auskommentiert im Code gelassen)

  • Mit gpiozero.Button.when_pressed mehrere Aktionen gleichzeitig ausführen ?? Schau mal ob du hier fündig wirst!

  • Vielleicht so?

    Ungetestet und nur auf die Schnelle geschrieben ,Beispiele gibts unter : https://gpiozero.readthedocs.io/en/stable/reci…-controlled-led

    LEDS sollten bei gedrückten Button beide angehen und beim loslassen wieder ausgehen.

    4 Mal editiert, zuletzt von Bertthias (7. August 2022 um 15:00)

  • Hab den Fehler gefunden. Wohl ein Anfängerfehler meinerseits.

    Augenscheinlich wird in der aufzurufenden Funktion der Callback () benötigt obwohl dies bei einem Direktaufruf zu einem Fehler führen würde.

    Die aufzurufende Funktion mit mehreren Aktionen hat so auszusehen:

    Code
    def up1():
         DC1.forward()
         LED_1.on()
         return
  • Könnte so aussehen. Ich bin mir nur nicht sicher, ob die übergebene Instanz von Button stammt. Jedenfalls kann man einen Callback die fallende und steigende Flanke abarbeiten lassen.


    Dieses Beispiel ist eine Busy-Loop. Gut geeignet, um den Prozessor zu erwärmen:

    Python
    while True:
        Button.when_pressed = LED_an
        Button.when_released = LED_aus
  • Könnte so aussehen. Ich bin mir nur nicht sicher, ob die übergebene Instanz von Button stammt. Jedenfalls kann man einen Callback die fallende und steigende Flanke abarbeiten lassen.

    Ich bin was Programmieren anbelangt nicht so ganz fit. Ich hab blos einige Grundkenntnisse in C erlernt was aber auch schon Jahre zurückliegt.

    Zum Callback: Der von dir zur Verfügung gestellte Code spuckt bei mir Massenweise Fehler aus. Irgendwas passt da nicht mit den übergebenen Werten und/oder mit den Klassen. Hab bissl rumprobiert und egal was ich versuche es kommen Probleme ala:

    Code
        super(RPiGPIOPin, self)._call_when_changed()
        super(LocalPiPin, self)._call_when_changed(
        method(ticks, state)
        self._fire_events(ticks, bool(self._state_to_value(state)))
        self._fire_activated()
        super(HoldMixin, self)._fire_activated()
        self.when_activated()
        return fn(self)
        if pin.value():
    TypeError: 'int' object is not callable

    Ich hab keine Ahnung was ich damit anfangen soll. Wenn ich die Fehlermeldungen google komm ich zu stackoverflow Seiten wo ich noch weniger verstehe, weil da immer Beispiele genannt werden die ich leider auch nicht nachvollziehen kann.

    Zitat von DeaD_EyE

    Dieses Beispiel ist eine Busy-Loop. Gut geeignet, um den Prozessor zu erwärmen

    Zu deiner Busy-Loop Aussage, ich versuche sowieso nach Möglichkeit keine über flüssigen Schleifen zu verwenden. Dennoch soll das Script "dauerhaft laufen".

    Ich hab das jetzt mal so gelöst:

    Das Script macht jetzt was es meiner Meinung nach machen soll. Das ganze läuft und ich kann mit 4 Buttons 2 DC-Motoren auf und abfahren lassen.

    Mir ist schon klar dass dies wohl keine programmiertechnisch elegante Lösung ist.

    Ich bin auch für Verbesserungsvorschläge offen (welche ich mit meinem begrenztem Wissen nachvollziehen kann).

  • Korrigierte Version (Button.value ist ein int und keine Methode):

  • Hallo,

    Ich bin auch für Verbesserungsvorschläge offen (welche ich mit meinem begrenztem Wissen nachvollziehen kann).

    Leere Zeilen werden nicht mit Kommentarzeichen gefüllt. Kommentare sind dazu da um dem Leser zu erklären warum der Code etwas macht, wenn das nicht ersichtlich ist. Was der Code macht, steht da schon als Code und muss nicht erklärt werden. Wenn du sprechende Namen verwenden würdest, würdest du dir Kommentare wie 'Status indicator LED' sparen können. An Sich schreibt man keine Kommentare "rechts hinter" den Code, sondern über die Zeile mit den selben Einrückungen.

    Auf Modulebene, alles ohne Einrückungen, sollte kein ausführbarer Code stehen. Der Einstieg in die 'main'-Funktion ist die Ausnhame ('if __name_ == '__main__':").

    In Python werden Konstanten GANZ_GROSS geschrieben, Klassen in PascalCase-Schreibweise und der Rest klein_mit_unterstrich. Namen nummeriert man eigentlich auch nicht durch, denn die Zahlen geben dem Leser meist keinen Mehrwert. Oft braucht man auch keine Namen und man würde die Objekte eher in eine Liste stecken.

    Alles was du auf Modulebene stehen hast gehört da nicht hin. Du könntest dort aber die einzelnen Pins als Konstanten definieren.

    Wenn eine Funktion nichts zurück gibt, dann ist ein "leeres" 'return' überflüßig. Die Funktion hört auf wenn nichts mehr zu tun ist.

    Üblicherweise wird das Programm aus einer Funktion mit dem Namen 'main' gesteuert. Die if-Abfrage, die den internen Namen der Python Datei abfrägt, dient als Einstiegspunkt in diese Funktion.

    Man versucht doppelten Code zu vermeiden. Du hast zwei Funktionen die jeweils einen Motor ansteuern. Dabei ist der Code identisch, es sind nur andere Motoren. Dafür kann man Funktionen Argumente übergeben. Dann hat man eine Funktion und übergibt ihr je nach Bedarf den einen oder den anderen Motor/Led.

    Default-Werte wie 'initial_value=False' brauch man nicht noch mal angeben.

    Zwischenstand:

    Meiner Meinung nach aufgeräumter. Die Namen sind noch durch nummeriert, da ich nicht weis, was da gemacht wird.

    Zum Thema 'partial': Wenn du eine Funktion aufrufst und ihr Argumente übergibst, dann stehen die in der Klammer beim Funktionsaufruf. Die Klammer ist aber, wie du selbst bemerkt hast, dafür zuständig, dass die Funktion ausgeführt wird. Bei 'when_pressed' will man aber nicht dass die Funktion gleich ausgeführt wird, wenn der Interpreter darüber stolpert, sondern eben erst wenn der Button gedrückt wurde. Also darf da keine Klammer stehen, aber wohin jetzt mit den Argumenten? Genau das Problem löst 'partial'. Erst kommt die Funktion und dann mit Komma getrennt kommen die Argumente.

    Ich hoffe das ist so geschrieben, dass du den Programmablauf nachvollziehen kannst.

    Das ganze kann man nocht weiter kürzen und Objekte mit Schleifen erstellen, Listen oder Dictonarys nutzen um geschickter auf Objekte zuzugreifen, aber eins nach dem anderen. Da solltest du mal das offzielle Tutorial durcharbeiten, damit dir die Grundlagen und der Umgang mit Funktionen wie auch Datentypen klar sind.

    In dem Sinne weiterhin viel Spass mit Python.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

Jetzt mitmachen!

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