zwei Taster gleichzeitig mit add_event_detect?

    • Offizieller Beitrag

    Hallo!

    In letzter Zeit hatte ich öfter das Problem, daß sich bei meinem headless RaspiRadio der MPC nach dem Einschalten in den "Pause Modus" gegangen ist.
    Das Radio hat 5 Taster (shut down, Sender <, Sender >, Volume -, Volume +) und eine LED. Der 6. Taster (Pause/Play) war erst eingeplant, aber dann dummerweise von mir verworfen.

    Hier der Code:

    Wie bekomme ich bei gleichzeitigem drücken von Lauter+Leiser ein callback=Pause_Play hin? Habe bis jetzt nichts dazu gefunden, oder die falschen Suchbegriffe.

    Vielen Dank schonmal!

  • Hallo Hyle,

    Du hast einen Pseudo-Interrupt, der bei "LEISER" ausgelöst wird - und einen solchen für "LAUTER".

    Wenn Du beide Taster gleichzeitig drücken möchtest, wird immer einer der beiden gedrückten Taster zuerst auslösen. So hast Du es programmiert.

    Am einfachsten wäre es wohl, innerhalb des Pseudo-Interrupts zu prüfen, ob denn auch die andere Taste gedrückt ist. Wenn ja, dann setzt der Pseudo-Interrupt ein Status-Flag - wenn nicht, wird es gelöscht. Bei gesetztem Flag wird jeweils der Pseudo-Interrupt verlassen, ohne LAUTER oder LEISER weiter zu betrachten.

    In der Hauptroutine prüfst Du, ob dieses Status-Flag gesetzt ist und rufst eine Funktion auf, die dann das macht, was Du für [LEISER & LAUTER] = STOP oder PLAY vorgesehen hast.

    Da Du den Rest ja programmieren konntest, wirst Du wohl mit diesen Gedanken dem Ziel ein großes Stück näher kommen. Und ich fühle mich nicht genötigt, doch noch mal eine Zeile in dieser Programmiersprache schreiben zu müssen.

    Alternativ könntest Du beide betreffenden GPIOs über ein AND-Gatter schicken, das nur dann ein Signal erzeugt, wenn beide Taster gedrückt sind. Und dieses Signal geht dann an einen weiteren GPIO-Input, den Du analog programmierst. Das heißt, auch hier rivalisieren die drei Pseudo-Interrupts (LAUTER, LEISER, LAUTER & LEISER) miteinander. Du kannst nur sicher davon ausgehen, dass der Pseudo-Interrupt für LAUTER & LEISER, wenn beide TASTER gedrückt sind. Aber auch hier wird es so sein, dass häufig vorher ein PSeudo-Interrupt für entweder LAUTR oder LEISER ausgelöst wird. Das heißt, an der oben beschriebenen Programmier-Umsetzung ändert sich nichts.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (18. September 2016 um 09:55)

    • Offizieller Beitrag

    Hallo Andreas,
    vielen Dank das hat mir echt geholfen!

    Ich dachte mir schon, daß es dafür keine gute Lösung gibt. Dein Denkanstoß hat mich auch noch auf die Möglichkeit gebracht zu prüfen, wie lange z.B. LEISER gedrückt wurde. Wahrscheinlich wird Schalterprellen noch zusätzliche Probleme erzeugen.

    Dann mach ich das besser gleich richtig - Lötkolben raus und Taster nachrüsten. ;)

    Das war übrigens mein erstes Python-Script.

    :danke_ATDE:

  • Ich würde dir raten nicht os.system zu verwenden sondern das Python Module mpd2 zu nutzen, das wäre weitaus besser ;)

    Desweiteren kannst du eine einzige Callback definieren, dieser wird dann ja der pin (channel) übergeben welcher den Interrupt ausgelöst hat. Du prüft dann einfach nur noch welcher Pin das ist und behandelst das entsprechend.
    Siehe dazu auch FAQ => Nützliche Links / Linksammlung => Interrupt
    Da kannst du entnehmen das die Callback in einem separaten Thread läuft und daraus ergibt sich eine Besonderheit die du ausnutzen kannst - Siehe #7 von obigem Link ... Du hast nämlich eine while Schleife um das Script daran zu hindern sich zu beenden, diese Schleife kannst du nutzen.

    Und ein GPIO.cleanup() kannst du durch "pass" ersetzen.

  • Hallo Hyle,


    Das war übrigens mein erstes Python-Script.


    Da liegst Du mir schon uneinholbar voraus... :thumbs1:

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (18. September 2016 um 12:52)

    • Offizieller Beitrag


    Desweiteren kannst du eine einzige Callback definieren
    ...
    Callback in einem separaten Thread läuft und daraus ergibt sich eine Besonderheit die du ausnutzen kannst


    Ahh verstehe, wieder was gelernt. Danke meigrafd!
    python-mpd2 muß ich mir mal in Ruhe ansehen.



    Da liegst Du mir schon uneinholbar voraus...


    :blush:

  • Natuerlich gibt es dafuer eine gute Loesung. Es gibt ja da draussen Geraete, die so etwas koennen...

    Das Problem ist die Definition von "gleichzeitig". Wenn du echte Gleichzeitigkeit haben wollen wuerdest, dann wuerde kein Mensch das anders als nur zufaellig hinbekommen. Und das auch nur ein bis zweimal im Leben. Wir reden hier also *immer* ueber eine gewisse Latenz zwischen den beiden Ereignissen. Ein AND-Gatter wuerde das uebrigens nicht wirklich helfen, du haettest zwar ein klares Signal fuer deine Doppeltastenbelegung, aber wuerdest trotzdem mindestens eine, wenn nicht beide alternativen Funktionen ausloesen. Bei Lautstaerke rauf/runter mag das verschmerzbar sein, spaetestens bei Dingen wie Lied wechseln oder aehnlichem wird es unangenehm.

    Das simple pruefen, ob eine andere Taste gedrueckt ist, hilft auch nur sehr, sehr bedingt. Da kommen wir zwar von unendlich kleinem delta-t fuer eine Zeitspanne auf "Zeit zwischen Kernel realisiert einen Tastendruck bis Python bekommt davon etwas mit" - aber das ist eine zum ersten schwammige, und zweitens immer noch im Mikrosekundenbereich angelegte Zeitspanne.

    Stattdessen will man ja ueblicherweise eine definierte Zeitspanne haben, statt sich auf eher zufaellige Systemeigenschaften zu verlassen.

    Und dazu hat die Informatik eine Loesung parat: Zustandsautomaten.

    Diese bestehen aus einer Reihe von Zustaenden, die ein System einnehmen kann - nix tun (idle), lautstaerke erhoehen, umschalten play/pause - und Ereignissen, die einen Uebergang von einem zum naechsten erlauben.

    Dein bisheriges vorgehen sieht aus wie in Grafik "normal-volume-control.png". Du hast einen idle-Zustand, und wenn einer der Taster gedrueckt wird, springst du in den Zustand "volume_up" bzw "volume_down".

    Was du aber stattdessen brauchst ist ein Automat der aussieht wie folgt:

    Das sieht kompliziert aus, ist es aber gar nicht. Es gibt eine Reihe von Ereignissen - volume+pressed, volume+released (druecken/loslassen des Volume + Tasters), dasselbe fuer Volume -, und noch zwei besondere Ereignisse: epsilon, das Ereignis das auftritt wenn es nichts gibt, und zeitbasierte Ereignisse.

    Damit kann man dein Problem schoen modellieren. Wenn eine Taste gedrueckt wird (nehmen wir zB mal volume+), dann wissen wir noch nicht genau, was passieren soll. Es kann lauter bedeuten, oder gleich kommt die zweite Taste dazu, und dann heisst es toggle play/pause. Also haben wir einen Zustand, der das repraesentiert - volume_up_or_toggle.

    Aus dem geht es entweder nach einer gewissen Verzoegerung nach volume_up, womit dann die Lautstaerke erhoeht wird.
    Oder die zweite Taste kommt dazu, und wir wissen, wir sind in toggle_play_pause.

    Und noch etwas cooles kann man machen: zum einen hat ein sofortiges loslassen der Taste die Folge, dass sofort in "nudge_up" gewechtelt wird - man kann also schnell hoch/runter druecken, ohne doofe .3 Sekunden warten zu muessen.

    Und wenn man die Taste gedrueckt haelt, fuehrt der Zustand "volume_up" durch einen Timeout auf sich selbst, alle .5 Sekunde. Das ist dann das Feature "gedrueckt halten & langsam geht die Lautstaerke rauf".

    Code, der das alles illustriert, findet sich auf https://github.com/deets/brombeer…diosimulator.py.

    Das Modul tfa.py, das man braucht, liegt daneben: https://github.com/deets/brombeer…io-utils/tfa.py

  • Oh gott, so viel Text wegen solch einer Kleinigkeit :-/

    Ob man jetzt ein zusätzliches Module nutzt oder sowas eben jüst selber umsetzt.... Verkomplizieren kann man es dann immernoch :fies:


    BTW: Mit gpiozero lässt sich sowas extrem vereinfacht umsetzen: https://www.raspberrypi.org/blog/gpio-zero…ical-computing/

  • Seit wann bist *DU* denn ein Kurzgefasster? :lol: :lol: Klassischer Fall von der Rabe nennt die Kraehe schwarz...

    Schreib mal was ich da so zusammengebaut habe mit deinem gpiozero. Butter bei die Fische... bin mal gespannt.

  • Entschuldige bitte aber wieso machst du neuerdings aus ner Mücke einen Elefanten? Wir haben hier ein Thema und zu diesem Thema schrieb ich was.. Ich hab nie behauptet Dein Module mit gpiozero umsetzen zu wollen
    Schön und gut das man mit der Zeit wächst und es später ein mal anders/besser machen kann, aber das da oben ist IMHO für dieses Thema hier, übertrieben.
    Ein StatusFlag setzen um so zu verhindern das 2 gleichzeitig gedrückte Taster auch beide etwas ausführen ist völlig ausreichend - und nu häng dich bitte nicht schon wieder am 'gleichzeitig' auf sonst können wir in 90% der Threads hier auch zu RTOS usw raten.....

  • Wie waere es, wenn du den TE entscheiden laesst, ob er mit meiner Loesung etwas anfangen kann, oder nicht? Wer hat dich dazu beauftragt, den Anwalt fuer das Verstaendnis, und den Lernwillen anderer zu sein?

    Ich habe die Loesung entwickelt, weil es mir Spass gemacht hat, ueber das Problem nachzudenken, und es zu loesen. Mit keinem Wort habe ich behauptet, dass die Loesungen, die andere vorgeschlagen haben, nicht ebenfalls funktioneren wuerden.

    Doch mit schoener Regelmaessigkeit meldest du dich zu Wort, und unterstellst ich wuerde irgendwen dazu zwingen wollen, etwas so zu machen, wie ich es fuer richtig halte. Was kompletter Unfug ist, aber Baende spricht darueber, wie es um dein Selbstwert aussieht. Bekomm das mal in den Griff. Wirklich.


  • Ob man jetzt ein zusätzliches Module nutzt oder sowas eben jüst selber umsetzt.... Verkomplizieren kann man es dann immernoch :fies:

    Wenn du der Meinung bist, meine Postings herabzuwuerdigen, dann habe *ICH* dazu eine Meinung, die ich auch aeussere. Wald. Rufen. Rein. Raus. Mach nen Satz draus.

    bootsmann Schoen wenn es etwas besseres als RPI.GPIO gibt - das ist nun wirklich nicht besonders dolle, wobei Teile des Problems im Linux Kernel selbst liegen. So kann es zB sein, dass eine Flanken-Triggerung danach nicht den richtigen Wert liefert, weil der nicht mehr anliegt beim einlesen.

    PIGPIO macht das dank DMA geschickter, weil gleich gesamplet. Wie geht gpiozero damit um?

    • Offizieller Beitrag

    Bis einer heult... =( Beruhigt euch bitte!

    Nochmals Danke an ALLE, ich werde mir die verschiedenen Ansätze mal in Ruhe ansehen. Aber ihr könnt vergessen, daß ich euch mitteile wofür ich mich entschieden habe. So das habt ihr jetzt davon!

    Bevor das hier noch ausartet markiere ich das Thema als erledigt,

  • Du musst mal an deinem Textverstaendnis arbeiten. Ich habe die Physik dieser Welt nicht gemacht, beschwer dich bei dem Schoepfer deiner Wahl. Und "an die Decke" gehe ich *NACH* deinen Bemerkungen zur Ueberkompliziertheit und Unnoetigkeit meines Beitrags. Die keine inhaltliche Auseindersetzung mit meinem Code darstellen, sondern schlicht eine Herabwuerdigung, zu deren Antrieb man vieles sagen koennte....

  • Hallo Meigrafd, hallo __deets__,

    es gab hier Lösungsvorschläge, die auf zwei unterschiedlichen Ansätzen aufbauen. Der eine mit dem Flag-setzen (den ich auch gebracht habe) - und die Vollprofi-Lösung von __deets__.

    Auch wenn der Vorschlag nicht von mir gekommen ist, erkenne ich dessen Vorteile - um nicht zu sagen Genialität. Nur ... und das ist mir bei meinen Beiträgen immer wichtig: Wo steht der Fragesteller, wo hole ich ihn ab, um ihn zur Lösung zu führen?

    Der Fragesteller hyle hat schnell durchblicken lassen, dass er noch nicht jahrzehntelange Erfahrung aufweist, aber schon was recht Brauchbares recht sinnvoll umgesetzt hat und letztlich nur Kleinigkeiten verfeinert zu werden brauchen. Also "hole ich ihn ab", indem ich einen einfachen, aber funktionsfähigen, Ansatz beschreibe, von dem ich glaube, dass hyle ihn versteht und eigenständig umsetzen kann.
     
    Das mit dem Flag-setzen ist mit ganz wenigen zusätzlichen Zeilen und einer neuen Funktion im ersten selbstgeschriebenen Skript irgendwie - vielleicht auch mit Nachfragen - machbar.

    Dein Vorschlag, __deets__ ist super. Nur befürchte ich persönlich, dass es über das hinaus geht, was der Fragesteller hyle momentan programmiermäßig umsetzen kann und für seine fast fertige Entwicklung noch draufsetzen will. Dies will ich nicht als Kritik an Deinem Beitrag verstanden wissen, __deets_! Dein Vorschlag ist berechtigt - Kritik daran kann ich allerdings nicht nachvollziehen.


    Aber soll Hyle entscheiden, welchen der beiden skizzierten Wege er gehen möchte. Beide Wege sind gut, beide führen zum Ziel.


    Und wenn ich mal gereizt bin, dann schaue ich gern mal hier und dort rein. Wobei ich leider sagen muss, dass das auch nicht immer hilft... aber immer öfter...

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    3 Mal editiert, zuletzt von Andreas (16. Oktober 2017 um 11:28)

Jetzt mitmachen!

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