Scroll-Menü

  • Aha oke.

    Generell ist es schon mal besser mit Interrupts zu arbeiten, das schont die CPU Auslastung und sorgt auch dafür fast kein trigger Event zu verpassen (in der Zeit wo das Script mit sleep blockiert wird kann auf nichts reagiert werden)

    Der callback vom gpio event übergibt nur den Pin des GPIO von wo der event ausgelöst wurde. Den kannst du so wie in Beitrag#15 also nicht nutzen.
    Auch solltest du im callback mit if..elif.. usw arbeiten das machts schneller, weil wenn eins zutrifft muss das andere nicht auch noch geprüft werden.

    Der callback wird immer wieder aufgerufen sobald ein event auftritt, also ein RISING gpio passiert. Das läuft im Hintergrund in einem Thread. Das Script selbst beendet sich aber sobald es von oben nach unten abgearbeitet wurde und beendet dann auch den Interrupt Thread. Deshalb sollte man hier das Script daran hindern sich zu beenden. Da habe ich mir angewöhnt signal anstatt einer while Schleife zu verwenden.
    Und wenn es beendet wurde sollte man auch GPIO.cleanup() aufrufen damit die eingestellten GPIO's wieder auf Werkszustand zurückgesetzt werden (und beim nächsten Scriptstart keine Warnings mehr ausgegeben werden)


    Versuch es mal hiermit:
    [code=php]
    #!/usr/bin/python
    import RPi.GPIO as GPIO
    import signal

    Taster1 = 4
    Taster2 = 17

    auswahl = ["Menupunkt 0", "Menupunkt 1", "Menupunkt 2", "Beenden"]

    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Taster1, GPIO.IN)
    GPIO.setup(Taster2, GPIO.IN)

    Counter = 0

    def menueAuswahl(pin):
    global Counter
    Counter = (Counter + 1) % 4
    #print("Rising edge detected on %s" % pin)
    if Counter == 0:
    print(auswahl[Counter])
    elif Counter == 1:
    print(auswahl[Counter])
    elif Counter == 2:
    print(auswahl[Counter])
    elif Counter == 3:
    print(auswahl[Counter])

    def menueAendern(pin):
    #print("Rising edge detected on %s" % pin)
    print("Menüwechsel nach: %s" % auswahl[Counter])

    try:
    GPIO.add_event_detect(Taster1, GPIO.RISING, callback=menueAuswahl, bouncetime=200)
    GPIO.add_event_detect(Taster2, GPIO.RISING, callback=menueAendern, bouncetime=200)
    signal.pause()
    except KeyboardInterrupt:
    print("\nQuit\n")

    GPIO.cleanup()
    [/php]

    Drückst du jetzt 2x auf Taster1 gibt er dir über menueAuswahl -> Menupunkt 1 aus.
    Drückst du dann auf Taster2 sollte er über menueAendern ausgeben: Menüwechsel nach: Menupunkt 1

    Später kann man sich diese ganzen if...elif in menueAuswahl aber eigentlich auch schenken sofern da nicht noch was anderes ausgeführt werden soll, Hauptsache er zählt den Counter hoch ;)

    • Offizieller Beitrag

    Außerdem nutze ich gerne

    Python
    from time import *


    um den Befehl "sleep(X)" und weitere Timefunktionen zu importieren.
    So spart man sich immer die längere Version "time.sleep(X)".


    Bitte nutze keine Wildcard imports. Warum? einfaches Beispiel:
    erstelle ne ne Datei namens
    testimport.py und schreib folgendes rein

    Code
    def sleep(zahl):
    	return zahl +2


    dann ne konsole auf

    Python
    >>>from time import *
    >>>from testimport import *
    >>>sleep(4)
    >>>6


    Der letzte import gewinnt ;). sleep ist jetzt ein nur ein Beispiel im das zu veranschaulichen, aber es gibt durch aus Module in den ein und der selbe Funktionsname vollkommen andere Bedeutungen hat.
    Wenn du sleep importieren willst und du dir sicher bist das es sleep nur einmal gibt, dann nutze

    Python
    from time import sleep


    Auf der Sicheren seite ist man mit

    Code
    import time
    time.sleep
  • Erstmal: verdammt ist das immer umständlich Texte in einen Pythoncode zu verwandeln. Immer sind diese verfluchten unsichtbaren utf8 Formatierungen vorhanden...:@

    Danke meigrafd!So lernt auch der kleine Michi noch was dazu :thumbs1:

    Nach einem Test meines Codes musste ich auch feststellen, dass die sleeptime von 0,5 etwas zu lange gewählt war. War ja auch nur "quick'n'dirty". Da muss man die Taste schon recht lange (min.1sec) gedrückt halten, damit was passiert. Warum das allerdings nicht über Punkt 2 hinauslief, erschließt sich mir gerade nicht (könnte es mir evtl. durch fehlerhafte Formatierung erklären....).

    Zu meiner "Entschuldigung":
    Sleep verwende ich idR. nur wenn ich weiß, das jetzt nichts passieren wird und ich dem Pi ruhig mal eine Pause gönnen kann. Kann natürlich blöd werden, wenn der Pi grad ne Pause macht und ich ihm einen Tastendruck mitteilen möchte. Da ist die Wahl der interrupttechnik wirklich die optimalere, um nix zu verpassen.
    Ist halt immer eine Frage der jeweiligen Anwendung.

    /edit:
    Danke, DBV für den Hinweis. IdR. verwende ich aber keine Systemvariablen, also würde ich mir z.B. niemals eine Funktion sleep basteln. Werde mir den Hinweis aber zu Herzen nehmen.

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

    Einmal editiert, zuletzt von LieberScholli (20. Januar 2015 um 00:48)

  • Ihr habt mir schon sehr weitergeholfen. Nur, wenn ich dann mal eine Aktion, aufrufen will, muss ich doch den Counter abfragen, warum brauche ich die if elif dann nicht mehr? Wie frage ich sonst ab, wo der Counter steht?

  • Kannst du mir erklären warum das %s die auswahl einsetzt?

    Der Counter ist global, ist also überall verfügbar, und in menueAuswahl wird er geändert und steht dann zB auf 1. In menueAendern wird der dann abgerufen.

    %s steht für "string" - manchmal kann es Probleme geben wenn man " + " verwendet wie zum Beispiel:

    Code
    zahl = 5
    print("bla " + zahl)


    Dann meckert er das er ein integer nicht in ein str eingefügt werden kann, oder so...:

    Code
    TypeError: cannot concatenate 'str' and 'int' objects


    Würde man aber stattdessen

    Code
    zahl = 5
    print("bla %d" % zahl)

    verwenden gibts keine Fehlermeldung da er dann die Variable in decimal formatiert.
    Siehe dazu unter "String Formatting Operator": http://www.tutorialspoint.com/python/python_strings.htm

    Nur, wenn ich dann mal eine Aktion, aufrufen will, muss ich doch den Counter abfragen, warum brauche ich die if elif dann nicht mehr? Wie frage ich sonst ab, wo der Counter steht?

    Das würde schon reichen:
    [code=php]
    def menueAuswahl(pin):
    global Counter
    Counter = (Counter + 1) % 4

    def menueAendern(pin):
    print("Menüwechsel nach: %s" % auswahl[Counter])
    [/php]
    Der Counter wird durch Counter = (Counter + 1) % 4 verändert sobald die Anweisung menueAuswahl ausgeführt wird.

    //EDIT: Nur um eben die Grafik zu wechseln müsste in menueAuswahl noch mehr rein, also wirklich optisch zu scrolln ;)

  • OK, nochmal zum Verständnis für mich...für meine LCD Anzeige schreibe ich irgendwo im Script:
    if Counter == 0 :
    lcd.message ("was auch immer") Das muss nicht bei menueAuswahl stehen?
    EDIT: OK,kapiert.

    Einmal editiert, zuletzt von modulok (20. Januar 2015 um 01:04)

  • Dort, wo der "Counter", also die Menuauswahl verändert wird, sollte selbstverständlich auch eine Ausgabe an den User erfolgen.
    Aber bist ja auf nem gutem Weg. Viel Erfolg noch und bis später :thumbs1:

    ...and write down with pencil&paper...
    Where can i download "pencil&paper" ?

  • Hi,


    Erstmal: verdammt ist das immer umständlich Texte in einen Pythoncode zu verwandeln. Immer sind diese verfluchten unsichtbaren utf8 Formatierungen vorhanden...


    Dazu kann ich zwar nichts sagen aber in diesem Fall ist wohl das ü in Menüpunkt ist der Übeltäter. ;)

    meigrafd Am Anfang hast du so wies aussieht noch daran gedacht, am Ende waren die Finger dann wohl doch schneller :D

    DON'T PANIC!

  • modulok
    Gefühlt schon 100x geschrieben:


    Bitte gleich wieder vergessen, dass es in Python globale Variablen gibt.

    Schreib einen Dekorator und verknüpfe diesen mir der Funktion ``menueAuswahl`` oder Schreib eine Klasse. Globale Variablen sind nur was für Pfuscher. Und per Gelegenheit schau dir auch gleich noch PEP8 - die Rechtschreibregel für Python - an.

    meigrafd
    modulok verwendet wie du wahrscheinlich auch Python2.7. Also lass die Klammern bei der ``print`` Anweisung weg, denn damit schaffst du dir nur zusätzliche Probleme (wie in einem anderen Thread, wo ein user Python3 verwendet und du aber offensichtlich Python2 und du mekerst, dass er ein Tuple erstellt - es ging um irgend einen Zeitstring - aber in Wahrheit nur du mit Python2 den Tupel erstellt hast mit den Klammern um die Anweisung herum. In Python2 ist ``print`` ne Anweisung, in Python3 ne Funktion. Wenn du unter Python2 ``print`` als Funktion nutzen willst, dann musst du auch dem Programm mitteilen, dass es neu eine Funktion ist zB mit dem Import der Methode ``print_function``.

    Ob Interrupt oder ``while True`` mit zB ``time.sleep(.1)`` wirst auch du kein Unterschied bzgl. Auslastung der CPU feststellen können.

  • bootsmann: Ich weiß, du meckerst sehr sehr gerne und beharrst ziemlich viel auf PEP... Aber leider liest du nicht richtig die Beiträge, was ich wiederholt sehr schade finde.

    Ich weiß gerade nicht wo das Problem mit print("bla") sein soll - ich kenne den Unterschied, allerdings führe ich meine Scripts gerne auch mal mit python3 aus und schreibe diese deshalb soweit es geht kompatibel..
    Ich weiß aber leider auch nicht auf welchen Thread du dich beziehst, wo Ich an etwas schuld gehabt haben soll :huh:


    Auch die Sache bezüglich Interrupt und sleep hast du leider erneut überlesen.
    Wie auch schon LieberScholl herausgefunden hat ist ein sleep nicht wirklich toll da dann das Script kurzfristig auf keine Eingabe reagiert und blockiert wird - dieser Umstand sollte aber Dir eigentlich auch bekannt sein.....
    Gerade bei einer Menüführung ist es nervig wenn nicht jede Eingabe vom Gerät umgesetzt wird - zufällig immer die wo das Script wegen eines sleeps blockiert wird...
    Welche Alternative, sodass dies nicht zu einem Problem wird, gibts denn sonst?


    Man kann es auch übertreiben sodass Anfänger schon bei der ersten Programmierzeile überfordert sind und keine Lust mehr haben ... Schrittweises herantasten und ggf auch durch try&error etwas lernen, finde ich für Sinnvoller als mit PEP umsich zu werfen.

    PS: Wir hatten auch schon mal die Situation das Du bis zum Selbstversuch falscher Meinung warst und bis zum Selbstversuch auch darauf hartnäckig beharrtest.

  • Zitat

    ich weiß gerade nicht wo das Problem mit print("bla") sein soll - ich kenne den Unterschied

    zB: Interrupt löst ungewünscht aus

    Zitat

    print(bla) " oder " print (bla) ". Steht das auch in deinen PEPs


    Das sind Fakten. Wer den Unterschied zwischen Anweisung und Funktion nicht kennt bzw. nicht verstehen will, der sollte besser die Sprache wechseln
    https://www.python.org/dev/peps/pep-0214/
    https://www.python.org/dev/peps/pep-3105/

    Zum Thema ``signal.pause()`` das habe ich mal in die Runde geworfen anstelle zu deiner ``raw_input()`` Variante. Da ich aber kein C kann, weiss ich auch nicht genau, was das ``signal`` Modul bzw die ``pause()`` Methode macht.

    Spätestens, wenn komplexere Fragen kommen und wir Hobbyisten nicht mehr weiter helfen können und ein wechsel zu den Pros in python-formu.de der Frage Antwort liefert, wird dort als aller erstes darauf aufmerksam gemacht, dass der Code PEP 8 konform umgeschrieben werden muss, bevor jemand einem ernsthaft hilft. Genau so wie in anderen Sprachen. Ich lern zuerst die Vokabeln in Englisch bevor ich dann die Grammatik lerne.

  • Und was ist in deinem verlinkten Beitrag nun falsch?
    Dir ist aber hoffentlich schon bewusst das der von dir verlinkte Beitrag - meiner - einen Fehler des dortigen Themen Erstellers korrigierte?

    Der dortige TE hatte im ersten Beitrag des dortigen Threads
    print (time.asctime(), "Tür geschlossen")
    verwendet aber das gab ne tuple aus.

    ICH war dann, in dem von dir verlinkten Beitrag, daher gegangen und dieses Problem gelöst indem ich das auf
    print("%s -> Tür geschlossen" % time.asctime())
    geändert habe.

    Also bitte erklär mit eigenen Worten, wieso ICH dort ein Zusätzliches Problem erschaffen hatte - was nun dein Hinweiß auf PEP rechtfertigen würde?

  • Zitat

    * Die print (time.asctime() .. Zeilen waren falsch bzw dadurch wurde eine tuple zurück gegeben.

    Python
    >>> print(time.asctime(), "Tür offen")
    ('Tue Jan 20 13:32:32 2015', 'T\x81r offen')
    >>> from __future__ import print_function
    >>> print(time.asctime(), "Tür offen")
    Tue Jan 20 13:33:32 2015 Tür offen
    Zitat

    Der dortige TE hatte im ersten Beitrag des dortigen Threads


    Weil er Python3.x verwendet und du nicht!

    Edit:
    Das sollte hoffentlich inskünftig Klarheit schaffen:
    https://docs.python.org/3.0/library/functions.html#print

  • ...Ich gebs auf....
    Wenn du weiterhin darauf beharren willst das Ich mit Meinem code überhaupt erst Probleme verursache, dann back dir damit'n Eis.

    Mir vergeht jedenfalls erneut die Lust mit dir weiter im selben Thread zu verweilen.

Jetzt mitmachen!

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