Go Down

Topic: Projekt: LCDMenuLib - Menü mit mehreren Ebenen (4Bit/I2C/u8glib/SerialMonitor) (Read 214591 times) previous topic - next topic

Jomelo

Moin,
dann bau es so in die "initscreen" Funktion ein.
Um dein Display komplett ausschalten zu können musst du die Versorgungsspannung über einen Transistor/Fet steuerbar machen. Zudem musst du experimentell ermitteln wie lange das Display nach einschalten der Versorgungsspannung benötigt bis es Befehle vom Kontroller empfangen kann. Danach kannst du das Display initialisieren.
Diese Prozedur muss nach jedem neustart des Displays durchlaufen werden.
while(!success){try++;}

tobias_faust

Hi,
weiß einer wie ich in jedes UNtermenü automatisch einen BACK Eintrag hinbekomme? Gibt es da eine fertige funktion o.ä.?
Ich habe nur einen RotaryEncoder, der kann nur rechts/links/enter

Jomelo

Automatisch geht das nicht. Mir ist auch noch keine Lösung dazu eingefallen. Hier ist Handarbeit gefragt. (back button Beispiel)
while(!success){try++;}

skorpi080

Jomelo, wenn du mal Zeit und Laune haben solltest, schau dir mal Marlin Software bei 3D Druckern an.
Vielleicht kannst dir da was abschauen.

playground.arduino.cc/PmWiki/433Mhz-Funkmodule

Clyde85

Hi Leute erstmal dickes Lob an Jomelo. Ein gut gemachte Lib. Auf meinen Mega hatte ich nie Probleme damit, außer selbstgemachte ;-)  Aber für mein neues Projekt hab ich mir ein Micro gekauft. Auf dem Micro will die MenuLib 2.3.2 einfach nicht laufen. So funktioniert alles, nur wenn ich den Sketch mit der MenuLib hochlade bekomme ich nichts mehr angezeigt. Hab schon verschiedene Arduinos, LCDs, LCD Libs, 4-Bit/I2C und so ziemlich alle Pin durchprobiert aber immer das selbe.  Hat schon jemand die MenüLib auf einen Micro am Laufen?
Stelle ich mich nur zu doof, oder kann es sein das die Lib nicht auf einen Micro läuft?
MfG Marco
 

Jomelo

Passt den der Speicherverbrauch oder ist das Programm zu groß ?

Ich hab es noch nie auf einem Micro getestet. Kann dazu auch nicht so viel sagen.
while(!success){try++;}

Clyde85

Der Programmspeicher wäre zu 46% belegt, dynamischer Speicher zu 37%. Also alles im normalen Rahmen.
Währe schön wenn hier jemand ein Micro hätte und mal Testen könnte ob es bei ihn läuft.
Das Micro hatte einen 32U4. Der gleiche wie beim Leonardo. @Jomelo Danke für die schnell Antwort und nochmal
großes Lob für die Arbeit die du hier reinsteckst.   

tobias_faust

Hi,
ich habe mal eine Frage zu den Backendfunktions. Ich versteh das LCDML_Start, bzw LCDML_STOP nicht.
Ich benutze die LCDML Development Library.
Folgender code:
Code: [Select]
// define backend function  
  #define _LCDML_BACK_cnt    2  // last backend function id
  
  LCDML_BACK_init();
  LCDML_BACK_new_timebased_dynamic (0  , ( 20000UL )      , _LCDML_micros, _LCDML_start , _LCDML_jp_next, LCDML_BACKEND_control);
  LCDML_BACK_new_timebased_dynamic (1  , ( 10000000UL )   , _LCDML_millis, _LCDML_stop  , _LCDML_jp_next, LCDML_BACKEND_menu);
  LCDML_BACK_new_timebased_dynamic (2  , ( 10000UL )      , _LCDML_millis, _LCDML_stop , _LCDML_jp_next, LCDML_BACKEND_prog1); // every 10sec


