Go Down

Topic: LCD Menu Help (Read 1 time) previous topic - next topic

paulsvang

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

PaulS

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.

DuaneB

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
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

michael_x

May be I am too stupid to read other guy's sketch ;)

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...

DuaneB

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.
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

drone

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: [Select]


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

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


!c

paulsvang

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: [Select]

 /*
 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);
 


paulsvang

rest of code

Code: [Select]


    //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
  }
 
 
 

paulsvang

drone,

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

paulsvang



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: [Select]



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
}

DuaneB

Code: [Select]
if( digitalRead(buttonPressed) = HIGH ) { 

Should be ==

Duane B
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

paulsvang

Opps.  Of course it should be  == 

Go Up