0

I know that menus were discussed perhaps a thousand times here and everywhere. But using a ready solution is not something that I'm looking for because I know I won't learn the concept if I use them. Hence the question.

I am trying to build a simple timer with a setup menu. The timer code works so that part of the code is not a problem. The menu is an adaption of a code I found online which I understand, and for the most part, works as long as I am in level 1. My menu will have 2 levels. the structure of the menu is something like this:

Option 1: Display Timer 1

Option 2: Display Timer 2

Option 3: Reset Timer 1

Option 4: Reset Timer 2

Option 5: Set Timer 1 Action Delay

  • Option 5.1: Delay01
  • Option 5.2: Delay02
  • Option 5.3: Delay03
  • Option 5.4: Back

Option 6: Set Timer 2 Action Delay

  • Option 6.1: Delay01
  • Option 6.2: Delay02
  • Option 6.3: Delay03
  • Option 6.4: Back

The menu will be displayed with an I2C 1602 LCD Screen, and navigation will be by way of 3 push buttons: Up, Down, and Select.

I am using a nested "switch case" statement to navigate between the menus.

So as long as I'm in level 1, everything works. the times are displayed, reset works, and all is well. The moment I go to a submenu, the first option in the submenu is selected immediately and the display shows the parent menu.

I am putting the menu code in a function, the submenu code in another function. Once the menu with a submenu is selected, it calls the submenu function.

My current code is as follows: [Note: Updated with a function to handle screen updates based on @jsotola]

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

#include <EEPROM.h>     //EEPROM Functions: EEPROM Module
#include <Arduino.h>    //EEPROM Functions: for type definitions

LiquidCrystal_I2C lcd(0x27,16,2);


//Globals:
int page_counter    =   1 ; //To move between pages
int page_counter_s  =   1;  //submenu

int up = 2;             //Up button
int down = 3;           //Down button
int selection = 4;      //Select button
int LED =   13;

int pageCount   =   7;  //Main Menu


//Main Menu 
boolean last_up         =   LOW;            
boolean last_down       =   LOW;
boolean last_select     =   LOW;

boolean current_up      =   LOW;  
boolean current_down    =   LOW;
boolean current_select  =   LOW;

boolean last_up_s     =   LOW;            
boolean last_down_s     =   LOW;

boolean current_up_s    =   LOW;  
boolean current_down_s  =   LOW;

String line1;
String line2;


//---- De-bouncing function for all buttons----//
boolean debounce(boolean last, int pin){
  boolean current = digitalRead(pin);
  if (last != current){
    delay(5);
    current = digitalRead(pin);
  }
  return current;
}

//LCD Function

void printlcd(){
    lcd.setCursor(0,0);
    lcd.print(line1);
    lcd.setCursor(0,1);
    lcd.print(line2);
}

//Menu Function
void Menus(){                                                                                                                                                                                                                                                                           

    current_up = debounce(last_up, up);         //Debounce for Up button
    current_down = debounce(last_down, down);   //Debounce for Down button
    current_select = debounce(last_select, selection); //Debounce for Select button
    //----Page counter function to move pages----//

        //Page Up
        if (last_up == LOW && current_up == HIGH){  //When up button is pressed
          lcd.clear();                     //When page is changed, lcd clear to print new page        

            if(page_counter < pageCount){             //Page counter never higher than 3(total of pages)
                page_counter= page_counter +1;   //Page up
            }
            else{
                page_counter = pageCount;  
            }
        }

        last_up = current_up;

        //Page Down
        if (last_down== LOW && current_down == HIGH){ //When down button is pressed
          lcd.clear();                     //When page is changed, lcd clear to print new page    
          if(page_counter >1){              //Page counter never lower than 1 (total of pages)
          page_counter= page_counter -1;   //Page down

          }
          else{
          page_counter= 1;  
         }
        }

        last_down = current_down;




//------- Switch function to write and show what you want---// 
  switch (page_counter) {


    case 1:{ //Each case is a menu option

      line1 = "Counter 01:";
      line2 = "100 Hrs";
      printlcd();
    }
    break;

    case 2:{ //Each case is a menu option
      line1 = "Counter 02:";
      line2 = "70 Hrs";
      printlcd();
    }
    break;

    case 3:{ //Each case is a menu option
      line1 = "Reset 01:";
      line2 = "";
      printlcd();

      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "Success!";
            line2 = "C01 Reset";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);

            delay(3000);
            lcd.clear();

        }
    }
    break;

    case 4:{ //Each case is a menu option
      line1 = "Reset 02:";
      line2 = "";
      printlcd();

      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "Success!";
            line2 = "C02 Reset";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);

            delay(3000);
            lcd.clear();

        }
    }
    break;


    case 5:{ //Each case is a menu option

        line1 = "Set 01";
        line2 = "Interval";
        printlcd();

      //Action:
        if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            submenu();
        }
    }
    break;

    case 6:{ //Each case is a menu option
        line1 = "Set 02";
        line2 = "Interval";
        printlcd();

      //Action:
        if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            submenu();
        }
    }

    case 7:{ //Each case is a menu option
        line1 = "Exit service";
        line2 = "mode";
        printlcd();

      //Action:
        if (last_select == LOW && current_select == HIGH){ //When down button is pressed

            lcd.clear();
            line1 = "Exiting";
            line2 = "Please Wait";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(500);

            delay(3000);
            lcd.clear();
            }
    }
    break;

  }//switch end

}