Es geht um die 3. Funktion (LCDML_BACKEND_prog1). Initialisiereich die mit LCDML_stop, so wird sie NICHT aufgerufen. Nehme ich LCDML_start, so wird sie zwar im loop immer wie gewünscht aufgerufen, aber meine 1. Funktion (LCDML_BACKEND_control) nicht mehr.

Ich möchte, das meine Backendfunktion IMMER und kontinuerlich alle 10sek in der loop im Hintergrund läuft. Egal welches MEnü oder Display gerade aufgerufen ist.
Wo ist  mein Denkfehler?

PS: was macht eigentlich _LCDML_jp_next, das ist erst in der Develop neu und noch ohne Doku

Backendfunktion:
Code: [Select]

/* ===================================================================== *
 *                                                                       *
 * BACKEND SYSTEM                                                        *
 *                                                                       *
 * ===================================================================== *
 * every "backend function" needs three functions
 * - void LCDML_BACK_setup(..func_name..)   
 * - void LCDML_BACK_loop(..func_name..)     
 * - void LCDML_BACK_stable(..func_name..)
 *
 * - every BACKEND function can be stopped and started
 * EXAMPLE CODE:
    void LCDML_BACK_setup(LCDML_BACKEND_control)
    {
      // setup
      // is called only if it is started or restartet (reset+start)
    }
   
    void LCDML_BACK_loop(LCDML_BACKEND_control)
    {   
      // runs in loop
     
     
      return false; 
    }
   
    void LCDML_BACK_stable(LCDML_BACKEND_control)
    {
      // stable stop
      // is called when a backend function is stopped with stopStable 
    }
 * ===================================================================== *
 */


// *********************************************************************
// Read and publish BME280 Sensordata
// *********************************************************************
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C

void LCDML_BACK_setup(LCDML_BACKEND_prog1) {
  // setup
  // is called only if it is started or restartet (reset+start)
  // setup
  // is called only if it is started or restartet (reset+start)
  Serial.println(F("Setup: LCDML_BACKEND_static"));
  Serial.println(F("==========================="));

  volatile boolean status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
  }     
}


void LCDML_BACK_loop(LCDML_BACKEND_prog1)  {   
  char msg[50];
  char topic[50];
  snprintf (msg, sizeof(msg), "%.1f", bme.readTemperature());
  snprintf (topic, sizeof(topic), "%s%s", MQTT_ROOT, MQTT_GetTemperature);
  client.publish(topic, msg);

  snprintf (msg, sizeof(msg), "%.1f", bme.readHumidity());
  snprintf (topic, sizeof(topic), "%s%s", MQTT_ROOT, MQTT_GetHumidity);
  client.publish(topic, msg);

  snprintf (msg, sizeof(msg), "%.1f", bme.readPressure() / 100.0F);
  snprintf (topic, sizeof(topic), "%s%s", MQTT_ROOT, MQTT_GetPressure);
  client.publish(topic, msg);
}
   
void LCDML_BACK_stable(LCDML_BACKEND_prog1) {
  // stable stop
  // is called when a backend function is stopped with stopStable 
  // stable stop
  // is called when a backend function is stopped with stopStable
  Serial.println(F("Stop Stable: LCDML_BACKEND_static"));
  Serial.println(F("=================================")); 
}

   
// *********************************************************************
// insert here your own backend functions
// *********************************************************************


















// *********************************************************************
// Control Task, DO NOT CHANGE
// *********************************************************************
void LCDML_BACK_setup(LCDML_BACKEND_control)     
// *********************************************************************
{
  // call setup   
  LCDML_CONTROL_setup();     
}
// backend loop
void LCDML_BACK_loop(LCDML_BACKEND_control)
{   
  // call loop
  LCDML_CONTROL_loop();
}
// backend stop stable
void LCDML_BACK_stable(LCDML_BACKEND_control)
{
}



