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

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.

Hi, ich habe mal dieses Thema auf den neusten Stand gebracht.
Die Lib wurde aktualisiert und das Tutorial angepasst.

Mehr Informationen gibt es im ersten Beitrag:
http://arduino.cc/forum/index.php/topic,73816.0.html

Hallo,

erstmal danke für dieses gelugene Projekt. Ich konnte damit als Anfänger ein sehr komplexes Menü mit sauberer Steuerung und IR-Fernbedienung in wenigen Stunden realisieren. Die Steuerung und die Menüfunktionen als solches habe ich jetzt fertig.
Nuin stehe ich vor der Frage wo und wie ich permanent laufende Hintergrundprozesse integriere.

Ich bin dabei eine recht komplexe Steuerungseinheit aufzubauen. Dazu arbeite ich mit einer RTC und verschiedenen Alarmen. Prinzipiell sind es eine Vielzahl von Zeitschaltuhren, welche einen Schaltkreis grundsätzlich aktiven. Dazu kommen nach der Aktivierung verschiedene Prüfparameter durch Sensoren. Wenn alle Bedingungen erfüllt sind wird der jeweilige Pin HIGH oder ein PWM startet.

Die ganzen kleinen Subfunktionen werde einfach im Funktionsbereich als Subfunktionen aufbauen. Aber wo und wie integriere ich die Funktion die im Hintergrund immer läuft, sobald der Controller, sprich der Arduino, aktiv ist.

EDIT:
Ich glaube ich kann im loop auch Funktionen aus Menu_Func direkt aufrufen. Wenn dem so ist hab ich mein Problem gelöst.

Danke vorab.

Vermutlich in der Loop Funktion, ich bastel gleich mal ein Beispiel wie das dann aussehen könnte.