void submenu(){

    current_up_s = debounce(last_up, up);         //Debounce for Up button
    current_down_s = debounce(last_down, down);   //Debounce for Down button
    current_select = debounce(last_select, selection); //Debounce for Select button
    //----Page counter function to move pages----//

        //Page Up
        if (last_up == LOW && current_up_s == HIGH){  //When up button is pressed
          lcd.clear();                     //When page is changed, lcd clear to print new page        

            if(page_counter_s < 8){             //Page counter never higher than 3(total of pages)
                page_counter_s = page_counter_s +1;   //Page up
            }
            else{
                page_counter_s = 8;  
            }
        }

        last_up = current_up_s;

        //Page Down
        if (last_down == LOW && current_down_s == HIGH){ //When down button is pressed
          lcd.clear();                     //When page is changed, lcd clear to print new page    
          if(page_counter >1){              //Page counter never lower than 1 (total of pages)
          page_counter_s = page_counter_s -1;   //Page down

          }
          else{
          page_counter_s = 1;  
         }
        }

        last_down = current_down_s;




//------- Switch function to write and show what you want---// 
  switch (page_counter_s) {



    case 1:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "100 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";;
            line2 = "100 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 2:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "200 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "200 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 3:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "300 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "300 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 4:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "400 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "400 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 5:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "500 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "500 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 6:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "600 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "600 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 7:{ //Each case is a menu option

      line1 =   "Set dealy to:";
      line2 =   "700 hrs";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "New Delay:";
            line2 = "700 hrs";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

    case 8:{ //Each case is a menu option

      line1 =   "Back";
      line2 =   "";
      printlcd();
      //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
            lcd.clear();
            line1 = "Returning";
            line2 = "";
            printlcd();

            digitalWrite(LED,HIGH);
            delay(500);
            digitalWrite(LED,LOW);
            delay(3000);
            lcd.clear();
        }
    }
    break;

  }//switch end

}




void setup() {
  // put your setup code here, to run once:
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Menu Test");
  delay(3000);
  lcd.clear();  
}

void loop() {


  Menus();
}

So, my first question is: What is going wrong with the submenu? and my second question is: in the submenu, how do I exit back to main menu?

Any assistance will be much appreciated.

Thank You.

  • your LCD screen display code repeats multiple times with differing parameters ..... use a function that accepts two strings for the two lines and a boolean for clearing screen – jsotola Jan 17 at 7:50
  • @jsotola Hi. I have updated the code with a function to handle the screen printing. the code is in the question. The issue is still there. When I select option 5 or option 6 of the main menu, the program directly sets the delay to option 5.1 without allowing the user to navigate then select. – MDChaara Jan 17 at 9:21
  • the function i was talking about is in this form printlcd("Set 02", "Interval", true); ..... that would display the two lines ... the true means clear screen ..... see arduino.stackexchange.com/questions/3059/… .... read the comment at the accepted answer – jsotola Jan 19 at 3:55
  • the break statements should be inside the case block (inside the {} brackets) .........checking your code for logic errors – jsotola Jan 19 at 3:57
  • @jsotola Thank you very much. I'll look into the function and put the break statements inside the case blocks. Did you find any logic errors? – MDChaara Jan 19 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.