I2C LCD Display Menu+ unter Menu

Servus, ich mache gerade ein Projekt für die Schule, und ich komme beim Untermenüs machen nicht mehr weiter. Bis jetzt habe ich ein normales Menü erstellt bei dem man Hoch und Runter gehen kann plus Enter drücken kann. Dann kommt man in ein Untermenü, welches aber nach einer gewissen Zeit wieder zurück geht, da ich noch kein Backbuttonprogrammiert habe.
Wie es aussehen sollte:
-Backbutton so programmieren, dass ich aus dem Untermenü in das Main Menü zurück komme
-Untermenü so programmieren, dass ich die hoch und Runter Buttons auch da benutzten kann
-dass ich die verschiedenen Menüpunkte auch auswählen kann, da dann Aktionen wie eine Led. soll angehen auch programmieren will.

Bin neu:) bitte um Hilfe.

LG Felix

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 4);

int upButton = 35;
int downButton = 39;
int selectButton = 30;
int backButton = 32;
int menu = 1;
int LedOut1 = 29;
int LedOut2 = 28;
int LedOut3 = 27;
int LedOut4 = 26;
int Timer = 25;
int Timer_1 = 24;
int Timer2 = 23;
int Timer3 = 22;



void setup() {
  lcd.init();
  lcd.backlight();
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  pinMode(backButton, INPUT_PULLUP);
  pinMode(LedOut1, OUTPUT);
  pinMode(LedOut2, OUTPUT);
  pinMode(LedOut3, OUTPUT);
  pinMode(LedOut4, OUTPUT);

  updateMenu();
}

void loop() {
  if (!digitalRead(downButton)) {
    menu++;
    updateMenu();
    delay(100);
    while (!digitalRead(downButton))
      ;
  }
  if (!digitalRead(upButton)) {
    menu--;
    updateMenu();
    delay(100);
    while (!digitalRead(upButton))
      ;
  }
  if (!digitalRead(selectButton)) {
    executeAction();
    updateMenu();
    delay(100);
    while (!digitalRead(selectButton))
      ;
  }
  if (!digitalRead(backButton)) {
    executeAction();
      //Back-Button programmieren, so dass man ein Untermenü hat und da auch wieder raus kommt + einstellen dass man den beim normalen menü benutzten kann, aber es einfach wieder an anfang springt.
  updateMenu();
  delay(100);
  while (!digitalRead(backButton))
    ;
}
}
void updateMenu() {
  switch (menu) {
    case 0:
      menu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.print(">Solarenergie");
      lcd.setCursor(0, 1);
      lcd.print(" Windenergie");
      lcd.setCursor(0, 2);
      lcd.print(" Garagentor");
      lcd.setCursor(0, 3);
      lcd.print(" Luftqualitaet");
      break;
    case 2:
      lcd.clear();
      lcd.print(" Solarenergie");
      lcd.setCursor(0, 1);
      lcd.print(">Windenergie");
      lcd.setCursor(0, 2);
      lcd.print(" Garagentor");
      lcd.setCursor(0, 3);
      lcd.print(" Luftqualitaet");
      break;
    case 3:
      lcd.clear();
      lcd.print(" Solarenergie");
      lcd.setCursor(0, 1);
      lcd.print(" Windenergie");
      lcd.setCursor(0, 2);
      lcd.print(">Garagentor");
      lcd.setCursor(0, 3);
      lcd.print(" Luftqualitaet");
      break;
    case 4:
      lcd.clear();
      lcd.print(" Solarenergie");
      lcd.setCursor(0, 1);
      lcd.print(" Windenergie");
      lcd.setCursor(0, 2);
      lcd.print(" Garagentor");
      lcd.setCursor(0, 3);
      lcd.print(">Luftqualitaet");
      break;
    case 5:
      lcd.clear();
      lcd.print(">Strassenlaternen");
      lcd.setCursor(0, 1);
      lcd.print(" LED Haus");
      lcd.setCursor(0, 2);
      lcd.print(" Ampel");
      lcd.setCursor(0, 3);
      lcd.print(" Akkustand");
      break;
    case 6:
      lcd.clear();
      lcd.print(" Strassenlaternen");
      lcd.setCursor(0, 1);
      lcd.print(">LED Haus");
      lcd.setCursor(0, 2);
      lcd.print(" Ampel");
      lcd.setCursor(0, 3);
      lcd.print(" Akkustand");
      break;
    case 7:
      lcd.clear();
      lcd.print(" Strassenlaternen");
      lcd.setCursor(0, 1);
      lcd.print(" LED Haus");
      lcd.setCursor(0, 2);
      lcd.print(">Ampel");
      lcd.setCursor(0, 3);
      lcd.print(" Akkustand");
      break;
    case 8:
      lcd.clear();
      lcd.print(" Strassenlaternen");
      lcd.setCursor(0, 1);
      lcd.print(" LED Haus");
      lcd.setCursor(0, 2);
      lcd.print(" Ampel");
      lcd.setCursor(0, 3);
      lcd.print(">Akkustand");
    case 9:
      menu = 8;
      break;
  }
}

