Go Down

Topic: Projekt: LCDMenuLib / LCDMenuLib2 ( LCDML ) - Menü mit mehreren Ebenen  (Read 342587 times) previous topic - next topic

jabami

Hallo,

ich hab die "Custom Characters" gefunden. Aber warum "verbrätst" Du denn für den einfachen Scrollbalken 2 Characters? In jedem HD44780 kompatiblen Display sind bereits Pfeile für hoch und runter integriert.

Pfeil hoch

lcd.write(B00011000)

Pfeil runter

lcd.write(B00011001)

Hier das Datenblatt: https://www.adafruit.com/datasheets/HD44780.pdf

Soweit ich weiss implementieren sogar alle Derivate des HD44780 den selben Datensatz.
---------------------------------------------------------------------------------------------------
Nachtrag:
Hab meinen Fehler bzgl. der zusätzlich implementierten Symbole gefunden:

Scrollbalken Option 1 (die schönere Version) benutzt 5 (gezählt wird ab 0) zusätzliche custom characters, d.h. eigene Custom Characters können erst ab Byte 5 beginnen.

Scrollbalken Option 2 (die einfache Version) benutzt 2 zusätzliche Charactere (wobei dies, wie ich oben schon erwähnt unnötig ist), d.h. eigene Custom Characters können erst ab Byte 2 beginnen.

Im Allgemeinen können HD44780 basierte Displays 8 Custom Charaters speichern.

Beste Grüße,
Jan

Jomelo

Hi,
ich habe das gerade nochmal mit den Pfeilen nachgeschaut.
[edit]
Der normale  HD44780 Standard hat die Pfeile nicht. Der HD44780U Standard ergänzt die Pfeile. Die Displays die ich hier im Moment liegen haben nutzen noch den alten Standard, daher kann ich die Pfeile so nicht entfernen. Ich könnte in der nächsten Version den Standard im Config-File auswählbar bereitstellen. Als "default" bleibt dann die alte Variante eingebunden, die läuft auf jedem Display.
[/edit]

Den Bug, der die Pfeile nicht am ende der Zeile anzeigt habe ich nun behoben. Dieser ist bei einer Umstellung in der letzten Version leider eingefügt worden. Ich denke das ich gegen Ende nächster Woche eine neue Version bereitstellen kann.
while(!success){try++;}

Serenifly

@jabami
Viele - wenn nicht sogar die meisten - Displays die man hier zu kaufen bekommt haben aus irgendeinem Grund den japanischen A00 Zeichensatz

jabami

Hallo Jomelo,

Super dank Dir.

Kleiner Tip. Da Du ja eh schon eine Scrollbalken Config hast könntest Du noch eine 3. Konfiguration hinzufügen welche die Symbole

Pfeil hoch
lcd.write(B00011110)

Pfeil runter
lcd.write(B00011111)

nutzt. Ggf. zusammen mit dem vollen Symbol

lcd.write(B11111111)

macht das dann wahrscheinlich auch eine ganz nette Scrollbalkenalternative die keine Custom Characters verwendet.
------------------------------------------------------------------------------------------------------
Nachtrag:
@Jomelo: Ich hab eben erst gesehen was Du meinst. Zuvor dachte ich immer die Tabelle wird einfach auf der nächsten Seite weiter geführt, aber Du hast recht, es handelt sich offensichtlich um 2 verschiedene Versionen des HD44780. Daher klappt die oben genannte Idee von mir mit der 3. alternativen Konfiguration wahrscheinlich nicht. Die Pfeile nicht zu entfernen ist daher wirklich die beste Idee um eine möglichst hohe Kompatibilität zu gewährleisten. Sorry, das war mir vorher nicht aufgefallen.
------------------------------------------------------------------------------------------------------
Achso und weil wir grad dabei sind, wäre es möglich einen zusätzlich zu konfigurierenden Splash-Screen zu implementieren? Quasi eine Anzeige die einem Level 00 entspricht und nicht im Menü (als separater Eintrag) auftaucht. Der Splash Screen wäre der erste Screen nach dem Setup, und könnte wenn man im Menü ist (Level 0) über den Back Button erreicht werden. Über die Konfiguration ließe sich die Verwendung dieses Splash-Screens an und aussschalten. Die Funktionen für den Splash Screen könnten weiterhin in der separaten Datei (Menu_functions -> aus dem Beispiel) programmiert werden. Das fänd ich ne tolle Sache.

