Pages: [1]   Go Down
Author Topic: LCD Menu Help  (Read 1047 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm working a menu for an LCD but I'm stuck.  The LCD is used to display sensor parameters but I need it to be able to tripper the menu when a button is pressed however the same button is used in the menu function as well.  What would be the best approach to getting the menu functioning?  Ive looked around but couldn't find one that would work.  I'm currently using the menubackend library for the menu.   In my instance I need it to not display until I hit the button.

Please someone help shine some light on the issue I have here.

Paul
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Please someone help shine some light on the issue I have here.
The issue you have here is that you failed to post any code.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

May be I am too lazy to learn something new, I have not looked at any of the menu libraries, but here is a project that does something similar just using normal functions -

each menu level is represented as a function, when you exit a menu level you simply return from the current function back into whatever function you were previously in, super simple easy to maintain and doesn't hold anything in memory that is not needed by the function you are in - demo in the middle, code at the end.

http://rcarduino.blogspot.com/2012/07/lap-timer-build-along-part-one.html

Duane B

rcarduino.blogspot.com
Logged


Germany
Offline Offline
Faraday Member
**
Karma: 49
Posts: 2751
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

May be I am too stupid to read other guy's sketch smiley-wink

but I understand yours hangs "forever" waiting for key pressing ( waitForKeyPress ) in your menu system.

If this is true, you are limited to interrupt routines to do anything else besides updating the LCD according to to menu buttons, I fear.
Even Serial output (e.g. for debugging your lap counting) should be frozen then ???

I'd go for a more ( responsive/ real time / ??? ) menu library. However, I have not checked other available ones, yet...
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   No, it doesn't block for example the doRecord function updates lap times and generates an audio countdown as the the current best lap time is expiring. Some levels of the menu effectively block because there is nothing realtime to do there, other parts are real time and do not block.

I guess my point is, its pretty easy to make a menu flow just using the hierarchical nature of functions and the stack

Duane B.
Logged


0
Offline Offline
Sr. Member
****
Karma: 3
Posts: 323
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A typical way to make something have a different function after some other event occurs, is to record whether the other event has occurred, and then change your behavior based on that signal.

I don't know about the library you're using, but the following pseudo-code should be informative:

Code:

if( buttonPressed ) {
   if( ! alreadyPressed ) {
       alreadyPressed = true;
       showMenu();
   }
   else {
       advanceMenu();
   }
}

if( cancelButtonPressed ) {
   alreadyPressed = false;
   hideMenu();
}

!c
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

DuaneB

I will take a look at the link you posted and hopefully it will make sense to me.



PaulS,

lcd.print("Sensor value") in the loop is just a place holder to display the sensor readings to the lcd screen but for know it'll just print "Sensor Value" .  Basically Im trying to figure out how a push switch can trigger the menu to splash on the screen.  I've did something simple like the code below but it didn't work.  Hopefully someone can help.  

void loop () {
if (digitalRead(pinButtonEnter() == HIGH){
    readButtons();  
       navigateMenus();
}

Code:
 /*
  Testing menu out
  */
  #include <EEPROM.h>         // Add in the EEPROM library
  #include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
  #include <LiquidCrystal.h>  //this library is included in the Arduino IDE
  
  const int buttonPinLeft = 8;      // pin for the Up button
  const int buttonPinRight = 9;    // pin for the Down button
  const int buttonPinEsc = 10;     // pin for the Esc button
  const int buttonPinEnter = 11;   // pin for the Enter button
  
  int lastButtonPushed = 0;
  
  int lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
  int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
  int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
  int lastButtonRightState = LOW;   // the previous reading from the Right input pin
  int menustate = LOW;  //  test is menu should be displayed or not
  
  long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
  long lastEscDebounceTime = 0;  // the last time the output pin was toggled
  long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
  long lastRightDebounceTime = 0;  // the last time the output pin was toggled
  long debounceDelay = 500;    // the debounce time
  
  // LiquidCrystal display with:
  // rs on pin 7
  // rw on ground
  // enable on pin 6
  // d4, d5, d6, d7 on pins 5, 4, 3, 2
  LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
  
  //Menu variables
  MenuBackend menu = MenuBackend(menuUsed,menuChanged);
  //initialize menuitems
      MenuItem BackLight = MenuItem("BackLight");
        MenuItem BackLightIncrease = MenuItem("Brighter");
        MenuItem BackLightDecrease = MenuItem("Dimmer");
      MenuItem Warning = MenuItem("Set Warning");
        MenuItem warn1 = MenuItem("1 Warning");
        MenuItem warn2 = MenuItem("2 Warning");
        MenuItem warn3 = MenuItem("3 Warning");
      MenuItem Calibration = MenuItem("Menu 3");
  
  
  void setup()
  {
    pinMode(buttonPinLeft, INPUT);
    pinMode(buttonPinRight, INPUT);
    pinMode(buttonPinEnter, INPUT);
    pinMode(buttonPinEsc, INPUT);
    
    lcd.begin(20, 2);
  

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

rest of code

Code:

    //configure menu order
    menu.getRoot().add(BackLight);
    BackLight.addRight(Warning).addRight(Calibration);
    BackLight.add(BackLightIncrease).addRight(BackLightDecrease);
    Warning.add(warn1).addRight(warn2).addRight(warn3);
    menu.toRoot();
    lcd.setCursor(0,0); 
    lcd.print("Digital Dreams");
 
  }  // setup()...
 
 
  void loop()
  {
    readButtons();  //I splitted button reading and navigation in two procedures because
    navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)
   
 
   lcd.print("Sensor Value");
   
  } //loop()...
 


  void menuChanged(MenuChangeEvent changed){
    MenuItem newMenuItem=changed.to; //get the destination menu
    lcd.setCursor(0,1); //set the start position for lcd printing to the second row
    lcd.print(newMenuItem.getName());  // Print the Menu selection onto the LCD
    lcd.print("            ");  // Print spaces to clear the trailing spaces that should be blank
  }
 
  void menuUsed(MenuUseEvent used){
    lcd.setCursor(0,0); 
    lcd.print("Setting Saved       ");
    lcd.setCursor(0,1);
    lcd.print(used.item.getName());
    delay(3000);  //delay to allow message reading
    lcd.setCursor(0,0); 
    lcd.print("Digital Dreams");
    menu.toRoot();  //back to Main
  }
 
 
  void  readButtons(){  //read buttons status
    int reading;
    int buttonEnterState=LOW;             // the current reading from the Enter input pin
    int buttonEscState=LOW;             // the current reading from the input pin
    int buttonLeftState=LOW;             // the current reading from the input pin
    int buttonRightState=LOW;             // the current reading from the input pin
 
    //Enter button
                    // read the state of the switch into a local variable:
                    reading = digitalRead(buttonPinEnter);
 
                    // check to see if you just pressed the enter button
                    // (i.e. the input went from LOW to HIGH),  and you've waited
                    // long enough since the last press to ignore any noise: 
                 
                    // If the switch changed, due to noise or pressing:
                    if (reading != lastButtonEnterState) {
                      // reset the debouncing timer
                      lastEnterDebounceTime = millis();
                    }
                   
                    if ((millis() - lastEnterDebounceTime) > debounceDelay) {

                      buttonEnterState=reading;
                      lastEnterDebounceTime=millis();
                    }
                   

                    lastButtonEnterState = reading;
                   
 
      //Esc button               

                    reading = digitalRead(buttonPinEsc);
 
                    // check to see if you just pressed the Down button
                    // (i.e. the input went from LOW to HIGH),  and you've waited
                    // long enough since the last press to ignore any noise: 
                 
                    // If the switch changed, due to noise or pressing:
                    if (reading != lastButtonEscState) {
                      // reset the debouncing timer
                      lastEscDebounceTime = millis();
                    }
                   
                    if ((millis() - lastEscDebounceTime) > debounceDelay) {
                      // whatever the reading is at, it's been there for longer
                      // than the debounce delay, so take it as the actual current state:
                      buttonEscState = reading;
                      lastEscDebounceTime=millis();
                    }
                   
                    // save the reading.  Next time through the loop,
                    // it'll be the lastButtonState:
                    lastButtonEscState = reading;
                   
                       
     //Down button               
                    // read the state of the switch into a local variable:
                    reading = digitalRead(buttonPinRight);
 
                    // check to see if you just pressed the Down button
                    // (i.e. the input went from LOW to HIGH),  and you've waited
                    // long enough since the last press to ignore any noise: 
                 
                    // If the switch changed, due to noise or pressing:
                    if (reading != lastButtonRightState) {
                      // reset the debouncing timer
                      lastRightDebounceTime = millis();
                    }
                   
                    if ((millis() - lastRightDebounceTime) > debounceDelay) {
                      // whatever the reading is at, it's been there for longer
                      // than the debounce delay, so take it as the actual current state:
                      buttonRightState = reading;
                     lastRightDebounceTime =millis();
                    }
                   
                    // save the reading.  Next time through the loop,
                    // it'll be the lastButtonState:
                    lastButtonRightState = reading;                 
                   
                   
      //Up button               
                    // read the state of the switch into a local variable:
                    reading = digitalRead(buttonPinLeft);
 
                    // check to see if you just pressed the Down button
                    // (i.e. the input went from LOW to HIGH),  and you've waited
                    // long enough since the last press to ignore any noise: 
                 
                    // If the switch changed, due to noise or pressing:
                    if (reading != lastButtonLeftState) {
                      // reset the debouncing timer
                      lastLeftDebounceTime = millis();
                    }
                   
                    if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                      // whatever the reading is at, it's been there for longer
                      // than the debounce delay, so take it as the actual current state:
                      buttonLeftState = reading;
                      lastLeftDebounceTime=millis();;
                    }
                   
                    // save the reading.  Next time through the loop,
                    // it'll be the lastButtonState:
                    lastButtonLeftState = reading; 
 
                    //records which button has been pressed
                    if (buttonEnterState==HIGH){
                      lastButtonPushed=buttonPinEnter;
 
                    }else if(buttonEscState==HIGH){
                      lastButtonPushed=buttonPinEsc;
 
                    }else if(buttonRightState==HIGH){
                      lastButtonPushed=buttonPinRight;
 
                    }else if(buttonLeftState==HIGH){
                      lastButtonPushed=buttonPinLeft;
 
                    }else{
                      lastButtonPushed=0;
                    }                 
  }
 
  void navigateMenus() {
    MenuItem currentMenu=menu.getCurrent();
   
    switch (lastButtonPushed){
      case buttonPinEnter:
        if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
          menu.use();
        }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
          menu.moveDown();
         }
        break;
      case buttonPinEsc:
        menu.toRoot();  //back to main
        break;
      case buttonPinRight:
        menu.moveRight();
        break;     
      case buttonPinLeft:
        menu.moveLeft();
        break;     
    }
   
    lastButtonPushed=0; //reset the lastButtonPushed variable
  }
 
 
 
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

