mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD Menü Struktur Navigation


Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt ja schon einige Beiträge hier die sich mit LCD Menü 
beschäftigen.
Dank dieser konnte ich mir eine ungefähre Struktur zurechtbasteln.

Jetzt wollte ich fragen wie ihr eure Menüs so designed habt.
Wie erfolgt die Auswahl?

Ich habe eine 16x2 LCD zur Verfügung.
Da es ja nun nicht Sinnvoll ist immer nur einen Eintrag anzuzeigen und 
die zweite Zeile dann leer bleibt, dachte ich mir man könnte das ganze 
mittels eines Cursors am linken Rand des Displays selektieren und mit 
einer Taste Auswählen. Das Menü scrollt dann mit dem Cursor nach oben 
oder unten mit.

Oder wie würdet ihr das gestalten?

Autor: Ganymed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann auch einen Inkrementalen
Drehgeber nehmen. Durch Rechts-
oder Linksdehen wird das Menu herauf-
herunter gezählt.

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau so ....

oder anders ;o)

Also, das hängt ja auch von der Applikation ab. Wenn es Sinn macht auch 
während der Menü-Auswahl Status-Information auszugeben (z.B. 
Betriebsspannung .. Stromverbrauch .. irgendwelche Sensor Messwerte ... 
weiß der Geier), dann kann es natürlich auch mehr Sinn machen nur eine 
Zeile für das Menü zu benutzen und die andere für diese Informationen 
frei zu halten. Dann wiederum fände ich es persönlich schöner, wenn das 
Menü nach rechts und links scrollt. Die andere Frage ist dann, ob sich 
die Mühe auch lohnt.

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Genau so ....
>
> oder anders ;o)
>
> Also, das hängt ja auch von der Applikation ab. Wenn es Sinn macht auch
> während der Menü-Auswahl Status-Information auszugeben (z.B.
> Betriebsspannung .. Stromverbrauch .. irgendwelche Sensor Messwerte ...
> weiß der Geier), dann kann es natürlich auch mehr Sinn machen nur eine
> Zeile für das Menü zu benutzen und die andere für diese Informationen
> frei zu halten. Dann wiederum fände ich es persönlich schöner, wenn das
> Menü nach rechts und links scrollt. Die andere Frage ist dann, ob sich
> die Mühe auch lohnt.

Drehencoder ist für diese Zwecke oversized.
Es handelt sich grad mal um max 4 Menüeinstellungen die jeweils als 
einen Untermenüpunkt haben sollen.

Links/rechts wäre natürlich auch schön. Und in der oberen Zeile wird 
dann der Übergeordnete Menüpunkt angezeigt.

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Phantasie sind keine Grenzen gesetzt ....
man kann auch die übergeordneten Menüpunkte als Grafik am Rand 
darstellen ;o) Gibt ja schließlich 8 user defined characters.

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mir jetzt mal etwas gebastelt:
#define MENU_SIZE    (sizeof(menu_text) / sizeof(*menu_text))

// LCD-Menüeinträge definieren
// ===========================
const char Menu_0[] PROGMEM = "** Hauptmenu ** 1\n";
const char Menu_1[] PROGMEM = "Tastenzuordnung ";
const char Menu_2[] PROGMEM = "Dauerfeuer      ";
const char Menu_3[] PROGMEM = "Konfiguration   ";
const char Menu_4[] PROGMEM = "Speichern       ";
const char Menu_5[] PROGMEM = "Beenden         ";


// Tabelle von Zeigern auf die Texte erstellen
// ===========================================
const char *menu_text[] PROGMEM =
{
  Menu_0,
  Menu_1,
  Menu_2,
  Menu_3,
  Menu_4,
  Menu_5
};

volatile uint8_t MenuOnScreen = 1;
volatile uint8_t menu_index = 1;