void executeAction() {
  switch (menu) {
    case 1:
      action1();
      break;

    case 2:
      action2();
      break;
    case 3:
      action3();
      break;
    case 4:
      action4();
      break;
    case 5:
      action5();
      break;
    case 6:
      action6();
      break;
    case 7:
      action7();
      break;
    case 8:
      action8();
      break;
  }
}

void action1() {
  lcd.clear();
  lcd.print(">Stromstaerke");
  lcd.setCursor(0, 1);
  lcd.print(" Spannung");
  lcd.clear();
  lcd.print(" Stromstaerke");  //aus Main-Board2.0 die Spannungs und Strommesser hier hineinfügen
  lcd.setCursor(0, 1);
  lcd.print(">Spannung");
  
    //ist wahrscheinlich wie lange das Bild angezigt werden soll, bevor es wieder ins Menü zurück geht
}
void action2() {
  lcd.clear();
  lcd.print(">Stromstaerke");
  lcd.setCursor(0, 1);
  lcd.print(" Spannung");
  lcd.clear();
  lcd.print(" Stromstaerke");
  lcd.setCursor(0, 1);  //aus Main-Board2.0 die Spannungs und Strommesser hier hineinfügen
  lcd.print(">Spannung");
  Timer++;
  if (Timer == 10) {
    Timer = 0;
  }
  delay(1500);
}
void action3() {
  lcd.clear();
  lcd.print(">oeffnen");
  lcd.setCursor(0, 1);
  lcd.print(" schließen");
  lcd.clear();
  lcd.print(" oeffnen");
  lcd.setCursor(0, 1);  //Servo Motor anschauen, verstehen und Programmieren, new sketch first
  lcd.print(">schließen");
  Timer++;
  if (Timer == 10) {
    Timer = 0;
  }
  delay(1500);
}
void action4() {
  lcd.clear();
  // Sensorwert = analogRead(0);
  //Sensorwert = (sensorwert / 6);
  Serial.println("Luftqualitaet : ");
  //Serial.println(Sensorwert, DEC);  //schauen obs funktionier mit seriel.print wenn nicht nochmal im Main-board2.0 nachschauen
  //Serial.println();
  Timer++;
  if (Timer == 10) {
    Timer = 0;
  }
  delay(1500);
}
void action5() {
  lcd.clear();
  lcd.print(">LED's an");
  lcd.setCursor(0, 1);
  lcd.print(" LED's aus");
  lcd.clear();
  lcd.print(" LED's an");
  lcd.setCursor(0, 1);
  lcd.print(">LED's aus");
  Timer++;  //oder wenn der LDR anschlägt dass es dunkel wird (Parallelgteschalten)
  if (Timer == 10) {
    Timer = 0;
  }
  delay(1500);
}
void action6() {
  lcd.clear();
  lcd.print(">LED's an");
  lcd.setCursor(0, 1);
  lcd.print(" LED's aus");
  lcd.clear();
  lcd.print(" LED's an");
  lcd.setCursor(0, 1);
  lcd.print(">LED's aus");  //oder wenn der LDR anschlägt dass es dunkel wird (Parallelgteschalten)
  Timer++;
  if (Timer == 10) {
    Timer = 0;
  }
  delay(1500);
}
void action7() {
  lcd.clear();
  lcd.print("Akkustand: ");
  lcd.setCursor(0, 1);
  if (Timer == 10) {  //Akkustand in Prozent anzeigen lassen, Wahrscheinlich über seriel.print etc.
    Timer = 0;
  }
  delay(1500);
}
void action8() {
  lcd.clear();
  lcd.print("Akkustand: ");
  lcd.setCursor(0, 1);
  if (Timer == 10) {  //Akkustand in Prozent anzeigen lassen, Wahrscheinlich über seriel.print etc.
    Timer = 0;
  }
  delay(1500);
}
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 4);