// *********************************************************************
// Menu Task, DO NOT CHANGE
// *********************************************************************
void LCDML_BACK_setup(LCDML_BACKEND_menu)
// *********************************************************************                           
{   
  // get current function id                                                                 
  g_LCDML_BACK_lastFunc = LCDML.getFunction();                     
 
  // check current running function
  if (g_LCDML_DISP_functions_loop_setup[g_LCDML_BACK_lastFunc] == LCDML_FUNC_loop_setup)
  {
    // stop old function if running
    bitSet(LCDML.control, _LCDML_control_funcend);             
  }                                                               
  else if (g_LCDML_BACK_lastFunc != _LCDML_NO_FUNC)
  {
    // display new function content             
    LCDML_lcd_menu_clear();                                       
    LCDML_BUTTON_resetAll();                                   
    g_LCDML_DISP_functions_loop_setup[g_LCDML_BACK_lastFunc]();
  }                                                               
}                                                                   
void LCDML_BACK_loop(LCDML_BACKEND_menu)                           
{                                                                   
  if (LCDML.getFunction() != _LCDML_NO_FUNC)
  {
    g_LCDML_DISP_functions_loop[LCDML.getFunction()]();
  }
}                                                                   
void LCDML_BACK_stable(LCDML_BACKEND_menu)                           
{                                                                   
  if (g_LCDML_BACK_lastFunc != _LCDML_NO_FUNC)
  {
    // call loop end function                   
    g_LCDML_DISP_functions_loop_end[g_LCDML_BACK_lastFunc]();   
    // reset last function
    g_LCDML_BACK_lastFunc = _LCDML_NO_FUNC;                     
    // clear display/console
    LCDML_lcd_menu_clear();                                       
    // display menu
    LCDML.display();                                               
    LCDML_lcd_menu_display(); 
    // reset all button values                                 
    LCDML_BUTTON_resetAll();
    // reset current function                                   
    LCDML.function = _LCDML_NO_FUNC;                           
    bitClear(LCDML.control, _LCDML_control_funcend);           
    // jump to a function if enabled
    if(g_lcdml_jump_func != _LCDML_NO_FUNC) {                   
      LCDML.jumpToElement(g_lcdml_jump_func);                   
      LCDML_DISP_update_menu();                                 
      g_lcdml_jump_func = _LCDML_NO_FUNC;                       
    }
    // go root if enabled                                                           
    if(bitRead(LCDML.control, _LCDML_control_go_root)) {       
      LCDML.goRoot();                                           
      LCDML.display();                                       
      LCDML_lcd_menu_display();                               
    }                                                           
  }                                                               
}


Jomelo

Das mit dem Backend sollte eigentlich laufen. Ich hab dir aber auch eine frühe alpha Version gegeben und bin da im Moment noch am verbessern. Ich hoffe das die nächste Version (am Wochenende) besser laufen wird.

Das mit _LCDML_jp_root  und _LCDML_jp_next  ist der Ersatz für das weggefallene return in den Backendfunkionen. Anhand dieser Beschreibung kann man es grob erklären.
http://forum.arduino.cc/index.php?topic=165552.0

Im Moment bin ich dabei soviele Makros wie möglich zu entfernen, da diese schwer zu warten sind und viele unverständliche Fehlermeldungen verursachen können. Des Weiteren wird der Speicherbedarf in der nächsten Version leicht sinken.

Die nächste Versionsnummer ist 3.0.0. Diese Version ist ohne Anpassungen nicht abwärtskompatibel.

while(!success){try++;}

tobias_faust

HI Jomelo,
was LCDML_start bzw LCDML_stop betrifft, habe ich in dem Thread leider nicht herauslesen können - also WANN, WAS für WELCHES VErhalten benutzt werden soll.

Dafür hat der Thread aber andere Fragen bei mir geklärt :) (zb. Änderung der dynamischen Zeit)
Und andere dafür aufgeworfen, zb. wofür die Backendgruppen gut sein sollen.

Aus meiner Theorie: LCDML_start läuft immer, LCDML_stop immer dann wenn eine Menüfunktion aktiv ist. Wenn man sich im Menü bewegt dann nicht.

tobias_faust

Sag uns einfach wann wir welchen Zweig zur Benutzung downloaden können. Gibt es Punkte welche KOstrukte gegen welche Neuen ausgetauscht werden müssen damit alter Code mit neuer Lib läuft?

