Durch Tastendruck im Menü springen

Hallo,

ich habe gerade eine Aquariumbeleuchtung und habe mich an diese Vorlage gehalten:
http://vascoferraz.com/projects/aquarium-pwm-led-v1/

Ich würde das Menü gern etwas komplexer aufbauen und mehr Einstellungsmöglichkeiten (max. Helligkeit der RGB, Farbe des Mondes etc) und habe das auch schon hinbekommen.

Es wird hier allerdings ein “Durchklick-Menü” genommen, dass bei zu vielen Einstellungen dann auch zu lang wird.

Meine Idee war deshalb, verschiedene Taster zu nutzen (z.B. einen für Uhrzeiteinstellung, einen für Sonnenaufgang, einen für Lichtfarbe)

Das “Menü” ist folgendermaßen aufgebaut.

void loop () 
{
  
  while (ClockModeState == 0)
  { 
    
    PrintTimeOnLCD();
    PrintDateOnLCD();
    PrintWeekDayOnLCD();
    PrintTemperatureOnLCD();
    PrintCopyrightOnLCD();
    ReadTime();
    
    
    if(!Serial.available())
    {
     Serial.println(operationMode);
     switch(operationMode)
     {
      case 0: LED_PWM(); break; 
      case 1: LED_PWM_Debug(); break;            
      default: LED_PWM(); break;
     }
    }
    
    if(Serial.available())
    {
     operationMode = Serial.parseInt(); // read a number from the serial port to set the operation mode
     switch(operationMode)
     {
      case 0: LED_PWM(); break; 
      case 1: LED_PWM_Debug(); break;            
      default: LED_PWM(); break;
     }
    }
   
    PrintBrightnessOnLCD(); 
                   
    SwitchClockMode (1);
  }
  
  while (ClockModeState == 1)
  {
    SetHour();
  }
  
  while (ClockModeState == 2)
  {
    SetMinute();
  }
 
  while (ClockModeState == 3)
  {
    SetSecond();
  }
 
  while (ClockModeState == 4)
  {
    SetDay();
  }
  
  while (ClockModeState == 5)
  {
    SetMonth();
  }
  
  while (ClockModeState == 6)
  {
    SetYear();
  }
  
  while (ClockModeState == 7)
  {
    SetPresunrise();
  }
  
  while (ClockModeState == 8)
  {
    SetSunrise();
  }
  
  while (ClockModeState == 9)
  {
    SetSunset();
  }
  
}

“SwitchClockMode” klickt sich dann also durch die einzelnen voids durch und sieht so aus:

void SwitchClockMode (unsigned char x)
{
 if (analogRead(ClockMode) >= 1004)
    { ClockModeFlag = 1; }
 
 if (analogRead(ClockMode) <= 20 && ClockModeFlag == 1)
    { ClockModeFlag=0; gotomain=0; lcd.clear(); ClockModeState=x; k=0; } 
}

Was ich gern möchte, ist, dass ich das Menü erweitere (ich habe mitlerweile nicht mehr nur 9 sondern schon 13), ich aber mit einem neuen Taster nicht bei 1 anfange, sondern bei 7 oder 10, dass ich also mitten in das Menü springe.

Ich habe die “SwitchClockMode” kopiert als “SwitchLightMode” wieder eingefügt und überarbeitet, aber es funktioniert nicht. Habt ihr eine Idee woran das liegen könnte?

Du hast etwas falsch gemacht, bzw. wie sollen wir eine Idee haben, wenn du uns deine Version nicht zeigst.

Hey, da hast du sicherlich recht. Ich kann aber nichts vorweisen, weil ich es verworfen habe bzw. es wieder gelscöht habe, da es nicht ging und ich genug probiert hatte. Ich versuche es aber mal, aus dem Kopf zu erstellen. Ich habe im Prinzip nichts anderes gemacht, als den Aufbau des aktuellen Skripts zu kopieren und auf den neuen taster anzupassen…

Ich habe mir erst mal ein void geschrieben, um den neuen Taster zu lesen, diesen habe ich anfangs so definiert:

const int SetupMode = 3;          // Pushbutton to switch between modes

So sieht das Void aus:

void SwitchSetupMode (unsigned char x)
{
 if (analogRead(SetupMode) >= 1004)
    { ClockModeFlag = 10; }
 
 if (analogRead(SetupMode) <= 20 && ClockModeFlag == 1)
    { ClockModeFlag=0; gotomain=0; lcd.clear(); ClockModeState=x; k=0; }
}

Ich hatte gedacht, dass ich damit nicht um einen erhöhe, sondern im Wert gleich bei 10 raus komme…
Das hätte noch im Menü-Teil gemacht…

void loop ()
{
 
  while (ClockModeState == 0)
  {
   
    PrintTimeOnLCD();
    PrintDateOnLCD();
    PrintWeekDayOnLCD();
    PrintTemperatureOnLCD();
    PrintCopyrightOnLCD();
    ReadTime();
   
   
    if(!Serial.available())
    {
     Serial.println(operationMode);
     switch(operationMode)
     {
      case 0: LED_PWM(); break;
      case 1: LED_PWM_Debug(); break;           
      default: LED_PWM(); break;
     }
    }
   
    if(Serial.available())
    {
     operationMode = Serial.parseInt(); // read a number from the serial port to set the operation mode
     switch(operationMode)
     {
      case 0: LED_PWM(); break;
      case 1: LED_PWM_Debug(); break;           
      default: LED_PWM(); break;
     }
    }
   
    PrintBrightnessOnLCD();
    SwitchSetupMode (1);               
    SwitchClockMode (1);
  }
 
  while (ClockModeState == 1)
  {
    SetHour();
  }
 
  while (ClockModeState == 2)
  {
    SetMinute();
  }
 
  while (ClockModeState == 3)
  {
    SetSecond();
  }
 
  while (ClockModeState == 4)
  {
    SetDay();
  }
 
  while (ClockModeState == 5)
  {
    SetMonth();
  }
 
  while (ClockModeState == 6)
  {
    SetYear();
  }
 
  while (ClockModeState == 7)
  {
    SetPresunrise();
  }
 
  while (ClockModeState == 8)
  {
    SetSunrise();
  }
 
  while (ClockModeState == 9)
  {
    SetSunset();
  }

  while (ClockModeState == 10)
  {
    SetRedMax();
  }
   while (ClockModeState == 11)
  {
    SetGreen Max();
  }
  while (ClockModeState == 12)
  {
    SetBlueMax();
  }
}

