Projekt: LCDMenuLib / LCDMenuLib2 ( LCDML ) - Menü mit mehreren Ebenen

faiyth:
Hey,

ich bin gerade von LCDMenuLib auf LCDMenuLib2 umgestiegen. Dabei ist mir aufgefallen, dass in der neuen Lib der Display (i2c 20x4) bei jeder Bewegung des Cursors (Encoder) komplett neu geschrieben wird.

In der alten Lib wurde der Display nur beim Überschreiten des Cursors des aktiven Menüfensters komplett überschrieben, nicht jedoch beim Bewegen des Cursors innerhalb des aktiven Menüausschnittes oder beim Erreichen und Scrollen über die Menügrenzen (bei _LCDML_DISP_cfg_scrollbar = 0). Ansonsten wurde lediglich der Cursor selbst geupdated.
Insgesamt war der Menüfluss damit sehr flüssig.

In der lib2 wird der Display jedoch permanent mit LCDML_lcd_menu_clear überschrieben, was den ganzen Menüablauf sehr unruhig macht. Gibt es die Möglichkeit die alte Funktionsweise auf die neue lib zu übertragen oder wird dieses Menüverhalten für neue Funktionen der lib2 benötigt?

Ich schätze mal die Funktion wird bei der LCDMenuLib in LCDML_DISP_update_content und bei der LCDMenuLib2 in LCDML.DISP_checkMenuUpdate codiert, hab es bis jetzt aber noch nicht geschafft die ältere Funktion zu integrieren.

Grüße
Marvin

Moin, das stimmt.
Es ging auch eine lange Zeit mit der LCDMenuLib2 so. Ich schau mal nach wann es verloren gegangen ist und wie ich es zurück bekommen.

@skorpi080
Mit Plattform IO habe ich die Lib noch nicht übersetzt. Kann daher dazu bisher wenig sagen. Wenn du einen Weg findest nehm ich das als Anleitung auf GitHub mit auf :wink:

@faiyth

Das Problem ist in der nächsten Beta Version behoben. Zum testen kannst du den Master-Branch direkt bei GitHub herunterladen.
GitHub - Jomelo/LCDMenuLib2: Create a tree menu. Use it with different lcd types / console output / ssh console.

Das Ganze ist noch eine Beta Version, da sich noch etwas am Umgang mit dynamischen Untermenüs ändern wird.

@Jomelo
Sehr schön! Kurz mal reingeschaut und soweit sieht es genau aus wie in der ersten lib. Merci.

Habe ne Funktion gebastelt die vielleicht für manche hilfreich ist:

#define LCDV(x,y,z)  (lcd.setCursor(x, y), lcd.print(z))
  #define LCD(x,y,z)  (lcd.setCursor(x, y), SendtoTFT(PSTR(z)))
    void SendtoTFT(PGM_P z) { // A helper to print PROGMEN string to the panel
       while (const char q = pgm_read_byte(z++))
      lcd.print(q);
  }

und um auf das LCD zu schreiben:

LCDV(11,1,Value);
LCD(0,0,"Moin");

Ob das in der Arduino IDE funktioniert hab ich nicht getestet, mit PIO gehts.

momentan ist es mit dem Beispiel LCDML_021_dynUpdatedContent so dass alle dynamischen Menüs jede sekunde blinken.
Wie kann man es lösen dass nur das Menü mit dem Timer aktualisiert wird? Oder noch besser nur der dynamische Content von dem Menü.

Moin,
kurze Frage, welchen Displaytype verwendest du ?
Letztens hatte ich es noch mit einem 20x4 getestet, da war das Verhalten okay.

ist ein 16x4 LCD, ohne I2C.

Kannst du einmal die letzte Beta Version v2.2.7 beta 2 aufspielen ?
Ich kanns im Moment bei mir nicht reproduzieren.

das ist eben mit der Beta 2

Komisch komisch.

Kannst du einmal in der LCDMenuLib.h

Zeile 54 ein kommentieren und in Zeile 58 eine 1 setzen ?

// enable debug strings (remove comments from this line)
#define LCDML_DBG 1

