Menü Struktur über 1602 LCD anzeigen/steuern

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    gleich vorne weg: Ich bin nicht nur ein Foren Neuling, sondern auch noch recht unerfahren in Sachen Programmierung und Python, verzeiht daher eventuelle Anfänger Fehler/Fragen :)


    Ich habe ein Projekt vor Augen für eine Alarmanlage welche unter anderem durch einen RFID Chip aktiviert/Deaktiviert , über Druckknöpfe bzw. Drehgeber gesteuert und die Daten auf einem 16x02 LCD ausgeben soll....

    Mein Grundgedanke war hierfür ein Menü zu erstellen, worüber dann weitere Prozesse gestartet/beendet werden sollen.(Prozess für Überwachung, Prozess um IP Adresse anzuzeigen usw.) Ich habe es bereits geschafft ein einfaches Menü zu erstellen, jedoch ohne Untermenüs.

    Nun hab ich folgende Herausforderungen:

    - Ich möchte durch auswählen der einzelnen Progammpunkte weitere Prozesse starten, zb zu Anfang einfach mal die IP Adresse anzeigen, beim anwählen des entsprechenden Menüpunktes.
    Das Programm zum Anzeigen der IP funktioniert ebenfalls bereits. Aber wie kann ich aus dem Hauptprogramm ein "Unterprogramm" starten und dieses durch erneutes Drücken der Eingabe Taste wieder beenden, sodass wieder das Hauptmenü erscheint? Ich habe schon öfter von Modulen und subprocess gelesen, welchen man mit call.subprocess ([...]) aufrufen kann.
    Aber wie ich dann wieder zurück komme, habe ich nicht gefunden.

    - Leider habe ich im Forum nur Themen bezüglich Menüs mit grafischer Oberfläche zb über tkinter gefunden, jedoch nichts um eines für ein Display zu erstellen. Habe ich mich bei der Suche vielleicht zu doof angestellt ?! :blush: Oder gibt es hierzu noch keine Beiträge?

    Vielen Dank für eure Hilfe.
    Ich hoffe die Infos reichen erstmal, ich wollte nicht gleich so weit ausholen :)

    Lieben Gruß

  • +++ edit +++

    Ich habe nun mit subprocess.call([Dateipfad/Dateiname.py]) unter dem entsprechenden Menüpunkt das Skript mit der IP Adresse im Display gestartet bekommen.
    Im subprocess selbst habe ich noch die Befehle

    lcd.clear()
    sys.exit()

    eingefügt, welche per Knopfdruck ausgeführt werden.
    Wie schaffe ich es nun da der Prozess beendet ist, das "Hauptprogramm" wieder auf den letzten Menüpunkt zu setzen bzw. von vorn starten zu lassen?
    Im Moment zeigt er ja nur ein leeres Display (Logisch da lcd.clear...)

  • Ein anderes Python Script durch ein Python Script über subprocess auszuführen ist... ähm... mies :fies:

    Erstell dir eine Funktion, importiere das andere Script und führe dann die Funktion an gewünschter stelle aus. Dessen Rückgabe (return) lässt du dann anzeigen.

    Aber wie auch schon im anderen Thread: Ohne deine Scripts zu kennen kann man nur mit den Schultern zucken.

  • Hallo,

    ich habe das Ganze bei meiner BMA auch gemacht, um mittels zwei Tastern durch das Menü navigieren zu können (20x4 Display).
    Allerdings habe ich immer einen Wert in einer Variable gespeichert und dann die Ausgabe auf dem Display je nach Wert der Variable gemacht. Wenn ich dann im Menü auf den Punkt "Zurück" navigiert habe, ist er wieder in das Hauptmenü gesprungen. War alles ein größeres Python-Script

    Gruß
    Matze


  • Aber wie auch schon im anderen Thread: Ohne deine Scripts zu kennen kann man nur mit den Schultern zucken.

    Jap das war mein erster Post, da wusste ich noch nicht wie das geht :lol:
    Hier ist der Code für das Menü:

    [code=php]
    #!/usr/bin/python3
    from time import sleep, strftime
    from datetime import datetime
    from Adafruit_CharLCD import Adafruit_CharLCD
    import RPi.GPIO as GPIO
    import time, sys
    import subprocess

    Btndown = 38 # GPIO Inputs
    Btnup = 40
    Btnenter = 15

    lcd = Adafruit_CharLCD()
    lcd.begin(16,2)
    lcd.clear()
    entries = []
    char = ">"
    numItems = 6 # Anzahl der Menuepunkte
    cursor = 0
    displaying = True

    def init():

    GPIO.setwarnings(True)
    GPIO.setmode(GPIO.BOARD) # Verwendung der PIN Nummern -> NICHT GPIO-Nummern

    GPIO.setup(Btndown,GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # pull_up_down nur ohne
    GPIO.setup(Btnup,GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Widerstaende auf dem
    GPIO.setup(Btnenter,GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Board

    GPIO.add_event_detect(Btnup, GPIO.FALLING, bouncetime=1000) # Entprellzeit = 1000 Msek.
    GPIO.add_event_callback(Btnup, Btnup_on)
    GPIO.add_event_detect(Btndown, GPIO.FALLING, bouncetime=1000)
    GPIO.add_event_callback(Btndown, Btndown_on)
    GPIO.add_event_detect(Btnenter, GPIO.FALLING, bouncetime=1000)
    GPIO.add_event_callback(Btnenter, Btnenter_on)

    return


    # *********************** Funktionen ********************************************


    class LCDMenuEntry:
    def __init__(self, inName):
    self.name = inName
    location = "hidden"


    def setEntry(num, entry):
    entries[num].name = entry


    def updateDisplay(direction):
    global cursor
    if direction == "down" and cursor != (numItems - 1):
    if entries[cursor].location == "top":
    cursor += 1
    lcd.clear()
    lcd.message("Hauptmenue" +
    "\n" +char + " " + entries[cursor].name)
    elif entries[cursor].location == "bottom":
    entries[cursor - 1].location = "hidden"
    entries[cursor].location = "top"
    cursor += 1
    entries[cursor].location = "bottom"
    lcd.clear()
    lcd.message("Hauptmenue" +
    "\n" +char + " " + entries[cursor].name)

    elif direction == "up" and cursor != 0:
    if entries[cursor].location == "top":
    entries[cursor + 1].location = "hidden"
    entries[cursor].location = "bottom"
    cursor -= 1
    entries[cursor].location = "top"
    lcd.clear()
    lcd.message("Hauptmenue" +
    "\n" +char + " " + entries[cursor].name)

    elif entries[cursor].location == "bottom":
    cursor -= 1
    lcd.clear()
    lcd.message("Hauptmenue" +
    "\n" +char + " " + entries[cursor].name)


    def pickEntry(num):
    print ('picked:', num, "(" + entries[num].name + ")")
    if num == 0:
    pass

    elif num == 1:
    pass

    elif num == 2:
    lcd.clear()
    lcd.message("Einstellungen")

    elif num == 3:
    lcd.clear()
    subprocess.call(['/home/pi/Desktop/Alarmsystem/CasIP.py'])

    elif num == 4:
    pass

    elif num == 5:
    lcd.clear()
    lcd.message("Ausgewaehlt")


    def createMenu(numEntries):
    for x in range(0, numEntries):
    entries.append(LCDMenuEntry("Item " + str(x)))
    entries[0].location = "top"
    entries[1].location = "bottom"


    def Btndown_on( pin :(
    Switch_A = GPIO.input(Btndown)

    if (Switch_A == 0) :
    print ("Down Button gedrueckt")
    updateDisplay("down")
    sleep(1)

    def Btnenter_on( pin :(
    Switch_C = GPIO.input(Btnenter)

    if (Switch_C == 0) :
    print ("Enter Button gedrueckt")
    pickEntry(cursor)
    sleep(1)

    # *********************** Bezeichnung der Menuepunkte *************************************


    createMenu(numItems)

    setEntry(0, " ")
    setEntry(1, "System aktiv.")
    setEntry(2, "Einstellungen")
    setEntry(3, "IP anzeigen")
    setEntry(4, "Herunterfahren")
    setEntry(5, "Zurueck")


    lcd.message(datetime.now().strftime('%b %d %H:%M:%S') +
    "\n"+" > > Hauptmenue")
    sleep(1)


    try:
    init()
    while True :
    sleep(5)

    except KeyboardInterrupt:
    GPIO.cleanup()
    lcd.clear()
    sys.exit()

    if __name__ == '__main__':
    main()

    [/php]


    Das funktioniert auch alles erstmal soweit, bis auf ein paar Kleinigkeiten wie zB. wird die Uhrzeit auf dem Startbildschirm nicht aktualisiert usw aber das ist erstmal Nebensache.
    Mein Ziel wäre es halt zB beim Anwählen der einzelnen Programmpunkte, einzelne "Programme" ausführen zu können und durch erneutes drücken der Enter Taste wieder zurück ins Menü zu kommen. Das ganze soll aus dem Grund eigentlich mit nur 3 Knöpfen gesteuert werden, da ich die Buttons später durch einen Rotary Encoder ersetzen möchte.
    @ meigrafd : Zb soll beim "System aktiv" das Programm mit dem RFID Reader ausgeführt werden und wenn dann ein bekannter RFID Chip erkannt wird, soll dann wiederum die Alarmanlage scharf gestellt werden. Daher dachte ich an subprocess um das Mainscript möglichst kurz zu halten...


    @ Matze
    Sprich Du hast ein Mainscript geschrieben mit dem gesammten Menü und der dazugehörigen Funktionen in einer Datei?
    Ich habe oben in meinem Script ja auch den Menüpunkten Zahlen von 0-5 zugewiesen. Aber wie hast du dann den "zurück" Befehl realisiert?
    Ich mein um zu sagen : Wenn Entry 4 gewählt dann shutdown Zb okay, aber wie sieht es aus, wenn man eine Funktion aufruft, und dann wieder per Knopfdruck raus möchte, wie hast Du das gelöst?

    Gruß,
    Mamba

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!