Ich meine, dass ichd as gemacht habe. ich bin absoluter Noob und fuchse mich gern darin, versuche Muster zu erkennen und zu verändern, aber wirklich Ahnung habe ich nicht.

Vlt. ein Kompromiss? Ich habe für das Setup eines Verkaufsautomaten mit Münzprüfer folgende Menü-Technik, zu bedienen mit einem Taster, umgesetzt:

  • langer Druck wechselt in den nächsten Menüpunkt
  • kurzer Druck permutiert die Möglichkeiten eines Menüpunktes durch

vorletzter Menüpunkt ist Exit ohne Speichern, letzter Menüpunkt ist Exit mit Speichern ...

lullaby:
Ich habe mir erst mal ein void geschrieben, um den neuen Taster zu lesen, diesen habe ich anfangs so definiert:

const int SetupMode = 3;          // Pushbutton to switch between modes

Das hat jetzt nicht direkt was mit dem Problem zu tun, aber “SetupMode” als Namen für eine Pinnummer zu verwenden ist denkbar schlecht. Nenne sie lieber “modeSelectPin” (kleiner Angangsbuchstabe für Variablen), o.Ä. Des Weiteren schreibt man kein “void”. Du hast eine Funktion hinzugefügt, die nichts (void) zurückgibt. An und für sich hast du aber gute Namen für deine Funktionen gewählt, das sieht man auch nicht oft.

lullaby:
So sieht das Void aus:

void SwitchSetupMode (unsigned char x)

{
if (analogRead(SetupMode) >= 1004)
    { ClockModeFlag = 10; }

if (analogRead(SetupMode) <= 20 && ClockModeFlag == 1)
    { ClockModeFlag=0; gotomain=0; lcd.clear(); ClockModeState=x; k=0; }
}

analogRead gibt Werte zwischen 0 und 1023 zurück, dein erster if-block wird also nie ausgeführt (hab mich verlesen). Warum benutzt die einen analogen Pin zum Auslesen eines diskreten Bauelements (Taster kennt nur an und aus)?

lullaby:

// ...

while (ClockModeState == 1)
  {
    SetHour();
  }
//…

Ich kenne die Funktion ‘SetHour’ nicht, aber wenn diese nicht die Variable ClockModeState ändert, dann hängst du da für immer fest.

Da du selbst sagst, dass dein Menü noch erweitert werden soll, wäre es vielleicht Zeit mal über ein vernünftiges Menüsystem nachzudenken. Mach dir Gedanken über die logischen Abläufe in deinem System und halte logisch abgeschlossene Vorgänge getrennt (Button Zustand auslesen, Menü ändern, Aquariumzubehör steuern, etc.).

Hey,

danke erst mal für die vielen netten ANtworten, auch wenn sie das Problem nicht lösen.

Ich habe, wie gesagt, keine Ahnung vom Programmieren, sondern habe mich da wirklich nur reingefuchst und durch autodidaktisches Vorgehen etwas Wissen erworben.

Vielleicht habt ihr recht und ich sollte wirklich ein richtiges Menü einbetten; das hatte ich über eine library bei einem anderem Projekt schon mal gemacht und das macht es auch einfacher.

Der Vorschlag mit dem langen und kurzen Drücken ist prinzipiell gut, allerdings wäre das nicht meine Wahl zu Menüsteuerung. Bisher habe ich zwei Buttons, aber vielleicht sollte ich sowas wie links, rechts, bestätigen und zurück einbauen.

Vielen Dank auch für die Tipps zum allgemeinem Vorgehen und zum benennen!

Wie wärs dann mit einer Variable Clockmodestate_n für alle n Taster die du verwenden möchtest? Dann musst du nicht mit dem einen auf 10 springen und mit dem anderen dafür nur bis 10 oder so. Das klingt etwas nach übers Knie gebrochen.

lullaby:
Hey, da hast du sicherlich recht. Ich kann aber nichts vorweisen, weil ich es verworfen habe bzw. es wieder gelscöht habe, da es nicht ging und ich genug probiert hatte.

Nie einfach ein Sketch löschen, weil es nicht auf anhieb läuft; und genug probieren kann man gar nicht! :wink:

lullaby:
Ich meine, dass ichd as gemacht habe. ich bin absoluter Noob und fuchse mich gern darin, versuche Muster zu erkennen und zu verändern, aber wirklich Ahnung habe ich nicht.

Auch wenn es anfangs frustrierend ist und es nicht so will, wie du, nicht aufgeben. Learning by doing und testen, Werte verändern und schauen was passiert und was nicht. Gegen keine Ahnung helfen Tuturials und google, gerne auch hier im Forum... :wink:

Hier findest du ein sehr schönes Menü, welches du für deine Erfordernisse anpassen kannst.
Ich bin mir aber nicht sicher, ob du mit deinen Kenntnissen damit klar kommst.