// debug special method groups // enable a flag to control the function call order
#define LCDML_DBG_function_name_LOOP 0
#define LCDML_DBG_function_name_MENU 1

Und dann mal schauen ob beim "zucken" eine Aktion ausgeführt wird. Normalerweise sollte da nichts kommen (erst wenn der Screensaver startet).

Edit:

  • Anstatt Zeile 85 in Zeile 58 :wink:
  • Die Ausgabe erfolgt im seriellen Monitor
23:13:33.863 -> LCDML.MENU_checkDynContent
23:13:34.856 -> LCDML.MENU_checkDynContent
23:13:35.860 -> LCDML.MENU_checkDynContent
23:13:36.880 -> LCDML.MENU_checkDynContent
23:13:37.900 -> LCDML.MENU_checkDynContent
23:13:38.892 -> LCDML.MENU_checkDynContent
23:13:39.898 -> LCDML.MENU_checkDynContent
23:13:40.715 -> LCDML.MENU_goRoot
23:13:40.715 -> LCDML.MENU_resetActiveMenu
23:13:40.748 -> LCDML.MENU_goRoot
23:13:40.782 -> LCDML.MENU_getRootObj
23:13:40.782 -> LCDML.MENU_doScroll
23:13:40.815 -> LCDML.MENU_display
23:13:40.849 -> LCDML.MENU_doScroll
23:13:40.849 -> LCDML.MENU_display
23:13:40.882 -> LCDML.MENU_getCursorPosAbs
23:13:40.915 -> LCDML.MENU_getScroll
23:13:40.915 -> LCDML.MENU_getDisplayedObj
23:13:40.951 -> LCDML.MENU_getChilds
23:13:40.984 -> LCDML.MENU_countChilds
23:13:41.018 -> LCDML.MENU_getChilds
23:13:41.018 -> LCDML.MENU_countChilds
23:13:41.051 -> LCDML.MENU_getCursorPosAbs
23:13:41.086 -> LCDML.MENU_getCursorPos
23:13:41.119 -> LCDML.MENU_getCursorPos
23:13:41.153 -> LCDML.MENU_getCursorPos
23:13:41.153 -> LCDML.MENU_getCursorPos
23:13:41.188 -> LCDML.MENU_checkDynContent
23:13:42.128 -> LCDML.MENU_checkDynContent
23:13:43.009 -> LCDML.MENU_doScroll
23:13:43.043 -> LCDML.MENU_getCursorPosAbs
23:13:43.077 -> LCDML.MENU_getChilds
23:13:43.077 -> LCDML.MENU_countChilds
23:13:43.111 -> LCDML.MENU_getChilds
23:13:43.145 -> LCDML.MENU_countChilds
23:13:43.145 -> LCDML.MENU_getCursorPosAbs
23:13:43.179 -> LCDML.MENU_getCursorPos
23:13:43.214 -> LCDML.MENU_getCursorPos
23:13:43.248 -> LCDML.MENU_getCursorPos
23:13:43.286 -> LCDML.MENU_getCursorPos
23:13:43.286 -> LCDML.MENU_checkDynContent
23:13:43.320 -> LCDML.MENU_doScroll
23:13:43.355 -> LCDML.MENU_getCursorPosAbs
23:13:43.389 -> LCDML.MENU_getChilds
23:13:43.389 -> LCDML.MENU_countChilds
23:13:43.423 -> LCDML.MENU_getChilds
23:13:43.460 -> LCDML.MENU_countChilds
23:13:43.460 -> LCDML.MENU_getCursorPosAbs
23:13:43.493 -> LCDML.MENU_getCursorPos
23:13:43.530 -> LCDML.MENU_getCursorPos
23:13:43.564 -> LCDML.MENU_getCursorPos
23:13:43.564 -> LCDML.MENU_getCursorPos
23:13:43.837 -> LCDML.MENU_doScroll
23:13:43.874 -> LCDML.MENU_getCursorPosAbs
23:13:43.907 -> LCDML.MENU_getChilds
23:13:43.907 -> LCDML.MENU_countChilds
23:13:43.941 -> LCDML.MENU_getChilds
23:13:43.975 -> LCDML.MENU_countChilds
23:13:43.975 -> LCDML.MENU_getCursorPosAbs
23:13:44.012 -> LCDML.MENU_getCursorPos
23:13:44.048 -> LCDML.MENU_getCursorPos
23:13:44.084 -> LCDML.MENU_getCursorPos
23:13:44.084 -> LCDML.MENU_getCursorPos
23:13:44.228 -> LCDML.MENU_checkDynContent
23:13:44.512 -> LCDML.MENU_doScroll
23:13:44.512 -> LCDML.MENU_getCursorPosAbs
23:13:44.547 -> LCDML.MENU_getScroll
23:13:44.583 -> LCDML.MENU_getDisplayedObj
23:13:44.616 -> LCDML.MENU_getChilds
23:13:44.616 -> LCDML.MENU_countChilds
23:13:44.650 -> LCDML.MENU_getChilds
23:13:44.683 -> LCDML.MENU_countChilds
23:13:44.717 -> LCDML.MENU_getCursorPosAbs
23:13:44.717 -> LCDML.MENU_getCursorPos
23:13:44.754 -> LCDML.MENU_getCursorPos
23:13:44.791 -> LCDML.MENU_getCursorPos
23:13:44.825 -> LCDML.MENU_getCursorPos
23:13:45.235 -> LCDML.MENU_checkDynContent
23:13:45.336 -> LCDML.MENU_doScroll
23:13:45.369 -> LCDML.MENU_getCursorPosAbs
23:13:45.403 -> LCDML.MENU_getScroll
23:13:45.403 -> LCDML.MENU_getDisplayedObj
23:13:45.437 -> LCDML.MENU_setDynContent
23:13:45.471 -> LCDML.MENU_getCursorPos
23:13:45.504 -> LCDML.MENU_getChilds
23:13:45.504 -> LCDML.MENU_countChilds
23:13:45.538 -> LCDML.MENU_getChilds
23:13:45.571 -> LCDML.MENU_countChilds
23:13:45.571 -> LCDML.MENU_getCursorPosAbs
23:13:45.605 -> LCDML.MENU_getCursorPos
23:13:45.639 -> LCDML.MENU_getCursorPos
23:13:45.673 -> LCDML.MENU_getCursorPos
23:13:45.706 -> LCDML.MENU_getCursorPos
23:13:46.232 -> LCDML.MENU_checkDynContent
23:13:46.266 -> LCDML.MENU_doScroll
23:13:46.300 -> LCDML.MENU_display
23:13:46.333 -> LCDML.MENU_getCursorPosAbs
23:13:46.333 -> LCDML.MENU_getScroll
23:13:46.369 -> LCDML.MENU_getDisplayedObj
23:13:46.402 -> LCDML.MENU_setDynContent
23:13:46.437 -> LCDML.MENU_getCursorPos
23:13:46.437 -> LCDML.MENU_getChilds
23:13:46.471 -> LCDML.MENU_countChilds
23:13:46.508 -> LCDML.MENU_getChilds
23:13:46.508 -> LCDML.MENU_countChilds
23:13:46.542 -> LCDML.MENU_getCursorPosAbs
23:13:46.575 -> LCDML.MENU_getCursorPos
23:13:46.608 -> LCDML.MENU_getCursorPos
23:13:46.642 -> LCDML.MENU_getCursorPos
23:13:46.642 -> LCDML.MENU_getCursorPos
23:13:47.249 -> LCDML.MENU_checkDynContent
23:13:47.283 -> LCDML.MENU_doScroll
23:13:47.316 -> LCDML.MENU_display
23:13:47.316 -> LCDML.MENU_getCursorPosAbs
23:13:47.350 -> LCDML.MENU_getScroll
23:13:47.384 -> LCDML.MENU_getDisplayedObj
23:13:47.418 -> LCDML.MENU_setDynContent
23:13:47.418 -> LCDML.MENU_getCursorPos
23:13:47.452 -> LCDML.MENU_getChilds
23:13:47.486 -> LCDML.MENU_countChilds
23:13:47.519 -> LCDML.MENU_getChilds
23:13:47.519 -> LCDML.MENU_countChilds
23:13:47.553 -> LCDML.MENU_getCursorPosAbs
23:13:47.587 -> LCDML.MENU_getCursorPos
23:13:47.621 -> LCDML.MENU_getCursorPos
23:13:47.621 -> LCDML.MENU_getCursorPos
23:13:47.655 -> LCDML.MENU_getCursorPos
23:13:48.256 -> LCDML.MENU_checkDynContent
23:13:48.291 -> LCDML.MENU_doScroll
23:13:48.327 -> LCDML.MENU_display
23:13:48.327 -> LCDML.MENU_getCursorPosAbs
23:13:48.364 -> LCDML.MENU_getScroll
23:13:48.398 -> LCDML.MENU_getDisplayedObj
23:13:48.398 -> LCDML.MENU_setDynContent
23:13:48.431 -> LCDML.MENU_getCursorPos
23:13:48.468 -> LCDML.MENU_getChilds
23:13:48.501 -> LCDML.MENU_countChilds
23:13:48.501 -> LCDML.MENU_getChilds
23:13:48.535 -> LCDML.MENU_countChilds
23:13:48.568 -> LCDML.MENU_getCursorPosAbs
23:13:48.602 -> LCDML.MENU_getCursorPos
23:13:48.602 -> LCDML.MENU_getCursorPos
23:13:48.638 -> LCDML.MENU_getCursorPos
23:13:48.672 -> LCDML.MENU_getCursorPos
23:13:49.253 -> LCDML.MENU_checkDynContent
23:13:49.290 -> LCDML.MENU_doScroll
23:13:49.326 -> LCDML.MENU_display
23:13:49.326 -> LCDML.MENU_getCursorPosAbs
23:13:49.360 -> LCDML.MENU_getScroll
23:13:49.393 -> LCDML.MENU_getDisplayedObj
23:13:49.430 -> LCDML.MENU_setDynContent
23:13:49.430 -> LCDML.MENU_getCursorPos
23:13:49.464 -> LCDML.MENU_getChilds
23:13:49.498 -> LCDML.MENU_countChilds
23:13:49.531 -> LCDML.MENU_getChilds
23:13:49.531 -> LCDML.MENU_countChilds
23:13:49.565 -> LCDML.MENU_getCursorPosAbs
23:13:49.598 -> LCDML.MENU_getCursorPos
23:13:49.632 -> LCDML.MENU_getCursorPos
23:13:49.632 -> LCDML.MENU_getCursorPos
23:13:49.665 -> LCDML.MENU_getCursorPos
23:13:50.256 -> LCDML.MENU_checkDynContent
23:13:50.291 -> LCDML.MENU_doScroll
23:13:50.327 -> LCDML.MENU_display
23:13:50.327 -> LCDML.MENU_getCursorPosAbs
23:13:50.361 -> LCDML.MENU_getScroll
23:13:50.396 -> LCDML.MENU_getDisplayedObj
23:13:50.432 -> LCDML.MENU_setDynContent
23:13:50.465 -> LCDML.MENU_getCursorPos
23:13:50.465 -> LCDML.MENU_getChilds
23:13:50.503 -> LCDML.MENU_countChilds
23:13:50.536 -> LCDML.MENU_getChilds
23:13:50.536 -> LCDML.MENU_countChilds
23:13:50.572 -> LCDML.MENU_getCursorPosAbs
23:13:50.606 -> LCDML.MENU_getCursorPos
23:13:50.639 -> LCDML.MENU_getCursorPos
23:13:50.639 -> LCDML.MENU_getCursorPos
23:13:50.673 -> LCDML.MENU_getCursorPos
23:13:51.291 -> LCDML.MENU_checkDynContent
23:13:51.291 -> LCDML.MENU_doScroll
23:13:51.327 -> LCDML.MENU_display
23:13:51.365 -> LCDML.MENU_getCursorPosAbs
23:13:51.365 -> LCDML.MENU_getScroll
23:13:51.399 -> LCDML.MENU_getDisplayedObj
23:13:51.433 -> LCDML.MENU_setDynContent
23:13:51.466 -> LCDML.MENU_getCursorPos
23:13:51.499 -> LCDML.MENU_getChilds
23:13:51.499 -> LCDML.MENU_countChilds
23:13:51.534 -> LCDML.MENU_getChilds
23:13:51.568 -> LCDML.MENU_countChilds

