Debounce on a switch with variable resistance

Menu now works perfectly with the multi-directional button! I hope this is useful to someone in the future.

Here is a better schematic:

PaulS:

unsigned char button = analogRead(inputPin) >> 2;

Unsigned char? Why? Why not byte?

Ehh...good point. Thanks! Still learning...

PeterH:
I'm a bit perplexed by the number of state variables you are using in readButtons.

Using buttonState and lastButtonState looks fine to hold the current detected state and previously detected state so you can detect changes. Using lastButtonPushed as a way to pass the change from readButtons() to navigateMenus() (and then clear it once it's been processed) is also OK. Personally I'd have preferred to have readButtons() return the key that was pressed (or 0 is nothing was pressed) rather than using a global variable, because this reduces the amount of global data and that is always a good thing, but that's mainly a matter of style. But then you also have buttonPushed and buttonPushCounter, and I have no idea what they're for. If you can eliminate them that would reduce the complexity by a useful amount.

Another good point. Got the code from the ButtonStateChange example. I was running out the door when I added it and didn't clean it up very well. Not sure how it would look to eliminate the lastButtonPushed. This is what I have now:

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
	void toRoot() {
		setCurrent( &getRoot() );
	}
*/
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
//#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

#define buttonPinLeft (1<<0)
#define buttonPinRight (1<<1)
#define buttonPinEsc   (1<<2)
#define buttonPinEnter  (1<<3)

int buttonState = 0;         // current state of the button
int lastButtonState = 0;     //last button state
int lastButtonPushed = 0;


int inputPin = 0;

// 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 menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");


void setup()
{
 
  Serial.begin(9600);
 
 
  //lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  //lcd.setCursor(0,0);  
  Serial.print("$GO 1 1\r\n");
  //lcd.print("Hello World!");
  Serial.print("$PRINT Hello World!        \r\n");
}  // 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)
                  
} //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
  
  if(newMenuItem.getName()==menu.getRoot()){
      //lcd.print("Main Menu       ");
      Serial.print("$CLEAR 2 1\r\n"); 
       Serial.print("$GO 2 1\r\n");
       Serial.print("$PRINT Main Menu       \r\n");
  }else if(newMenuItem.getName()=="Item1"){
    Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item1       \r\n");  
    //lcd.print("Item1           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
    Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item1SubItem1       \r\n");  
    //lcd.print("Item1SubItem1");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item1SubItem2       \r\n"); 
    //lcd.print("Item1SubItem2   ");
  }else if(newMenuItem.getName()=="Item2"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item2       \r\n");   
    //lcd.print("Item2           ");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item2SubItem1       \r\n");   
    //lcd.print("Item2SubItem1   ");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item2SubItem2       \r\n");   
    //lcd.print("Item2SubItem2   ");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item2SubItem3       \r\n");   
    //lcd.print("Item2SubItem3   ");
  }else if(newMenuItem.getName()=="Item3"){
      Serial.print("$CLEAR 2 1\r\n"); 
      Serial.print("$GO 2 1\r\n");
      Serial.print("$PRINT Item3       \r\n");   
    //lcd.print("Item3           ");
  }
}

void menuUsed(MenuUseEvent used){
 //do something useful here
}

void  readButtons(){  //read buttons status
byte button = analogRead(inputPin) >> 2;
  if (button == 0){
    buttonState=0;
  }
  if (button > 20 && button < 60){
    buttonState=buttonPinLeft;
  }
  else if (button > 60 && button < 100){
    buttonState=buttonPinEnter;
  }
  else if (button > 140 && button < 160){
    buttonState=buttonPinEsc; 
  }
  else if (button > 160 && button < 200){
    buttonState=buttonPinRight;  
  }
  else {
    buttonState=0;
  }  
 
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    if (buttonState != 0 ) {
      lastButtonPushed = buttonState;      
    } 
    else {
      lastButtonPushed = 0;
    }
  }
  // save the current state as the last state for next time through the loop
  lastButtonState = buttonState;
}

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
}