@Serenifly: Ja eben, weil sie den gesamten Zeichensatz des Hitachi (jap. Firma) HD44780 Controllers implementieren. Siehe hierzu auch das zuvor verlinkte Datenblatt. In diesem Controller sind bereits sehr viele Zeichen vorinstalliert die man mit einem entsprechendenm Befehl ansprechen kann. Mit der LiquidCrystal library z.B. so:

lcd.write(B[upperByte][lowerByte])

[upperByte] und [lowerByte] muss man nur noch durch die entsprechenden Bitfolgen aus der Tabelle 4 des verlinkten Datenblattes ersetzen. Somit hat man schonmal eine recht gute Auswahl an Zeichen. Nur leider eben nicht alle. Siehe Scrollbalkensymbole von Jomelo bzw. einige mathematische Symbole.


Grüße,
Jan



Jomelo

Das mit den einfachen Pfeilen und dem HD44780U habe ich bereits ergänzt. Ich denk zum Scrollbalken mit mehreren CustomChars wird mir auch noch was einfallen.
Den Splash Screen kann ich installieren, wobei diesen könnte man nun auch umsetzen in dem die Funktion die als _setup gekennzeichnet ist, einfach etwas später einmalig aufgerufen wird.
Edit:
Oder direkt in eine Funktion springt, von der man dann mit Zurück wieder ins Menü kommt.
while(!success){try++;}

Serenifly

Ich weiß wie das funktioniert :)

Ich hätte sagen soll "NUR den japanischen Zeichensatz". Die von dir erwähnten Pfeile sind nur im A02 Zeichensatz (der die ganzen Sonderzeichen und kyrillischen Buchstaben hat). Die Displays haben jeweils einen der Sätze, aber nicht beide. Wenn du eines mit dem europäischen Zeichensatz hast, sehr schön, aber das ist nicht immer der Fall. Was man so lesen kann, haben die meisten Leute nur den begrenzteren japanischen Zeichensatz.

jabami


Das mit den einfachen Pfeilen und dem HD44780U habe ich bereits ergänzt. Ich denk zum Scrollbalken mit mehreren CustomChars wird mir auch noch was einfallen.
Den Splash Screen kann ich installieren, wobei diesen könnte man nun auch umsetzen in dem die Funktion die als _setup gekennzeichnet ist, einfach etwas später einmalig aufgerufen wird.
Edit:
Oder direkt in eine Funktion springt, von der man dann mit Zurück wieder ins Menü kommt.


Das letzte hab ich jetzt nicht so richtig verstanden. Wie meinst Du das? Der Splash-Screen soll ja nicht nur einmalig ausgeführt werden, sondern eben genau immer dann wenn das Menü nicht genutzt wird, da das Menü ja nur für Einstellungen und Konfigurationen genutzt werden soll.
Wieso sollte die Funktion etwas "später" und warum nur "einmalig" ausgeführt werden?

@Serenifly: Sorry, diesen Fehler von mir hatte ich soeben beim nochmaligen anschauen des Datenblattes auch bemerkt. Ich dachte immer die Zeichentabellen im Datenblatt würden zusammen gehören. Tun sie aber nicht. Ich hatte Dich da in Deinem vorhergehenden Post definitiv missverstanden.  :smiley-red:

Sijjim

Moin,

Nutze die Lib auch seit ein paar Tagen, funktioniert annähernd perfekt.
Aber wenn wir schon bei "Wünsch dir was" sind.... wie wäre es, wenn man in der Config vorgeben kann, welches Item als erstes nach dem Start angezeigt wird? Am besten sogar ob den Menüeintrag oder die Funktion dahinter. Glaube zwar, das ihr das mit dem Splash-Screen meint, sicher war ich mir aber nicht, oder redet ihr auch aneinander vorbei?!  :P