Edit: habe gerade das neue v3.0.0 Exmple angeschaut: OH-MEIN-GOTT  ... das ist ja wirklich komplett anders. Da kann man ja nicht mehr vom eigenen Sketch "anpassen" reden sondern eher vom "umschreiben" bzw "neu schreiben".....

Also diese neuen Funktionen müssen unbedingt alle neu dokumentiert werden....

skorpi080

Wenns dir nicht passt, lass es doch einfach. Er muss schon mal garnichts.
So neu ist es auch garnicht, dass man von einer Version zur anderen den Code neu schreiben muss.
Entweder du machst es oder du lässt es sein, ein Weg dazwischen wirds wohl nie geben.
playground.arduino.cc/PmWiki/433Mhz-Funkmodule

tobias_faust

Hi Skorpi080,
mein Post war 100% positiver natur. Ich schätze und bewundere Jomelos Arbeit! Per PN hat er mir auch geholfen die Lib auf dem ESP32 zum LAufen zu bekommen. Ich stehe vor einem großen ESP Projekt bei der die Lib die Basis sein soll. Ich möchte natürlich auch die neue 3.x einsetzen.

War im ersten MOment nur erschlagen von den Unterschieden und möchte die "neue" Lib auch verstehen damit ich sie effektiv einsetzen kann :)

Sobald Jomelo den Startschuss gibt für die neue 3.x gibt, ersetze ih die Lib 2.4 durch die 3.x.

usby

Hallo Jomelo

