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

Projekt: LCDMenuLib und LCDMenuLib2 (LCDML)


Aktuellste Version
LCDMenuLib2 Download

Alte Version
LCDMenuLib Download (keine neuen Updates mehr)

Einfache Installation über den Arduino Bibliotheksmanager möglich, einfach nach "LCDMenuLib" oder "LCDMenuLib2" suchen.

[Falls ihr Fragen habt, dass lest bitte nicht alle Seiten, nur die letzten 2 bis 5 Seiten sind interessant.]

Die Nachfolgende Beschreibung bezieht sich auf die LCDMenuLib2.

Beschreibung:
Mit der LCDMenuLib2 kann ein Menü mit mehreren Ebenen erstellt werden. Es können theoretisch maximal 254 Menüelemente angelegt werden, praktisch wird dies durch die Resourcen des Kontrollers begrenzt.
Die Menüelemente können in unterschiedlichen Ebenen angelegt werden, sodass sich grafisch eine Baumstruktur ergibt. Sprich es gibt einen Stamm, von dem verschiedene Äste (Sub Menüs) abgehen. Der Stamm des Menüs wird beim Anlegen der Lib generiert, alle Äste sind konfigurierbar.
Jedem Menüelement kann eine "Funktion", eine "Bedingung" zum Anzeigen, ein "Parameter" und spezielle Einstellungen zugewiesen werden. Diese Zuweisung werden dann je nach Einstellung abgearbeitet. Eine Funktion besteht aus einem Setup-Teil in dem Variablen initialisiert werden können. Das Setup wird beim schließen der Funktion zurückgesetzt und beim Öffnen erneut ausgeführt. Der Loop-Teil beinhaltet dann Ausgaben, die sich ständig ändern können. Der Close-Teil der Funktion wird immer dann aufgerufen, wenn die Funktion verlassen wird.
Der Inhalt einer Menüfunktion wird nur dann aktualisiert, wenn ein Aktion ausgeführt wird. Eine Aktion kann das Drucken eines Buttons sein oder aber ein Trigger der gesetzt wird. Trigger können auf eine feste Zeit konfiguriert werden, so dass die Menüfunktion in einem Intervall von XX Millisekunden aktualisiert wird. In der Menüfunktion sollte wenn möglich nur der Inhalt für das Display stehen oder die Verarbeitung der Buttons stattfinden. Es sollte hier niemals die „delay(x)“ Funktion verwendet werden.
Alle funktionell Abhängigen Funktion sind in Tabs thematisch getrennt.
Das Menü bietet möglichkeit einen Bildschirmschoner zu aktivieren. Dieser besteht aus einem Menüelement welches meistens versteckt angelegt wird.
Desweiteren kann nun in der LCDMenuLib2 eine Rollover funktion aktiviert werden. Hierbei springt der Kursor vom Ende zum Anfang oder umgekehrt insofern man versucht nach oben oder unten zu scrollen.