Trotzdem, danke an den Lib-Ersteller, tolles Teil was du hier gezaubert hast.
Grüße

jabami

Hallo Sijjim,

ich meinte exakt das Gleiche. Bis auf vielleicht den kleinen Unterschied, das der Splash-Screen keinen Eintrag im Menü selbst hätte. Den Splash-Screen würde man erreichen, wenn man das Menü "verlässt" , soll heissen wenn man in der Menüanzeige des Level 0 den back-button betätigt.

Gruss,
Jan

Jomelo

Hi Sijjim & jabami,

ich habe beide Funktionen getrennt voneinander umgesetzt. Ich habe die Lib unten angehängt. Im Moment ist es noch eine Beta, da ich bis zur nächsten Version noch I2C einbinden will.
Testet beide bitte die Beta Lib. Ihr könnt euren alten Code 1 zu 1 weiter verwenden. Die Änderungen sind abwärts kompatibel

@jabami
Füge mal in dem Tab in dem auch die anderen FUNC_ ... Funktionen liegen folgenden Code ein:
Code: [Select]

void FUNC_splash_screen(void)
{
 lcd.clear();

 // der weitere Code
}

Die Funktion kann mit "Quit/Back" aufgerufen werden, wenn das Menü in Ebene 0 ist. Das Beenden geht mit allen anderen Tasten außer Back/Quit. Es kann auch jeder Zeit aus jedem Menü Punkt der Screen direkt aktiviert werden mit:
Code: [Select]

LCDML.splashScreen = 1;

Um die Funktion zu deaktivieren muss einfach die Funktion "FUNC_splash_screen" gelöscht werden. Diese wird intern als Dummy mir leeren Inhalt angelegt und je nach Anwendung vom Benutzer überschrieben.


@Sijjim
Du musst dich damit abfinden, dass man im Moment noch mit der Element Nummer arbeiten muss. Leider kann man noch nicht direkt den Funktionsnamen übergeben.
Es ist aber möglich aus in jede ausführbare Funktion zu springen. Am Beispiel kann man das testen in dem man folgenden Code verwendet:
Code: [Select]

void setup()
{
 /* Setup for LcdMenuLib */
 
 LCDMenuLib_setup(_LCDMenuLib_cnt);
 //Serial.begin(9600);

 LCDML.jumpToElement(11); // Dreimal nach links drucken  
}

Anstatt 11 kann man auch zu 0 oder 1 springen. Ich experimentier noch, wie sich das umsetzen lässt mit  LCDML.jumpToElement(FUNC_p2). Ich denke zur nächsten Version wird das klappen.

Ansonsten kam mir noch die Idee, dass der Splash-Screen angezeigt wird, nachdem X Sekunden, z.B: 60  keine Aktivität ausgeführt wurde.



while(!success){try++;}

skorpi080


Ansonsten kam mir noch die Idee, dass der Splash-Screen angezeigt wird, nachdem X Sekunden, z.B: 60  keine Aktivität ausgeführt wurde.



Dass wollt ich haben
playground.arduino.cc/PmWiki/433Mhz-Funkmodule

jabami

Hallo Jomelo,

vielen herzlichen Dank für diese unglaublich schnelle Umsetzung. Es funktioniert soweit auch alles, nur das ich in meiner "FUNC_splash_screen" keine loops verwenden kann. Hier mein derzeitigr Code:
Code: [Select]