Am 11.8.17 hat michaeltanner einen Post zu "kryptischen Zeichen in der Menustruktur gemacht". Es geht dabei um Programme für Teensy 3.2.
Ich will hiermit bestätigen, dass auch bei mir auf einem Teensy 3.2 kryptischen Zeichen in der Menustruktur erscheinen. Und zwar nicht bei deinen Beispielprogrammen, die laufen gut, sondern bei deutlich umfangreicheren Programmen.
bei mir hat auch der Tipp von Michael geholfen, d.h. ich habe in der Datei LCDMenuLib.ccp folgendes geändert:
      if (bitRead(group_en, tmp->disp)) {   
//#if defined ( ESP8266 )
         strcpy_P(content[i-scroll], (char*)(flash_table[tmp->name]));
//#else
//         strcpy_P(content[i-scroll], (char*)pgm_read_word(&(flash_table[tmp->name])));
//#endif

d.h. es wird jetzt immer strcpy ohne pgm_read_word genutzt.

Vielleicht kannst du das ja verstehen und in Zukunft nutzen.

Gruß Uwe


Jomelo

LCDMenuLib v3.0.0 Beta 1

https://github.com/Jomelo/LCDMenuLib/tree/develop


Vorweg:
  • die Version 3.0.0 ist nicht kompatibel mit der Version 2.3.x
  • Alle Funktionen / Klassen / Makros angepasst/umgeschrieben.
    Dies Umschreiben wurde nötig, da die verwendeten Makros sich sehr bescheiden warten lassen und jede neue Funktionalität kaum noch zu testen war. Die Makros vereinfachen die Schreibweise von C Code, machen aber das Fehlersuchen sehr kompliziert.
    Kurzgesagt: Ich konnte die Lib in dem vorherigen Zustand nicht mehr erweitern ohne Stunden an Zeit zu investieren.
  • Die Bezeichnungen von Funktionen/Makros werden sich innerhalb der Beta Version 3.0.0 nicht mehr ändern. (außer es kommt etwas neues hinzu)


Allgemeines:
  • esp32 / esp8266 / arduino unterstützt
  • viele Beispiele erstmal entfern, diese werden in den nächsten Wochen angepasst wieder hinzugefügt. Bin da nicht ganz so schnell
  • Die Namensgebung von Funktionen/Makros ist nun streng nach Funktionalitäten getrennt.


Menü:
  • Menu Gruppen entfernt, als Ersatz gibt es nun "Bedingungen" (condetions)
  • Parameter können nun immer übergeben werden, es wird keine gesonderte Initialisierung benötigt. Die Parameter werden als Übergabewert an die entsprechendne Menüfunktionen übergeben. Es können Parameter zwischen 0 und 200 übergeben werden. Die Werte oberhalb sind für special Funktionen reserviert.
  • Der Aufbau der Display Funktionen wurde vereinfacht. Die bei der Initialisierung definierte Funktion wird als Callback aufgerufen. Innerhalb dieser Funktion gibt es die gewohnten Bezeichnungen.
  • Es gibt wie gewohnt setup, loop und loop_stableEnd, dies sind aber If-Abfragen in der Callback Funktion.
  • Die Funktionalität um dynamische Inhalte ins Menü zu bringen wurde vereinfacht und erweitert. Im unittest befindet sich ein Beispiel in dem im Menü dynamisch ein Parameter verstellt werden kann. Dies geht nur, wenn der Cursor auf dem Parameter steht.
  • Buttons können nun auch im Menü außerhalb von Funktionen abgefragt/zurückgesetzt werden.
  • Die Button Funktionalität befindet sich nun im LCDML object.
  • Der Initscreen wurde entfern, dazu kann nun beliebig eine Funktion als Bildschirmschoner festgelegt werden (Screensaver). Der Bildschirmschoner kann im Setup und jeder Menüfunktion ein- oder ausgeschaltet werden. Bei jedem aktivieren muss die Screensaver-Funktion und die Zeit bis dieser aktiviert wird neu gesetzt werden. Die Wartezeit des Bildschirmschoners wird mit jedem Tastendruck zurückgesetzt. Zudem kann jede Menüfunktion den Bildschirmschoner, solange sie aktive ist, abschalten.
  • Die Backendfunktionen LCDML_BACK_control und LCDML_BACK_menu sind nun in die Lib gewandert.
  • Es ist nun möglich im Kreis zu scrollen. (muss im Setup aktiviert werden) @3it danke für die Idee
  • Die Menülib ist nun unabhängig vom Backend. Beides kann aber miteinander kombiniert werden. Beispiele dazu folgen


Backend:

- anderer Name: LCDBL_....
- Hinzufügen von Micros und Millis

Details zur Abschaffung von Gruppen
Die Funktion Menüpunkte in Gruppen einzuteilen und einzeln ein oder auszublenden wurde abgeschafft.
Als alternative können Bedingungen gesetzt werden. Als Bedingung wir eine Funktion mit einem boolean Rückgabewert erwartet.
Mit Bedingungen können deutlich komplexere Lösungen umgesetzt werden. In den Beispielen sind zwei Bedingungen erstellt:
boolean COND_hide { return false; }


Timer Funktion TIMER_ms....
Die Funktion kann überall verwendet werden. Der Funktion muss eine unsigned long Variable übergeben werden, sowie die Wartezeit.
Es wird als Rückgabewert true oder false zurückgegeben. True, wenn die Zeit abgelaufen ist. False, wenn nichts passieren soll.
Die Funktion gibt zum erstenmal true zurück, sobald die Zeit abgelaufen ist.


ToDo:
- Beispiele hinzufügen
- Backend anpassen
- Dokumentation wird in englischer Sprache auf GitHub erfolgen. (das PDF ist ab dieser Version)
- Bugs beheben die euch auffallen.

Bekannte Bugs:
- das Springen in Menüs bei denen die SubMenüs sichtbar sind, das Hauptelement aber versteckt ist funktioniert noch nicht.


@usby
- Danke für die Info, ist in v3.0.0 geändert

@skorpi080
- Der folgende Bug ist behoben:
http://forum.arduino.cc/index.php?topic=73816.msg3167077#msg3167077
- Die Marlin Software kenne ich halbwegs, ich hab hier den Felix Printer, der nutzt eine ähnliche Quellcodebasis.

@tobias_faust
- das Backend nehm ich mir für BETA 2 vor


Viel Spaß beim ausprobieren.
while(!success){try++;}

Go Up