int main(void)
{
  init();                            // Einschaltsequenz starten
  sei();                            // Interrupts aktivieren

  while(1)
  {

    if(get_key_short(1<<KEY0) && Summe == 0)        // kurzer Tastendruck (PinB.6)
    {
      MenuOnScreen = 1 - MenuOnScreen;            // LCD-Hauptmenü anzeigen
      lcd_clrscr();
      lcd_puts ((const char*) pgm_read_word(&menu_text[0]));
    }      
      
    if(MenuOnScreen)
    {
      if(get_key_short(1<<KEY0))              // kurzer Tastendruck (PinB.6)
      {
        if(menu_index < MENU_SIZE - 2)
        menu_index++;
      }

      if(get_key_short(1<<KEY1))              // kurzer Tastendruck (PinB.7)
      {
        if(menu_index > 1)
        menu_index--;
      }

      if(get_key_long(1<<KEY0))              // langer Tastendruck (PinB.6)
      {
        eeprom_write_byte(00, nKonfig);          // Wert in EEPROM speichern
      }

      lcd_puts ((const char*) pgm_read_word(&menu_text[menu_index]));

    }
    else
    {

....

(noch nicht getestet obs funktioniert)

jetzt hätte ich mir vorgestellt am Anfang bzw. Ende des Textes einen < 
oder > anzuzeigen wenn das Menü noch weiter geht.

Soll ich das am besten gleich in die Textvariable schreiben oder als 
zusätzliche String zum Text anfügen?

Wie mach ich das am besten?

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hänge hier:
lcd_puts_P (menu_text[menu_index]);

Invalid initializer

Was stimmt da nicht?
Laut Anleitung müßte der Befehl die Werte aus dem Speicher auslesen 
können

Autor: Chris M. (shortie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
weil der Code eine nette Menüfunktion implementiert hat habe ich den mir 
als Bookmark vor längerer Zeit mal gespeichert. Allerdings bislang nicht 
getestet, aber vielleicht ist er für dich hilfreich.

http://www.paddy-ol.de/index.php?option=com_conten...

Autor: Patrick W. (paddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Chris M.

Danke, den Link hätte ich jetzt auch gepostet, denn das ist meine eigene 
Homepage. Freut mich, dass auch jemand das Zeugs liest was ich auf die 
Homepage stelle.

Der Code ist nicht besonders optimiert, aber zumindest lauffähig. Für 
Diskussion und Verbesserung bin ich immer offen, auch wenn ich aktuell 
wenig Zeit habe für die Atmels wegen den Klausuren.

Gruß Paddy

Autor: 2ZeilenLCD (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Manfred,

genau so ein Menü habe ich auch auf einem 2x16 Display von DOGM 
aufgesetzt.

Per Drehencoder wird vertikal durch das Menü gesteuert.
Mit OK wechselt man in den Menü Punkt als geht eine Ebene tiefer.
Mit BACK kann man in der Menü Hierachie wieder eine Ebene aufsteigen.
Mittels LEFT und RIGHT kann innerhalb eines Eingabescreens (z.b. 
Frequenz Eingabe für PWM) die Dezimalstelle ausgewählt werden, ansonsten 
kann auch hier der Wert per Drehencoder inkrementiert / dekrementiert 
werden...

Eigentlich hätte man auf LEFT / RIGHT auch verzichten können...
auch die OK Taste ist unnötig, weil der Drehencoder selbst auch als 
Taster dient... bzw. dieser hat bei Druck eine Tasterleitung zum uC...

Ahja, ein Video zu dem Menü findest du hier:
Youtube-Video "LCD Menu controlled by rotating encoder"

Ich muss allerdings zugeben, dass ich hier leider nichts kommentiert 
habe und die Qualtität auch nicht so der Hit ist, aber zumindest das 
Prinzip wird klar ;-)

Kurz zu dem was ich da auf dem Video mache (vermutlich erkennt man es 
nicht):

1. Zunächst navigiere ich durchs Menü, wähle PWM1 und stelle dort eine 
Frequenz von 900 Hz ein.

2. Ich wähle einen RECORD Modus, bei dem ich am Analog Eingang eine 
Spannung sample... ich drehe zur Stimulation des Analogeingang ein paar 
mal wirklich an einem Poti ;-)

3. Danach spiele ich die aufgenommene Sequenz am Analogausgang wieder 
ab... am Oszi sieht man dann den Verlauf, den ich zuvor per Stimulation 
aufgenommen habe...

4. Ich wechsle in den Menüpunkt System --> Beleuchtung und verstelle die 
Display Helligkeit ;-) Kleine Spielerei, die Helligkeit ist per PWM 
geregelt (und einer KSQ)... hier wird eigentlich nur der Tastgrad von 0% 
- 100 % verändert...

viele Grüße

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grüß dich!

Über dieses Video bin ich vor einigen Tagen gestolpert.
Sieht sehr professionell aus das ganze.

Das mit dem Encoder ist eine feine Sache, aber wie gesagt für meine 
Zwecke etwas unpraktisch.

Im Prinzip reichen mir 2 Tasten.

Wird eine der tasten länger gedrückt gelangt man ins Menü. Wo man dann 
mittels links/rechts durch die Menüpunkte navigiert.
Oder dort wird mit einem längerem Tastendruck ins Untermenü gewechselt 
wo ebenfalls wieder links/rechts - langer tastendruck die Option gewählt 
wird.

Über "Beenden" kommt man dann wieder aus dem Menü.

Ich freunde mich gerade mit den LCD Funktionen von Volker Oth's an: 
http://homepage.hispeed.ch/peterfleury/group__pfle...

Ich hänge momentan nur bei der lcd_puts_p Funktion.

Wenn ich hier mit Variablen arbeiten möchte funktioniert das nicht so 
richtig:
lcd_puts_p (menu_text[menu_index]);

AVR Studio zeigt mir zwar keinen Fehler, allerdings bekomme ich nur 
kryptische Zeichen am Display.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ich hänge momentan nur bei der lcd_puts_p Funktion.

Kann lcd_puts_p Text aus dem Flash ausgeben?

MfG Spess

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Hi
>
>>Ich hänge momentan nur bei der lcd_puts_p Funktion.
>
> Kann lcd_puts_p Text aus dem Flash ausgeben?
>
> MfG Spess

Ja, genau dafür ist er gemacht:
void lcd_puts_p  (  const char *  progmem_s   )   
 
   Display string from program memory without auto linefeed. 


Parameters:
 s  string from program memory be be displayed  

Returns:
none 
See also:
lcd_puts_P  

Mit
lcd_puts_p (menu_text[0])
haut das auch wunderbar hin. Nur mit den Variablen nicht.

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab noch was herausgefunden:
Selbst so funtkioniert es nicht:
lcd_puts_p (menu_index);

Fehler:
../main.c:251: warning: passing argument 1 of 'lcd_puts' makes pointer 
from integer without a cast

Wenn ich das ganze ohne PROGMEM und mit dem "lcd_puts" mache gehts.

Seltsam...

Autor: lcdmenue (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann schnell eine lcd_puts_P  per copy und paste erstellen
die lcd_puts  kopieren umbenennen
in diese _P den eintrag pgm_read_byte ( ... )  an die richtige stelle 
setzen ... und trallala es geht


für LCDs  lassen sich prima strukturen machen
struct
{
 unsigned char level;
 char * text;
 void (*f_pointer)(void); // funktion die aufgerufen werden soll
}t_menu;


const char Menu_0[] PROGMEM = "** Hauptmenu ** 1\n";
const char Menu_1[] PROGMEM = "Tastenzuordnung ";
const char Menu_2[] PROGMEM = "Dauerfeuer      ";
const char Menu_3[] PROGMEM = "Konfiguration   ";
const char Menu_4[] PROGMEM = "Speichern       ";
const char Menu_5[] PROGMEM = "Beenden         ";


t_menu menu[] PROGMEM = {
{0 , Menu_0 , NULL }
  {1 , Menu_1 , funktion_für_naechste_ebene}, 
     {2 , Menu_1_unterpunkt1 , funktion_für_naechste_ebene}
        {3 , Menu_1_unterunterpunkt1 , foo }
        {3 , Menu_1_unterunterpunkt2 , foo}
     {2 , Menu_0_unterpunkt2 , NULL }
  {1 , Menu_2 , funktion_für_naechste_ebene},
     {2 , Menu_2_unterpunkt1 , foo}
     {2 , Menu_2_unterpunkt2 , foo}
  {1 , Menu_3 , foo },
  {1 , Menu_4 , foo },
  {1 , Menu_5 , foo }
}


da in dem menüarray nur pointer auf texte sind kann man da auch mit 
mehreren sprachen arbeiten
wer funktionen mit übergabewert will
baut sich die sturctur etwas um

void (*f_pointer) ( unsigned char wert);

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

die lcd_puts_p sieht so aus:
/*************************************************************************
Display string from program memory without auto linefeed 
Input:     string from program memory be be displayed                                        
Returns:   none
*************************************************************************/
void lcd_puts_p(const char *progmem_s)
/* print string from program memory on lcd (no auto linefeed) */
{
    register char c;

    while ( (c = pgm_read_byte(progmem_s++)) ) {
        lcd_putc(c);
    }

}/* lcd_puts_p */

sollte doch eigentlich passen oder?

lcd_puts sieht dagegen so aus:
void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
    register char c;

    while ( (c = *s++) ) {
        lcd_putc(c);
    }

}/* lcd_puts */

Wird bei deiner Struktur die Funtion für das entsprechende Menü sofort 
ausgeführt wenn es angewählt wird? Oder wie ist das angedacht?

Autor: Lokus Pokus (derschatten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
// LCD-Menüeinträge definieren
// ===========================
const char menu_000[] PROGMEM = " Multifunktions ";  // 0
const char menu_001[] PROGMEM = "ArcadeController";  // 1
const char menu_002[] PROGMEM = "** HAUPTMENUE **";  // 2
const char menu_100[] PROGMEM = "Tastenzuordnung>";  // 3
const char menu_101[] PROGMEM = "[X        ]    1";  // 4
const char menu_102[] PROGMEM = "[XX       ]    2";  // 5
const char menu_103[] PROGMEM = "[XXX      ]    3";  // 6
const char menu_104[] PROGMEM = "[XXXX     ]    4";  // 7
const char menu_105[] PROGMEM = "[XXXXX    ]    5";  // 8
const char menu_106[] PROGMEM = "[XXXXXX   ]    6";  // 9
const char menu_107[] PROGMEM = "[XXXXXXX  ]    7";  // 10
const char menu_108[] PROGMEM = "[XXXXXXXX ]    8";  // 11
const char menu_109[] PROGMEM = "[XXXXXXXXX]    9";  // 12
const char menu_200[] PROGMEM = "<Dauerfeuer    >";  // 13
const char menu_201[] PROGMEM = "[         ]    0";  // 14
const char menu_202[] PROGMEM = "[X        ]    1";  // 15
const char menu_203[] PROGMEM = "[XX       ]    2";  // 16
const char menu_204[] PROGMEM = "[XXX      ]    3";  // 17
const char menu_205[] PROGMEM = "[XXXX     ]    4";  // 18
const char menu_206[] PROGMEM = "[XXXXX    ]    5";  // 19
const char menu_207[] PROGMEM = "[XXXXXX   ]    6";  // 20
const char menu_208[] PROGMEM = "[XXXXXXX  ]    7";  // 21
const char menu_209[] PROGMEM = "[XXXXXXXX ]    8";  // 22
const char menu_210[] PROGMEM = "[XXXXXXXXX]    9";  // 23
const char menu_300[] PROGMEM = "<System        >";  // 24
const char menu_301[] PROGMEM = "LCD            >";  // 25
const char menu_302[] PROGMEM = "<LED-Test       ";  // 26
const char menu_400[] PROGMEM = "<Speichern     >";  // 27
const char menu_500[] PROGMEM = "<Beenden        ";  // 28


typedef struct def_menustruktur
{
  char *text;
  struct def_menustruktur* next;
  struct def_menustruktur* previous;
  struct def_menustruktur* sub;
  struct def_menustruktur* up;
  void (*funktion)(void);
}menustruktur;

void tastenzuordnung(void);
void dauerfeuer(void);
void lcd(void);
void led(void);
void speichern(void);
void beenden(void);

// Tabelle von Zeigern auf die Texte erstellen
// ===========================================
menustruktur menu[] PROGMEM =
{
   {menu_100, 13, 3, 4, 3, },
      {menu_101, 5, 4, 3, 3, tastenzuordnung},
      {menu_102, 6, 4, 3, 3, tastenzuordnung},
      {menu_103, 7, 5, 3, 3, tastenzuordnung},
      {menu_104, 8, 6, 3, 3, tastenzuordnung},
      {menu_105, 9, 7, 3, 3, tastenzuordnung},
      {menu_106, 10, 8, 3, 3, tastenzuordnung},
      {menu_107, 11, 9, 3, 3, tastenzuordnung},
      {menu_108, 12, 10, 3, 3, tastenzuordnung},
      {menu_109, 12, 11, 3, 3, tastenzuordnung},
  {menu_200, 24, 13, 14, 13, },
      {menu_201, 15, 14, 13, 13, dauerfeuer},
    {menu_202, 16, 14, 13, 13, dauerfeuer},
    {menu_203, 17, 15, 13, 13, dauerfeuer},
    {menu_204, 18, 16, 13, 13, dauerfeuer},
    {menu_205, 19, 17, 13, 13, dauerfeuer},
    {menu_206, 20, 18, 13, 13, dauerfeuer},
    {menu_207, 21, 19, 13, 13, dauerfeuer},
    {menu_208, 22, 20, 13, 13, dauerfeuer},
    {menu_209, 23, 21, 13, 13, dauerfeuer},
    {menu_210, 23, 22, 13, 13, dauerfeuer},
  {menu_300, 27, 24, 25, 24,},
    {menu_301, 26, 25, 24, 24, lcd},
    {menu_302, 26, 25, 24, 24, led},
  {menu_400, 28, 27, 27, 27, speichern},
  {menu_500, 28, 27, 28, 28, beenden}
};

Bräuchte mal hilfe.

../main.c:137: warning: initialization discards qualifiers from pointer 
target type
../main.c:137: warning: initialization makes pointer from integer 
without a cast

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.