/* ==========================
* SPLASH-Screen
*
* Beschreibung:
* Diese Funktion zeigt die darzustellenden
* Messwerte an.
* ========================= */
 void FUNC_splash_screen(void)
 {  
   /* --------- INIT ---------
    * Initialisierung dieser Funktion
    * wird nur einmal beim Start dieser Funktion ausgefuert
    * danach nur erneut, wenn die Menu Funktion verlassen wurde
    * wenn keine Variablen initialisiert werden müssen, kann diese
    * Funktion anstatt mit if(!CTR_init()) ....     mit
    * CTR_init();  aufgerufen werden    
    */  
   if(!LCDML.FuncInit())
   {
     /* Init Function */            
     // Static Display 1st Row for m_dot
     lcd.clear();                   // Clear the LCD Display
     lcd.setCursor(0,0);            // set Cursor to initial position 1st Row
     lcd.print("m");            // print custom character 5 "dotted_m"
     lcd.print(" :");               //
     lcd.setCursor(12,0);           // set Cursor to position 12 in 1st Row
     lcd.print("kg/s");             //
     // Static Display 2nd Row for T
     lcd.setCursor(0,1);            // set Cursor to initial position 1st Row
     lcd.print("T :");              //
     lcd.setCursor(12,1);           // set Cursor to position 12 in 1st Row
     lcd.print('\xDF');             // print custom character 6 "°"
     lcd.print("C");                //    
   }
   /* --------- LOOP ----------
    * Hier sollte der Code stehen der ständig neu geladen wird
    * z.B. eine Uhrzeit oder änliches.
    */
    lcd.setCursor(3,0);            // set Cursor to position 3 in 1st Row
    lcd.print(millis()/1000);      // display seconds elapsed since power-up
    lcd.setCursor(3,1);            // set Cursor to position 3 in 1st Row
    lcd.print(millis()/1000);      // display seconds elapsed since power-up  
   
   /* --------- STOP  ---------      
    * CTR_func_end (direct, enter, up, down, left, right)
    * Fall in dieser Funktion keine Variablen zurückgesetzt werden
    * müssen, kann diese Funktion auch vereinfacht mit CTR_end(0, 1, 1, 1, 1, 1);
    * aufgerufen werden. Die Endbedingungen müssen durch die Zahlen >0 vorgegeben
    * werden
    * Wenn alles 0 ist, hängt das gesammte Programm in dieser Funktion fest
    */
   if(LCDML.FuncEnd(0, 1, 0, 0, 0, 0))
   {
     /* Falls noch Variablen zurückgesetzt werden müssen, bevor diese Funktion
      * verlassen wird, kann dies in dieser If Schleife geschehen
      */
   }    
 }


Und ich hätte noch eine Frage zur Verwendung der Functions generell. Wie kann ich eine globale Variable an eine Funktion übergeben? Ich wollte einen Konfigurationspunkt für die Hintergrundbeleuchtung hinzufügen und bin daran gescheitert, da ich meine Variablen für den anzusprechenden Pin und den Helligkeitswert nicht in die Funktion bekommen habe.

Beste Grüße,
Jan

Jomelo

Ok, die Splash Funktion ist anders aufgebaut wie die anderen Funktionen, die Init und End Funktion haben dort keine Wirkung.

Wenn du diese nicht verwendest läuft die Funktion auch in der Loop. Ich werde das mal noch anpassen ;-)
Um die Initialisierung muss man sich im Moment noch per Hand kümmern.

while(!success){try++;}

skorpi080

Code: [Select]

in void setup()

brightness_index = 6;


Code: [Select]
//LCD Hintergrundbeleuchtung
  #define _PIN_BACKLIGHT 10
  unsigned char brightness_levels[7] = { 0, 20, 50, 90, 130, 190, 255 };
  unsigned char brightness_index;
 


Code: [Select]
 