Okay,
das "MENU_checkDynContent" sollte da nicht stehen.
Ich schau mal wo es her kommen kann.

das kommt dann wenn der Screensaver läuft

Hatte beim testen gerade das falsche Beispiel offen, daher habe ich es nicht gesehen.
...

Da ist ein Bug im Beispiel. Ich schau mal eben wie es richtig aussehen müsste.

Ich werde das Problem in den nächsten Tagen beheben. Einen kleinen Teil in der Lib muss ich anpassen.

Das Beispiel aktualisiert das Menü, sobald ein dyn Element gefunden wurde. Nun muss dieses dyn Element aber nicht das Element sein, welches permanent aktualisiert werden soll. Bei einer Aktualisierung wird aktuell das gesamte Menu gelöscht und neu geschrieben. Durch den "Clear" kommt dieses blink Verhalten.

Nun ist es recht einfach den Bug auf einem Zeilen Display zu beheben. Bei einem grafischen Display z.b. einem welches über die U8GLib angesprochen wird, ist es etwas komplizierter, da hier meistens eine Page neu geschrieben wird.

Lösungsansatz / Herausforderung:

  • verschiedene Displaytypen berücksichtigen
  • Trigger auf spezielle dynamische Element erlauben, damit diese kontinuierlich aktualisiert werden. (Der Polling Ansatz ist hier nicht der beste)
    => Das Beispiel bleibt nicht so bestehen wie es aktuell ist.

