liste von callback funktionen ... mit Paramerterübergabe

  • Hallo,

    das Programm
    [PHP]
    import RPi.GPIO as GPIO
    BounceTime=50 #[ms]
    GPIO.setmode(GPIO.BCM)
    switm=[23,24] # GPIOs Taster
    for i in switm :
    GPIO.setup(i,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
    print ('setup:',i)

    def ButtonPressed(value) :
    print ('ButtonPressed @ GPIO # :',value)

    """for i in range(len(switm)) : # geht nicht
    GPIO.add_event_detect(switm[i], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[i]), bouncetime=BounceTime)
    """
    GPIO.add_event_detect(switm[0], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[0]), bouncetime=BounceTime)
    GPIO.add_event_detect(switm[1], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[1]), bouncetime=BounceTime)
    [/PHP]
    funktioniert.

    ABER warum funktioniert der eleganter Weg (Auskommentiert) nicht. Ich hätte eine liste von solchen Funktionen zu starten.

    Bitte um eine "Umweg" :)

    Danke

    Gottfried

  • liste von callback funktionen ... mit Paramerterübergabe? Schau mal ob du hier fündig wirst!

    • Offizieller Beitrag

    weil len eine länge zurück gibt. er würde er versuchen interupts für 0 und 1 zu setzen. (länge von switm =2, bei 0 angefangen zu zählen ergibt 0,1) Ein

    Code
    "for i in switm:
    GPIO.add_event_detect(i, GPIO.BOTH, callback=lambda x: ButtonPressed(switm[i]), bouncetime=BounceTime)

    sollte klappen

  • sorry - nein,

    ich musste Deinen Vorschlag etwas adaptieren weil
    [PHP]
    GPIO.add_event_detect(switm[i], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[i]), bouncetime=BounceTime)
    [/PHP]
    ja in beiden Fällen (also 1. Parameter und parameter @ ButtonPressed) die GPIO Nummer übergeben werden muss. Ja und dann steht praktisch wieder dasselbe da wie bei mir und es kommt immer der als letzter definierte callback, also in meinem Fall 24.

    Ich vermute, dass Python hier eine Adresse (call by reference) übergibt und die Adresse von "i" ist immer die letzte...? Oder?

    Ich weiss auch nicht wie der "String"-Anfang vor der for Schleife gemeint war.

    Summa Summarum - geht nicht

    Gottfried

  • Hallo,

    über eine Liste mittels `for in in range(len(...))` zu iterieren ist voll das Python Anti-Pattern - macht man nicht.

    Im Vorschlag von dbv war ein Fehlerchen. So sollte es richtig sein:

    Code
    for pin in switm:
        GPIO.add_event_detect(pin, GPIO.BOTH, callback=ButtonPressed(pin), bouncetime=BounceTime)

    Welchen Sinn hat denn das `lambda` beim Callback? Das ist IMHO überflüssig, weil du den Callback doch an die Funktion `ButtonPressed()` binden willst - und nicht an eine anonyme Lambda-Funktion.

    Gruß, noisefloor

    • Offizieller Beitrag

    hihi, eigentlich wollte ich exakt das schrieben was noiseflor geschrieben hat, ich sollte keine posts zwischen Meetings machen :). Aber selbst mit Fehlern war der Ansatz erkennbar, wenn er den channel erwartet, übergebe ich den channel und keine länge des listenobjektes ;)

  • Hallo noisefloor


    Welchen Sinn hat denn das `lambda` beim Callback? Das ist IMHO überflüssig, weil du den Callback doch an die Funktion `ButtonPressed()` binden willst - und nicht an eine anonyme Lambda-Funktion.

    Im Beispiel wird eine Liste von Interrupts mit der selben Callback serviciert und dort muss ich die Information haben welcher es war. Und via Globals finde ich das nicht ... lustig.


    über eine Liste mittels `for in in range(len(...))` zu iterieren ist voll das Python Anti-Pattern - macht man nicht.

    OK, aber warum geht es nicht?

    Und das herzigste:
    [PHP]
    import RPi.GPIO as GPIO
    BounceTime=50 #[ms]
    GPIO.setmode(GPIO.BCM)
    switm=[23,24] # GPIOs Taster
    for i in switm :
    GPIO.setup(i,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
    print ('setup:',i)

    def ButtonPressed(value) :
    print ('ButtonPressed @ GPIO # :',value)

    for i in switm :
    print ('i:',i)
    GPIO.add_event_detect(i, GPIO.BOTH, callback=lambda x: ButtonPressed(i), bouncetime=BounceTime)
    """
    GPIO.add_event_detect(switm[0], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[0]), bouncetime=BounceTime)
    GPIO.add_event_detect(switm[1], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[1]), bouncetime=BounceTime)
    """
    [/PHP]

    funktioniert trotzdem nicht - egal welchen Taster man drückt value in ButtonPressed ist 24. Wenn man die beiden Elemente in switm tauscht dann eben 23 (immer der letzte). Und die brute-force Methode (auskommentiert) funktioniert!

    Womit wir am Ausgangspunkt der Frage wären - wie macht man das und warum geht es nicht?

    Danke

    Gottfried

    Einmal editiert, zuletzt von gottfried50 (3. Februar 2016 um 12:18)


  • weil len eine länge zurück gibt. er würde er versuchen interupts für 0 und 1 zu setzen. (länge von switm =2, bei 0 angefangen zu zählen ergibt 0,1) Ein

    Code
    "for i in switm:
    GPIO.add_event_detect(i, GPIO.BOTH, callback=lambda x: ButtonPressed(switm[i]), bouncetime=BounceTime)

    sollte klappen

    Wo übergebe ich eine "Länge eines Listenobjektes" an irgendwen?
    [PHP]
    for i in range(len(switm)) : # geht nicht
    GPIO.add_event_detect(switm[i], GPIO.BOTH, callback=lambda x: ButtonPressed(switm[i]), bouncetime=BounceTime)
    [/PHP]
    und range(len(switm)) ist schlicht 0 und 1 .... oder übersehe ich da

    was?

    • Offizieller Beitrag
    Zitat

    for i in range(len(switm))


    lies:
    for i in range 0 bis 1. Das ist absolut überflüssig, wenn ein

    Code
    for blub in switm

    gleich den Channel setzt. Erst den Index aus Länge des Listenobjektes zu suchen und dann das Listenobjekt mit dem Index anzusprechen ist absolut unpythonisch, am Ende kommt 23/24 raus. Aber einfach Lesbar ist das nicht.

    Funktioniert noiseflor sein Lösungsvorschlag?

  • Auch ich versteh die Verwendung des ``lambda`` Ausdruckes hier nicht. DDer Paramenter ``callback`` in der ``add_event_detect`` Funktion erwartet ja als Argument eine Funktion. Nun kommt aber mit dem ``x`` ein zusätzliches Argument, welches gar nicht verwendet wird, daher (oder liege ich hier falsch?).

    Hier mal meine Lösung (ich hab ein Öffner und ein PIR-Sensor, also 1x .RISING und 1x .FALLING)

    Auch sei hier auf die Namenskonvention von Python hingewiesen (PEP 8).

    PS:
    Warum auch immer hier ein Leerzeichen beim Einfügen weggeschnitten wird, mein Code enthält 4 Leerzeichen.

  • Hallo,

    ich habe meine unbefriedigende Lösung mit Lambda von ...
    https://www.raspberrypi.org/forums/viewtopic.php?f=32&t=50833
    ... schlicht abgeschrieben - mit anderen Worten - ich kann das auch nicht erklären .. aber sie geht

    und selbst hier im Forum:
    Wie sage ich es in Python ? (Einsteigerfragen)
    wird das mit Lambda gemacht.

    Was ich ... hmmm ... witzig finde: Die Frage war ja eine (mehrere) Callback mit Paramter - das steht doch groß und deutlich als Titel da .... ist das verloren gegangen?

    Also noch einmal: mein Code funktioniert wie am Anfang dargestellt. Die Frage ist >wieso geht das in der Schleife nicht< - meinetwegen mit "for i in switm...." und zweitens >wie kann man das mit einer Liste von Events in die selbe Callback machen?<

    Danke Euch

    Gottfried

  • Hallo,

    Zitat

    Was ich ... hmmm ... witzig finde: Die Frage war ja eine (mehrere) Callback mit Paramter - das steht doch groß und deutlich als Titel da .... ist das verloren gegangen?


    Lies' den Titel doch mal... dann kannst du die Frage schon mal selber beantworten.

    Zitat

    und zweitens >wie kann man das mit einer Liste von Events in die selbe Callback machen?<


    Indem du jedes Event an die selbe Callack Funktion bindest. In deinem Beispeil-Code kommt aber nur ein Event vor, nämlich `BOTH`.

    BTW: der Satz steht im Widerspruch zum Titel - da steht nämlich "Liste von Callback Funktionen" und nicht "liste von Events" - was denn jetzt?

    Beschreib' doch mal verständlich und _ausführlich_, was du vorhast bzw. was das Ziel ist. Erspart uns das Raten und Spekulieren und dir beschert es hoffentlich schneller eine Lösung.

    Gruß, noisefloor

    Einmal editiert, zuletzt von noisefloor (4. Februar 2016 um 19:30)

Jetzt mitmachen!

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