/* ===================================================================================================
* SET BACKLIGHT
* ===================================================================================================
*/
 void  FUNC_helligkeit(void)
 {
   if(!LCDML.FuncInit())
   {    
     lcd.clear();
     lcd.print(F(" Helligkeit 1-6"));   
     lcd.setCursor(7,1);
     lcd.print(brightness_index);
   }
   
   /* --------- LOOP ---------- */
   if(LCDML.checkButtons())
   {
     if (LCDML.g_button_down >= 1 && brightness_index > 0 && brightness_index <=6) //fadeOut
     {      
        LCDML.g_button_down=0;
        brightness_index-1;          
     }
     else if (LCDML.g_button_up >= 1 && brightness_index < 6 && brightness_index >=0)  //fadeIn
     {
        LCDML.g_button_up=0;      
        brightness_index+1;
     }
     
     lcd.setCursor(7,1);
     lcd.print(brightness_index);
     analogWrite(_PIN_BACKLIGHT, brightness_levels[brightness_index]);
   }
   
    /* --------- STOP  ---------*/
   if(LCDML.FuncEnd(0, 1, 0, 0, 0, 0))
   {
   
   }
 }
 
playground.arduino.cc/PmWiki/433Mhz-Funkmodule

jabami

Danke skorpi08 für das Backlightbeispiel.

Meine Implementierung sieht nun so aus:

Code: [Select]

void FUNC_LCD_Backlight(void)
 {
   /* --------- INIT ---------
    * Initialisierung dieser Funktion
    * wird nur einmal beim Start dieser Funktion ausgefuert
    * danach nur erneut, wenn die Menu Funktion verlassen wurde
    * wenn keine Variablen initialisiert werden müssen, kann diese
    * Funktion anstatt mit if(!CTR_init()) ....     mit
    * CTR_init();  aufgerufen werden    
    */  
   if(!LCDML.FuncInit())
   {    
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print(F("LCD Helligkeit :"));
   }
   
   /* --------- LOOP ----------
    * Hier wird nur ein Ereignis ausgelöst, sobald ein Button gedrückt
    * wurde. Die Funktion CTR_check_button liefert true, wenn ein Button
    * seit dem letztem durchlauf betätigt wurde, ansonsten false.    
    */
   for (int i=0;i<=(brightness_index*2)-1; i++){
        lcd.setCursor(i,1);
        lcd.write(B11111111);  
     }
   lcd.setCursor(12,1);
   lcd.print(brightness_levels[brightness_index]*100/255);
   lcd.print("%");
     
   if (LCDML.checkButtons()) {      
     if (LCDML.g_button_left >= 1 && brightness_index > 0 && brightness_index <=6) //fadeOut
     {      
        LCDML.g_button_left=0;
        brightness_index-1;          
     }
     else if (LCDML.g_button_right >= 1 && brightness_index < 6 && brightness_index >=0)  //fadeIn
     {
        LCDML.g_button_right=0;      
        brightness_index+1;
     }
     
     analogWrite(_PIN_BACKLIGHT, brightness_levels[brightness_index]);
   }    
   
   /* --------- STOP  ---------      
    * CTR_func_end (direct, enter, up, down, left, right)
    * Fall in dieser Funktion keine Variablen zurückgesetzt werden
    * müssen, kann diese Funktion auch vereinfacht mit CTR_end(0, 1, 1, 1, 1, 1);
    * aufgerufen werden. Die Endbedingungen müssen durch die Zahlen >0 vorgegeben
    * werden
    * Wenn alles 0 ist, hängt das gesammte Programm in dieser Funktion fest
    */
   if(LCDML.FuncEnd(0, 1, 0, 0, 0, 0))
   {
     /* Falls noch Variablen zurückgesetzt werden müssen, bevor diese Funktion
      * verlassen wird, kann dies in dieser If Schleife geschehen
      */
   }      
 }


Leider funktioniert das noch nicht so wie ich mir das vorstelle. Wo genau in Deinem Code hast Du denn diesen Teil hier untergebracht:

Code: [Select]

//LCD Hintergrundbeleuchtung
  #define _PIN_BACKLIGHT 10
  unsigned char brightness_levels[7] = { 0, 20, 50, 90, 130, 190, 255 };
  unsigned char brightness_index;


Bei mir steht der in einem Tab der nur die LCD Steuerung übernimmt. Das scheint an dieser STelle aber nicht zu funktionieren. Ich bastel noch ein wenig. Werd schon ne Lösung finden.

Go Up