Alles klar, vielen dank für die Zeit die du hier reinsteckst!

Moin,
die Lib ist zu einem Hobby geworden :wink:

Ich habe mir das Problem nochmal im Detail angeschaut. Im Moment gibt es keine andere Lösung zu der, die im Beispiel abgebildet ist. Sobald ein Dyn-Element sichtbar ist (sich im Angezeigten Fenster befindet) wird das Menü neuaufgebaut, weil es könnte sich ja um das kontinuierlich verändernde Element handeln.

Eine Unterscheidung zwischen einem "statisch" angezeigten Dyn-Element (nur Änderung durch User Aktion) und einem "zeitlich angepassten" Element wird von der Menüstruktur nicht unterschieden. Eine neue Variablen in einem Element anzulegen, die diese Eigenschaft verwalten würden den Speicherverbraucht auch für die 95% der User, die dieses Feature nicht nutzen erhöhen.

Sprich, um dies zu umgehen müsste ich ein Task System im Hintergrund laufen lassen, welches dann aktiviert wird, wenn genau die vom Programmierer gewünschte Funktion aktualisiert werden sollte. Könnte man so machen, ist aber für diesen einen Anwendungsfall recht viel Aufwand.

Wenn mir ein cleverer Ansatz einfällt werde ich es anpassen. Ich versuche bei allen Änderungen immer abzuwägen, dass Speichernutzung vs Anzahl der Lib User die es gebrauchen könnten in einem fairen Verhältnis bleibt. Anpassungen die sich über die bestehenden "Register / Flags" noch abbilden lassen sind immer möglich.

So,
irgendwie konnte ich es heute nicht sein lassen.

Auf Github ist nun Version v2.2.7-beta3

In dieser Version ist das Beispiel angepasst und läuft nun ohne irgend ein zusätzliches "Zucken" auf dem Display.

jawohl, sieht schon besser aus.
Jetzt zuckt nur der Timer.
Vielen Dank!

Edit//
dynValue: 100 kann nicht geändert werden
beim drücken auf Enter gehts nicht in das Menü um den Wert zu ändern.

Jomelo:
So,
irgendwie konnte ich es heute nicht sein lassen.

Auf Github ist nun Version v2.2.7-beta3

In dieser Version ist das Beispiel angepasst und läuft nun ohne irgend ein zusätzliches "Zucken" auf dem Display.

hast du noch den Ehrgeiz gehabt und mein Bugreport angeschaut und gefixt?