Wichtiges vorweg:

  • Falls ihr in eurem Programm die „delay(x)“ Funktion verwenden solltet, beantworte ich keine Fragen dazu. (Schaut euch bitte das „Blink without delay“ Bespiel oder die Beispiel die bei der Lib dabei sind an.
  • Stellt eure Fragen bitte im Forum als Beitrag allen zur Verfügung, dann können auch alle von einer Lösung profitieren.
  • Das Backend System aus der "LCDMenuLib" wurde entfernt, da es so ganz neue Möglichkeiten gibt externe Libs einzusetzen. Hier bietet sich z.B. folgende Lib an: GitHub - arkhipenko/TaskScheduler: Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers

1.1 Features

  • Beliebige Ausgabe auf Displaytypen -> Konsole, LCD, GLCD, OLED, ....
  • Einfaches Einbinden von neuen Displaytypen
  • Die Schnittstelle kann leicht für jeden Displaytype angepasst werden -> 4Bit, I2C, SPI, ShiftReg, ...
  • Beispiele für verschiedene Libs aus der Arduinowelt: LiquidCrystal, LiquidCrystal_I2C, u8glib, u8glib2
  • 254 Menüpunkte maximal (meistens begrenzt der Ram die Anzahl)
  • 254 Menüpunkte pro Ebene möglich / keine Begrenzungen bei der Ebenen Anzahl (konfigurierbar)
  • Trennung von Struktur- und Funktionsebene durch mehrere Tabs
  • Leitfaden für den sauberen Programmaufbau / saubere Strukturierung
  • Ansteuerung über mindestens 3 Taster / Funktionen (up, down, enter), Encoder, Keypad, IR, ...
  • maximal 6 Taster werden unterstützt. (up, down, enter, quit/back, left, right)
  • Bildschirmschoner aktivierbar, dieser wird nach X Sekunden und/oder zu Beginn angezeigt
  • Scrollbalken aktivierbar
  • Scrollbalken wird nur angezeigt, wenn mehr Menüelemente wie Zeilen im Display vorhanden sind
  • Cursor Position wird gespeichert, nachdem eine Ebene zurückgegangen wird
  • Möglichkeit direkt zwischen Menüelementen hin und her zu springen
  • Möglichkeit die Menüelement ID abzufragen
  • jegliche Displaytypen und Libs können verwendet werden.
  • Menüpunktbezeichnungen werden im Flash Speicher abgelegt
  • Funktioniert mit Arduino / ESP8266 / ESP32
  • in der neusten Version werden auch grafische Displays unterstützt

1.2 Bilder

Bilder ohne Display mit dem Menü in der Konsole

Bilder grafisches Display mit u8glib

Interessante Beiträge:
10 Jahre LCDMenuLib - Beitrag

1 Like

Projekt: LCDMenuLib (LCDML) – Kapitel 2: Displayfunktionen
2.1 Inbetriebnahme des ersten Beispiels
Das Beispiel mit der Bezeichnung „LCDML_1_easy_01_first_test“ soll zeigen wie ein einfaches Menü aussehen kann.
Vorweg kurz etwas zum Quellcode:
Alle Makros / Funktion die mit LCDML_DISP_... beginnen beziehen sich auf das Menü so wie die Funktionen die darin aufgerufen werden (Displaysystem). Alle weiteren Makros / Funktionen die mit LCDML_BACK_... anfangen beziehen sich auf Abläufe die im Hintergrundlaufen (Backendsystem)
Im Beispiel werden zuerst die benötigten Libraries eingebunden. Die Libs die benötigten werden hängen von der verwendeten Schnittstelle ab. Z.B. wird bei I2C noch die Wire.h benötigt, dazu später aber mehr.

// include libs
#include <LiquidCrystal.h>
#include <LCDMenuLib.h>

Nach den Libraries werden die Konstanten für das Menü angelegt. Beim oben genannten Beispiel sollte hier alles so belassen werden wie es ist. Später kann hier der Initscreen (Standby Screen) aktiviert werden oder die Buttonpresstime (für Buttons) eingestellt werden. Mit der Button Press Time werden die Buttons entprellt.
Nach der Lib Konfiguration werden die Einstellungen vom Display gesetzt. Es müssen die Reihen (row) und Spalten (cols) angegeben werden und die PINs an denen das Display angeschlossen ist. Falls ein Display verwendet wird, beidem die im Beispiel vorhandenen Konstanten nicht passen bitte in Kapitel 2.4 „Schnittstellen mit externen Libs“ weiterlesen.
Das Beispiel „LCDML_1_easy_01_first_test“ lässt sich der Einfachheit nur über die serielle Schnittstelle bedienen.
Folgende Tasten haben eine Bedeutung im Menü:
e = Enter (In eine Ebene wechseln)
q = Quit (Geht aus einer Ebene heraus)
u = Up (Navigation nach oben im Menü)
d = Down (Navigation nach unten im Menü)
Die folgenden Tasten können aber auch in Funktionen verwendet werden:
e = Enter (Benutzerdefiniert z.B. etwas setzen oder bestätigen)
q = Quit (verlässt die Funktion und kehrt ins Menü zurück)
u = Up (Benutzerdefiniert)
d = Down (Benutzerdefiniert)
l = Left (Benutzerdefiniert)
r = Right (Benutzerdefiniert)
Um das Menü mit Buttons oder Encodern steuern zu können ist das Kapitel 2.3 „Steuerungsmöglichkeiten“ empfehlenswert.
Als nächstes wird im Beispiel das Menü angelegt. _LCDML_DISP_cnt bekommt die ID des letzten Menüelementes, sprich dieser Wert wird gesetzt wenn man weiß wie das Menü aussieht. Wird dieser Wert zu groß gewählt entstehen Fehlermeldungen. Wenn der Wert zu klein ist wird nicht das volle Menü angezeigt.

#define _LCDML_DISP_cnt    11 //ID des letzten Menü elementes

Danach wird mit der letzten Menü Element ID viele Variablen angelegt. Da dies nicht von Hand gemacht werden muss gibt es das Makro „LCDML_DISP_init(_LCDML_DISP_cnt);. Anschließend
wird die Menüstruktur aufgebaut. Für die ersten drei Elemente sieht das wie folgt aus:

// LCDMenuLib_element(id, group, prev_layer_element, new_element_num, lang_char_array, callback_function)
LCDML_DISP_add      (0  , _LCDML_G1  , LCDML_root        , 1  , "Information"        , LCDML_FUNC_information);
LCDML_DISP_add      (1  , _LCDML_G1  , LCDML_root        , 2  , "Time info"          , LCDML_FUNC_timer_info);
LCDML_DISP_add      (2  , _LCDML_G1  , LCDML_root        , 3  , "Settings"           , LCDML_FUNC);

Der erste Wert im Makro ist die ID. Diese musst fortlaufend mit Null beginnend hochgezählt werden.
Als zweiter Wert folgt die Gruppe. Die Menüelemtne können in Gruppen eingeteilt werden. Die Gruppen können dann ausgeblendet werden z.B. um Funktion erst anzuzeigen nach dem eine Identifikation erfolgt ist oder für Funktionserweiterungen die erst später freigegeben werden sollen. In diesem Beispiel haben alle Element im Menü die Gleiche Gruppe.
Als drittes wird die Ebene in der sich das Element befinden soll angegeben. Mit LCDML_root ist die Hauptebene gemeint. Mit dem vierten Parameter wird die Reihenfolge in der zuvor angegeben Ebene festgelegt. Eine neue Untereben kann nur angelegt werden wenn zuvor das darüber liegende Element angelegt wurde. Z.B.

LCDML_DISP_add      (3  , _LCDML_G1  , LCDML_root_3      , 1  , "Change value"       , LCDML_FUNC);

Der Name der Ebene in der das „sub“ Element angelegt wird setzt sich aus der Hauptebene und der Position des Elementes für das Ein Sub Element erzeugt werden soll zusammen.
Als fünften Parameter wird der Name der im Display für das Menüelement angezeigt wird angegeben. Hierbei muss beachtet werden, dass der Name zwei Zeichen kürzer sein muss als die Spalte im Display breit ist. Die Länge ist so definiert, dass vor dem Menüelement der Cursor gesetzt werden kann und hinter dem Namen der Scrollbalken Platz finden kann. Also bei einem 16x2 Display maximal 14 Zeichen und bei einem 20x4 maximal 18 Zeichen.
Der letzte Parameter gibt die Callback Funktion an. Dies ist die Funktion die ausgeführt wird, sobald das Menüelement Aufgerufen wird. Es macht keinen Sinn auf Menüs, die noch SubEbenen besitzen eine Funktion zu legen, diese würde nie ausgeführt werden. Für die Elemente, bei denen keine Funktion aufgerufen werden soll muss die Dummy-Funktion „LCDML_FUNC“ eingetragen werden. Wenn ein Funktionsname im Menü eingetragen ist muss dazu auch eine Funktion existieren die aufgerufen werden kann, ansonsten entstehen Fehlermeldungen beim übersetzen
Nach dem Anlegen der Menüelemente wird mit dem Makro „LCDML_DISP_createMenu(_LCDML_DISP_cnt);“ das Menü angelegt.

Als nächstes folgt die Definition des Backend. An dieser Stelle will ich hier noch nicht drauf eingehen. Dieser Teil sollte erstmal unbeachtet bleiben. Dazu mehr im Kapitel 3 „Backendsystem„.
Im Setup wird die für dieses Beispiele benötigte Serielle Schnittstelle initialisiert. Darauf folgend wird die Gruppe 1, in der sich alle oben angelegten Menüelemente befinden aktiviert, sodass diese sichtbar ist. Danach werden die oben automatisch angelegten Variablen mit dem Makro „LCDML_setup(_LCDML_BACK_cnt);“ anhand der zuvor eingestellten Menükonfiguration initialisiert.
In der Loop Schleife befindet sich nur die LCDML_run(_LCDML_priority); Funktion, diese kümmert sich um den Aufruf der Funktion die im Backendsystem laufen. Dazu auch später mehr.
Das Beispiel beinhaltet drei Menüelemnte bei denen Funktionen hinterlegt sind:
LCDML_FUNC_information
Zeigt einfach nur eine Information an
LCDML_FUNC_timer_info
lässt einen Timer runter zählen
LCDML_FUNC_p2
Hier muss etwas mit Button gemacht werden

Mehr Informationen könnt ihr hier finden:
Overview: Jomelo/LCDMenuLib2 (github.com)

Code Reference · Jomelo/LCDMenuLib2 Wiki (github.com)

Releases · Jomelo/LCDMenuLib2 (github.com)

läuft mit ein paar Veränderungen :smiley: DANKE !!!!

// Einstellungen für das verwendete LCD (20x4)
#define _LCD_cols 16
#define _LCD_rows 2

// Pin Belegung für das LCD
#define _LCD_PIN_rs 12
#define _LCD_PIN_e 11
#define _LCD_PIN_dat4 5
#define _LCD_PIN_dat5 4
#define _LCD_PIN_dat6 3
#define _LCD_PIN_dat7 2

// Der Button mode gibt an wie die Tastatur (Tastenfeld) angeschlossen werden sollen
// 0 = Keine Buttons verwenden (Steuerung über Serialmonitor)
// (w = up, a = left, s = down, d = right, q = back, e = enter)
//

// Der Button mode gibt an wie die Tastatur (Tastenfeld) angeschlossen werden sollen
// 0 = Keine Buttons verwenden (Steuerung über Serialmonitor)
// (w = up, a = left, s = down, d = right, q = back, e = enter)
//
// 1 = Einen Eingang und Auswertung über Bereiche
// 2 = Für jeden Button einen Eingang
#define _BUTTON_MODE 0

Hallo Jomelo,
allerherzlichsten Dank für die Projektvorstellung.

Gruss
Kurti

Hallo,

"WProgram.h" muss durch "arduino.h" ersetzt werden. Habe lange gesucht bevor ich als Neuling herausgefunden habe.
Gruss
helix1

Update:

  • Ich habe die Library auch für die Arduino Version 1.0.1 brauchbar gemacht.

Super, Jomelo.

Eine Frage zum Verständnis:
Du erzeugst Objekte vom Typ Menu, arbeitest aber meist mit den char* auf deren Texte. Hat das einen Grund ?
Falls der gleiche Text in verschiedenen Menu Objekten (z.B. auf verschiedenen Ebenen oder in verschiedenen Zweigen) auftaucht, bist du sicher, dass die zwei #define Anweisungen zwei unterschiedliche char* adressieren?

#define _LANG_MENU_setting1_2                     "Einstellungen"
#define _LANG_MENU_setting3_2                     "Einstellungen"

Menu Item1_2    (_LANG_MENU_setting1_2);
Menu Item3_2    (_LANG_MENU_setting3_2);

char * tmp =  _LANG_MENU_setting1_2;  // z.B.

if (tmp  == _LANG_MENU_setting3_2 ) {
 // eine sicher nicht gewollte eventuelle Optimierung des Compilers
 // wenn man hier landet
}

Für Uno (oder noch kleinere Arduinos), oder wenn der Arduino neben der Menu System Bedienung nebenbei noch möglichst viele dynamische Daten zwischenspeichern soll und/oder einen ganzen SD card block im RAM halten soll, oder ...,

... wäre es noch superer, wenn die konstanten Menü-Texte aus dem Flash genommen würden ...

Du erzeugst Objekte vom Typ Menu, arbeitest aber meist mit den char* auf deren Texte. Hat das einen Grund ?
Ich habe das damals so gewählt, da ich dann die einzelnen Menü Ebenen mir über die Serielle Schnittstelle auch direkt ausgeben lassen konnte.
Außerdem war es zum damaligen Zeitpunkt leichter texte miteinander zu vergleichen (vom Verständnis her).

Falls der gleiche Text in verschiedenen Menu Objekten (z.B. auf verschiedenen Ebenen oder in verschiedenen Zweigen) auftaucht, bist du sicher, dass die zwei #define Anweisungen zwei unterschiedliche char* adressieren?
So wie in deinem Beispiel funktioniert der Aufruf nicht. Ich nutze dazu einen array in dem jeweils der Name der nächst höheren Ebene steht. "funcname"

Beispiel:

#define _LANG_MENU_setting1_2                     "Einstellungen"
#define _LANG_MENU_setting3_2                     "Einstellungen"

Menu Item1_2    (_LANG_MENU_setting1_2);
Menu Item3_2    (_LANG_MENU_setting3_2);

char * tmp =  _LANG_MENU_setting1_2;  // z.B.

void BACK_SelectMenuFunction(void)
  {
    char *tmp;
      // Selbsthaltung der ausführenden Funktion falls gesetzt
      // HIER NICHTS ÄNDERN
      if(func_loop_name != NULL) {
        tmp = func_loop_name;
      } else {
        tmp = lcd_display.curfuncname;
      }          
        
      // AB HIER KÖNNEN ÄNDERUNGEN GEMACHT WERDEN
      
      //Nur Menupunkte die Ausgeführt werden können sollten hier drin stehen
      if(tmp == _LANG_MENU_setting1_2 && lcd_display.funcname[1] == "Ebene 1") 
      {
               
      }
      else if(tmp == _LANG_MENU_setting3_2 && lcd_display.funcname[2] == "Ebene 2") 
      {
               
      }

Die Bezeichnungen der Ebene stimmen zwar in dem Beispiel nicht, aber das Prinzip sollte deutlich werden.
Und zur Adressverwaltung vermute ich, dass die Inhalte nicht an der gleichen Stelle liegen, da sie auch in unterschiedlichen Objekten angelegt werden.

Die Erweiterung mit dem Flashspeicher ist eine gute Idee. Damit werde ich mich mal beschäftigen. Für mein damaliges Projekt reichte der Ram aus.

Hallo Jomelo,
erstamals Vielen Dank für deine tolle Arbeit :slight_smile:
Bei mir zeigt es leider keine Pfeile nach oben und nach unten, nur die Ziffern 0 (Pfeil nach oben?) und 1 (Pfeil nach unten?),
habe schon versucht was zu machen, aber als Anfänger komme ich nicht weiter =(
Ist es auch möglich dass, erstmal zB. Datum und Zeit angezeigt werden und erst beim OK drücken spring es ins Menü?
Grüße
Jurek

Hi,

das die Pfeile nicht angezeigt werden, liegt vermutlich am verwendeten Display oder aber daran, dass schon zuviele Benutzerdefinierte Zeichen für das Display belegt sind.

Du kannst das Display im Programm immer löschen und für eigene Zwecke verwenden.
Sobald du "lcd_display.display(); " aufrufst, sollte das Menü wieder erscheinen.

Hi,
leider komme ich nicht weiter...
Wenn ich über lcd.write() im loop die Pfeile anzeige funktioniert das, aber im Programm selbst nicht.
Ich habe ein UNO R3 und ein LCD Keypad shield von DFRobot. Mein IDE ist 1.0.1
Code: Dropbox - Error - Simplify your life
An welche Stelle muss ich in meinem Beispiel die display_RTC() setzen?
Wenn ich das in loop mache überlappen sich der Zeit und das Menü :~
Bitte um Hilfe

Hallo,
gute Nachrichten :slight_smile:
dank den Tipp von Jamelo ist mir gelungen die Pfeile anzuzeigen.
Folgendes habe ich verändert:
in der Datei LCDMenu2.cpp
Zeilen von 199 bis 210, print auf write und die HEX weg

            if(curloc == 0) {
                lcd->setCursor((cols-1),(rows-1));
                lcd->write(arrow_down);
            }
            else if(curloc == j) {
                lcd->setCursor((cols-1),0);
                lcd->write(arrow_up);
            }
            else {
                lcd->setCursor((cols-1),0);
                lcd->write(arrow_up);

                lcd->setCursor((cols-1),(rows-1));
                lcd->write(arrow_down);

und in void setup()

lcd.createChar(0,arrow_up);
lcd.createChar(1,arrow_down);

und dann funktioniert zumindest bei mir :wink:

Ich verzweifle langsam, was ist an dem Code falsch :frowning:
es funktionier einfach nicht

/* ===============================================
 * SET DATE
 * =============================================== 
 */
 void set_Date(char *func_name) 
  {
    //CONTROL_refresh_button();
    t = rtc.getTime(); // Get data from the DS1307
    int tag, monat, jahr, pos;
    if (!CONTROL_set_func_active(func_name)) 
    {
      pos=0;
      tag=t.date;
      monat=t.mon;
      jahr=t.year;
      Serial.print(tag);
      Serial.print(monat);
      Serial.print(jahr);
      lcd.clear();
      lcd.setCursor(3,0);
      lcd.write("Set   date");
      lcd.setCursor(3,1);
      if (tag<10){lcd.print("0");}
      lcd.print(tag);
      lcd.write(".");
      if (monat<10){lcd.print("0");}
      lcd.print(monat);
      lcd.write(".");
      lcd.print(jahr);
    }
    if (menu_button_down == 1 && pos==0) //set tag-
      {
        if ((tag>1) && (tag<=31))
          {
            Serial.print(tag);
            Serial.print(" down ");
            delay(250);
            tag--;
            Serial.print(tag);
            menu_button_down=0;
            if (tag<10) {lcd.setCursor(3,1);lcd.print("0");lcd.print(tag);}
            else {lcd.setCursor(3,1);lcd.print(tag);}
            lcd.setCursor(3,1);
            lcd.blink();
          }
      }
    if (menu_button_up == 1 && pos==0)  //set tag+
      {
        if ((tag<31) && (tag>=1))
          {
            Serial.print(tag);
            Serial.print(" up ");
            delay(250);
            tag++;
            Serial.print(tag);
            menu_button_up=0;
            if (tag<10) {lcd.setCursor(3,1);lcd.print("0");lcd.print(tag);}
            else {lcd.setCursor(3,1);lcd.print(tag);}
            lcd.setCursor(3,1);
            lcd.blink();
          }
      }
    if (menu_button_up == 1 && pos==1)  //set monat+
      {
        if ((monat<12) && (monat>=1))
          {
            Serial.print(monat);
            Serial.print(" up ");
            delay(250);
            monat++;
            Serial.print(monat);
            menu_button_up=0;
            if (monat<10) {lcd.setCursor(6,1);lcd.print("0");lcd.print(monat);}
            else {lcd.setCursor(6,1);lcd.print(monat);}
            lcd.setCursor(6,1);
            lcd.blink();
          }
      }
    if (menu_button_down == 1 && pos==1)  //set monat-
      {
        if ((monat<=12) && (monat>1))
          {
            Serial.print(monat);
            Serial.print(" down ");
            delay(250);
            monat--;
            Serial.print(monat);
            menu_button_down=0;
            if (monat<10) {lcd.setCursor(6,1);lcd.print("0");lcd.print(monat);}
            else {lcd.setCursor(6,1);lcd.print(monat);}
            lcd.setCursor(6,1);
            lcd.blink();
          }
      }
    if (menu_button_up == 1 && pos==2)  //set jahr+
      {
        if (jahr<2100 && jahr>=2000)
          {
            Serial.print(jahr);
            Serial.print(" up ");
            delay(250);
            jahr++;
            Serial.print(jahr);
            menu_button_up=0;
            lcd.setCursor(9,1);
            lcd.blink();
            lcd.print(jahr);
          }
      }
    if (menu_button_down == 1 && pos==2)  //set jahr-
      {
        if ((jahr<=2100) && (jahr>2000))
          {
            Serial.print(jahr);
            Serial.print(" down ");
            delay(250);
            jahr--;
            Serial.print(jahr);
            menu_button_down=0;
            lcd.setCursor(6,1);
            lcd.blink();
            lcd.print(jahr);
          }
      }
    if (menu_button_right == 1) 
    {
      pos++;
      if (pos>3)
      {
        pos=0;
      }
    }
    // CONTROL_func_end (direct, enter, up, down, left, right) 
    CONTROL_set_func_end(0, 1, 0, 0, 0, 0);
  }

Was funktioniert denn genau nicht, und was hast du vor ?

Es soll über LCD Display und Keypad Shield Tasten das Datum einstellen.
Es fehlt noch am ende der Befehl

rtc.setDate(tag, monat, jahr);

ich wollte, sätzen des Datums mit enter bestätigen und auch beenden.
Wie etwa:

if (menu_button_enter == 1)
{
rtc.setDate(tag, monat, jahr);
CONTROL_set_func_end(0, 1, 0, 0, 0, 0);
}

Leider wenn ich diese Code ausführe passiert nichts, es werden keine tasten erfasst (außer back)
dafür habe ich mir die Ereignise im Serial anzeigen lassen. Es wird nichts angezeigt :frowning:
Variable "pos" sagt ob ein Tag, Monat oder Jahr zu stellen ist (0 - Tag, 1 - Monat, 2 - Jahr) und dort soll auch der Blinkcursor stehen.
Tasten nach oben und nach unten sollen den jeweiligen Wert ändern.
Der Hauptcode kommt von deinem Beispiel, ich habe nur das Menü (läuft Prima) und die ausführende Funktionen verändert.
Gruß
offtopic

Solange ich nicht den ganzen Code sehen kann, kann ich nur Tipps geben.

Mikrocontroller haben die Eigenschaft schnell zu sein, da ich in deinem Code viele Delays (die Stoppen das Programm) sehen kann, vermute ich als erstes das es daran liegt.
Solange ein Delay aktive ist, wird kein Button erkannt. Es könnte nun sein, dass du im falschen Moment druckst, oder es kann sein das ein anderer Fehler vorliegt. Bitte poste mal den ganzen Code oder lad ihn irgendwo hoch.
Gruß
Jomelo

Hallo,
anbei der Code:
https://www.dropbox.com/s/k9ptqho9zbs2xpl/Kirys_menu1.txt
Ich wollte auch den gleichen Code (nach Modifikationen) fürs Zeit einstellen verwenden.
Gruß
offtopic

Fehler gefunden :slight_smile:
das ist in void setup() gewandert:

t = rtc.getTime(); // Get data from the DS1307
dzien=t.date;
miesiac=t.mon;
rok=t.year;

und dzien, miesiac, rok sind jetzt globale Variable
Funktionscode ohne Fehler:

Gruß
offtopic

Wie kann man es denn hier mit umlaute benutzen?
Ich benutze im moment dieses hier:

void lcdPrint(char* buf)
{
for(byte i=0;i<strlen(buf);i++)
{
switch (buf*)*

  • {*
  • case 0xC2:*
  • case 0xC3:*
  • case 0xCE:*
  • case 0xCF: break; // filtering UTF-8 highbyte *
  • case 'ä': lcd.print('\xE1');break; // translate UTF-8 lowbyte*
  • case 'ö': lcd.print('\xEF');break; // translate UTF-8 lowbyte*
  • case 'ü': lcd.print('\xF5');break; // translate UTF-8 lowbyte*
  • case '?': lcd.print('\xE0');break; // alpha*
  • case 'ß': lcd.print('\xE2');break; // beta, sz*
  • case 'µ': lcd.print('\xE4');break; // micro*
  • case '°': lcd.print('\xDF');break; // degree symbol*
  • case '?': lcd.print('\xF4');break; // omega*
  • case '?': lcd.print('\xE5');break; // sigma*
  • case '?': lcd.print('\xF6');break; // Sigma*
    _ default: lcd.print(buf*);_
    _
    }_
    _
    } _
    _
    }_
    _
    [/quote]*_
    Aber beim #define ist ja nix mit lcdprint

skorpi08:
Aber beim #define ist ja nix mit lcdprint

Wenn Deine print-Befehle für das LCD-Display in einer Library stecken statt in Deinem Sketch, dann mußt Du meine Umwandlungsroutine natürlich erstmal in Deine Library einbauen, bevor Du sie aufrufen kannst.