drone,

thanks. I will look at that concept and see if I can get it to work.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



Drone or anyone,

Sample Code I put together to get the idea of how it functions.  Please look at the code and notes then let me know if this is feasible.  I will test it out later when I get home.   

Code:


const int buttonPressed = 3;

void setup() {
pinMode(buttonPressed, INPUT);
}



void loop () {
if( digitalRead(buttonPressed) = HIGH ) {   // if button is pressed, then do the following
   if( ! alreadyPressed ) {   // if alreadyPressed is not True, then do the following
       alreadyPressed = true;  // makes the variable  alreadyPressed to True...  second time around it skips this if
// statement.
       showMenu();
   }
   else {
       displaysensorvalue();   // not sure if the sensor display should be here or not since it shouldn't be
// displayed if the menu function is displayed
   }
}

if( cancelButtonPressed ) {
   alreadyPressed = false;
   hideMenu();
}
}


displaysensorvalue(){
lcd.print("Sensor Value = 5");  //just a place holder
}

hideMenu(){
  // not sure what goes here to hide the menu or if it's needed
}

showMenu(){
menu.List  // just an placeholder for the menu
}
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
if( digitalRead(buttonPressed) = HIGH ) { 

Should be ==

Duane B
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Opps.  Of course it should be  == 
Logged

Pages: [1]   Go Up
Jump to: