/*
Forum: https://forum.arduino.cc/t/lcd-display-menu-in-einem-menu/1415656
Wokwi: https://wokwi.com/projects/448908967433771009
2025/11/29
ec2021
Das vorliegende Programm erlaubt das Erstellen von Menütexten und der Handhabung des Menüs mithilfe
eines Joysticks. Die vertikale angeordnete Y-Achse dient dem Scrollen innerhalb eines Menüs.
Die horizontale X-Achse bedient die in der zweiten Zeile des Displays angezeigten Aktionen:
"<Zurück" nach links, "Select>" nach rechts.
Mit dem simulierten Joystick-Knopf (Taster) kann man aus jedem Menü direkt ins Hauptmenü
zurückschalten.
Die Menüs und ihre Zusammenhänge sind in der Datei "LCDMenue.h" definiert und beschrieben.
Das bestehende Konzept ist durch Verwendung der Ziffern ('0' ... '9') auf maximal 10 Menüs beschränkt.
Bei Bedarf könnte das Programm auch beispielsweise um die Nutzung von Buchstaben erweitert werden.
Einfach lesbar ließen sich u.a. die Hex-Ziffern "A" .."F" verwenden, um insgesamt 16 Menüs zu erlauben.
Zur Information:
Zur Darstellung von Umlauten auf dem LCD-Display sind diese wie folgt zu codieren:
Für ü \365 Für ä \341 Für ö \357
Beispiel für "Zurück": "Zur\365ck"
*/
/*----------------------------------------------------------------------------
Im folgenden Teil sind bei Menü-Ergänzung keine Änderungen erforderlich
-----------------------------------------------------------------------------*/
#include <LiquidCrystal.h>
#include "LCDMenue.h"
//Definieren der Pins - Joystick
constexpr uint8_t PinY {A0};
constexpr uint8_t PinX {A1};
constexpr uint8_t PinSW {A2};
//Definieren der LCD-Pins - Display
constexpr uint8_t rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 6 ;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
//Werte von X, Y und SW - Joystick
constexpr int lowerLimit {100}; // Schaltschwelle für unten bzw. links
constexpr int upperLimit {900}; // Schaltschwelle für oben bzw. rechts
int ValueY = 0; //Hoch und Runter
int ValueX = 0; //Links und Rechts
uint8_t ValueSW = LOW;
uint8_t lastSW = HIGH;
int actMenu = 0;
int menuIndex = 0;
int lastIndex = -1;
char text[maxLen] = "-";
int prevMenu = -1;
int nextMenu = -1;
void setup()
{
Serial.begin(115200);
lcd.begin(16, 2);
lcd.clear();
pinMode(PinSW, INPUT_PULLUP);
}
void loop() {
joystick();
scrollen();
bestaetigen();
anzeigen();
}
void anzeigen() {
static int lastMenu = -1;
if (actMenu != lastMenu) {
lastMenu = actMenu;
menuIndex = 0;
lastIndex = -1;
}
if (menuIndex != lastIndex ) {
lastIndex = menuIndex;
lcd.clear();
prepareMenueText(actMenu, menuIndex);
lcd.setCursor(0, 0);
lcd.print(text);
lcd.setCursor(0, 1);
uint8_t mode = 0;
if (prevMenu >= 0) mode = 1;
if (nextMenu >= 0) mode += 2;
lcd.print(actionFromPROGMEM(mode));
}
}
void bestaetigen() {
static unsigned long lastOk = 0;
if (millis() - lastOk > updateInterval) {
lastOk = millis();
uint8_t mode = 0;
if (ValueX > lowerLimit) mode = 1;
if (ValueX >= upperLimit) mode = 2;
switch (mode) {
case 0:
if (prevMenu >= 0) actMenu = prevMenu;
break;
case 2:
if (nextMenu >= 0) actMenu = nextMenu;
break;
}
}
}
void scrollen() {
static unsigned long lastScroll = 0;
if (millis() - lastScroll > updateInterval) {
lastScroll = millis();
switch (ValueY) {
case 0 ... lowerLimit:
menuIndex++;
menuIndex = menuIndex % menueLen[actMenu];;
break;
case upperLimit ... 1023:
menuIndex--;
menuIndex = (menuIndex < 0) ? menueLen[actMenu] - 1 : menuIndex;
break;
}
}
}
char * actionFromPROGMEM(int index) {
static char buf[maxLen];
strcpy_P(buf, (char*)pgm_read_word(&(ac[index])));
return buf;
}
void copyMenuFromPROGMEM(char* const m[], int len, int index) {
if (index < len) {
char buf[maxLen];
strcpy_P(buf, (char*)pgm_read_word(&(m[index])));
prevMenu = value(buf[0]);
nextMenu = value(buf[1]);
strncpy(text, &buf[2], maxLen);
}
}
int value(char c) {
return (c >= '0' && c <= '9') ? int(c - '0') : -1; // Umrechnen von Zeichen zu Integer-Zahl
}
void joystick() {
//Einlesen der Werte von X und Y
ValueX = analogRead(PinX);
ValueY = analogRead(PinY);
ValueSW = digitalRead(PinSW);
if (ValueSW != lastSW) {
lastSW = ValueSW;
if (!ValueSW) {
actMenu = 0;
menuIndex = 0;
}
delay(50); //Simples Entprellen des Tasters
}
}