const int upButton = 35;
const int downButton = 39;
const int selectButton = 30;
//const int backButton = 32;
byte menu = 1;
byte line = 1;
const byte LedOut[] = {29, 28, 27, 26};
uint32_t Timer;

void setup() {
  lcd.init();
  lcd.backlight();
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  //pinMode(backButton, INPUT_PULLUP);
  pinMode(LedOut[0], OUTPUT);
  pinMode(LedOut[1], OUTPUT);
  pinMode(LedOut[2], OUTPUT);
  pinMode(LedOut[3], OUTPUT);

  menu1();
  lcd.print(">");
}

void loop() {
  if (!digitalRead(downButton)) {
    if (line < 4) {
      lcd.setCursor(0, line - 1);
      lcd.print(" ");
      line++;
      lcd.setCursor(0, line - 1);
      lcd.print(">");
    }
    delay(100);
    while (!digitalRead(downButton));
  }
  if (!digitalRead(upButton)) {
    if (line > 1) {
      lcd.setCursor(0, line - 1);
      lcd.print(" ");
      line--;
      lcd.setCursor(0, line - 1);
      lcd.print(">");
    }
    delay(100);
    while (!digitalRead(upButton));
  }
  if (!digitalRead(selectButton)) {

    if (menu == 1)menu2();
    else menu1();
    line = 1;
    delay(100);
    while (!digitalRead(selectButton));
  }
  if (Timer > 0)if (millis() - Timer >= 10000)menu1();
}

void menu1() {
  menu = 1;
  line = 1;
  Timer = 0;
  lcd.clear();
  lcd.print(F(">Solarenergie"));
  lcd.setCursor(1, 1);
  lcd.print(F("Windenergie"));
  lcd.setCursor(1, 2);
  lcd.print(F("Garagentor"));
  lcd.setCursor(1, 3);
  lcd.print(F("Luftqualitaet"));
}
void menu2() {
  menu = 2;
  line = 1;
  Timer = millis();
  lcd.clear();
  lcd.print(F(">Strassenlaternen"));
  lcd.setCursor(1, 1);
  lcd.print(F("LED Haus"));
  lcd.setCursor(1, 2);
  lcd.print(F("Ampel"));
  lcd.setCursor(1, 3);
  lcd.print(F("Akkustand"));
}

fügst einzelne Aktionen selbst hinzu

Danke für die schnelle Antwort!

Aktuell sind Code und Daten (die Menustruktur) ziemlich miteinander verwoben. Ich würde das trennen.

Für die Darstellung der Menustruktur könnte man structs verwenden. (Genaue Syntax und Datentypenmusst du mal rausfinden)

struct MenuItem{
  String titel;
  Function action;
  Pointer parameter;
};

struct Menu{
  Uint countItems;
  MenuItem items[];
};

Die Daten könnte man das in etwas so schreiben:

Menu menuSolar = {
  2,
  {
    {"Stromstaerke", showValue, &solarAmp},
    {"Spannung", showValue, &solarVoltage}
  }
};

Menu menuRoot = {
  8,
  {
    {"Solarenergie", enterSubmenu, &menuSolar},
    {"Windenergie", enterSubmenu, &menuWind},
    {"Garagentor", enterSubmenu, &menuGarage},
    {"Luftqualitaet", enterSubmenu, &menuLuft},
    {"Strassenlaternen", enterSubmenu, &menuLaternen},
    {"LED Haus", enterSubmenu, &menuHaus},
    {"Ampel", enterSubmenu, &menuAmpel},
    {"Akkustand", enterSubmenu, &menuAkku}
  }
};

Menu* currentMenu = menuRoot;
Uint currentMenuItemIndex = 0;

Um wieder eine Menuebene zurück zu kommen, könnte man die bisherigen Ebenen in einem Array speichern. Die Struktur dazu könnte so aussehen:

struct HistoryItem{
  Uint itemIndex;
  Menu* menu;
};

Uint historyMaxItems = 5;
struct History{
  Uint numberItems;
  HistoryItem items[historyMaxItems];
};

Oke, aber wie erstelle ich ein Untermenü? Also wenn ich z.B. "Solarenergie" auswähle, dass ich dann in ein neues Menü rein komme?

Zur Orientierung oder um es zu nutzen: Das Menü von Jomelo.

Gruß Tommy

  if (!digitalRead(selectButton)) {
    if(menu<10){
      menu = menu * 10 + line;
      line = 1;
      delay(100);
      while (!digitalRead(selectButton));
      subMenu(menu);
    } else goToAction(menu+line);
  }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.