LCD Menu for preamp

Hi, I have been working on an Arduino controlled preamp system. I am just trying to create the menu structure so that the user is able to cycle through different options. However I am having a problem with sub-menus just doesn't work as I expected. Here is the code I have so far I have put a comment at the top of where the issue starts.

#include <LiquidCrystal.h>
#include <string.h>

/* DIO pin definitions */
#define LCD_DATA4 4         /* LCD data DIO pin 4 */
#define LCD_DATA5 5         /* LCD data DIO pin 5 */
#define LCD_DATA6 6         /* LCD data DIO pin 6 */
#define LCD_DATA7 7         /* LCD data DIO pin 7 */
#define LCD_RESET 8         /* LCD Reset DIO pin */
#define LCD_ENABLE 9        /* LCD Enable DIO pin */
#define LCD_BACKLIGHT 10    /*LCD backlight DIO pin */

LiquidCrystal lcd(LCD_RESET, LCD_ENABLE, LCD_DATA4, LCD_DATA5, LCD_DATA6, LCD_DATA7);

void setup() 
{  
  // set lcd size
  lcd.begin(16,2);
  Serial.begin(9600); //trying to debug
  delay(1000);
  MainMenu();
}
String screen(int level, int pos) //function to return correct string value
{
  String string;
  
	if (level == 0 && pos == 1)
	{
		string = "     Input:    ";
	}
	else if (level == 0 && pos == 2)
	{
		string = "    Volume:    ";
	}
	else if (level == 0 && pos == 3)
	{
		string = "      Bass:    ";
	}
	else if (level == 0 && pos == 4)
	{
		string = "     Balance:  ";
	}
	else if (level == 2 && pos == 1)
	{
		string = "      20 dB    ";
	}
	else if (level == 1 && pos == 1)
	{
		string = "     7.1 in    "; 
	}
	else if (level == 1 && pos == 2)
	{
		string = "    e5.1 in    ";
	}
	else if (level == 1 && pos == 3)
        {
	    string = "     2.1 in    ";
        }
	else if (level == 1 && pos == 4)
	{
		string = "     2.0 in    ";
	}
  return string;
}
void scrnprint(int level, int subLevel) //prints main screen
{
	ClearLCD();
	lcd.setCursor(0,0);
	lcd.print(screen(level,subLevel));
}
void scrnprintsub(int level, int subLevel,int edit) //prints screen when sub menu is visible
{
	byte ArrowsUD[8] = {
		B00100,
		B01110,
		B11111,
		B00000,
		B11111,
		B01110,
		B00100,
	};
	lcd.createChar(0,ArrowsUD);
	lcd.setCursor(0,0);
	lcd.print(screen(0,level));
	lcd.setCursor(0,1);
	lcd.print(screen(level,subLevel));
	if (edit == 1)
	{
		lcd.write(byte(0));
	}
	else
	{
		lcd.print(" ");
	}
	
}
void MainMenu()
{
  byte pos = 1,subpos = 1, inputSelected = 1;
    
  ClearLCD();
  scrnprintsub(1,inputSelected,0); // prints initial value of Input: with 7.1
  do
  {
    
    switch(LCDState()) // calls LCDState to get key press
    {
      case 8: //value correspond to numpad direction arrows
        pos++;
        if (pos > 4)
        {
           pos = 1;
        }
		if (pos == 1)
		{
			scrnprintsub(1,pos,0);
		}
		else
		{
			scrnprint(0,pos);
		}
		
        break;
      
      case 2:
        pos--;
        if (pos < 1)
        {
           pos = 4;
        }
		if (pos == 1)
		{
			scrnprintsub(1,pos,0);
		}
		else
		{
			scrnprint(0,pos);
		}
		
        break;
        
      case 6: //right = select
		switch(pos)
		{
			case 1: // when menu position is one ISSUE STARTS HERE!!!
			subpos = 1;
			scrnprintsub(1,pos,1);
			inputSelected = 0; //sets to 0 as initial condition
			do
			{
				
				switch(LCDState()) //gets key press
				{
					case 2: //cycle through options
					subpos--;
					if (subpos < 1){subpos = 4;}
                                        Serial.print(subpos);
					scrnprintsub(1,subpos,1);
					break;	
					
					case 8: //cycle through options
					subpos++;
					if (subpos > 4){subpos = 1;}
                                        Serial.print(subpos);					
					scrnprintsub(1,subpos,1);
					break;
					
					case 6: //if input is selected, set inputSelected to current position, and print new value
					inputSelected = subpos;
                                        Serial.print(subpos);
					scrnprintsub(1,inputSelected,0);
					break;			
				}
			}while (inputSelected != 0); //exits this case when a value has been selected
			break;	
			
			
			
			
		}
		
        break;
		delay(100);
	}
  }while(1==1);
		
}


void loop()
{

}

void ClearLCD()
{
  lcd.setCursor(0,0);
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print("                ");
  delay(20);
}

/* Read the current state of the LCD buttons using the ADC */
int LCDState()
{
  int ADC_Value;
  int ADC_Button_State = 0;

  ADC_Value = analogRead(0);      /* Read the ADC */


  /* If ADC reads above 1000 then assume no buttons have been pressed */
  if (ADC_Value > 1000) 
  {
    ADC_Button_State = 0;
  } 
  else /* If it was below 1000 then a button is pressed... */
  {

    /* If ADC reads between 0 & 49, then the RIGHT button has been pressed */
    if (ADC_Value < 50)             
    {
      ADC_Button_State = 6; 
    }
    else
    {
      /* If ADC reads between 50 & 194, then the UP button has been pressed */
      if (ADC_Value < 195)
      {      
        ADC_Button_State = 8;      
      }
      else
      {
        /* If ADC reads between 195 & 379, then the DOWN button has been pressed */
        if (ADC_Value < 380) 
        { 
          ADC_Button_State = 2;
        }
        else
        {
          /* If ADC reads between 380 & 555, then the LEFT button has been pressed */
          if (ADC_Value < 555)  
          {
            ADC_Button_State = 4;
          }
          else
          {
            /* If ADC reads between 555 & 789, then the SELECT button has been pressed */
            if (ADC_Value < 790)  
              {
                ADC_Button_State = 1;
              }        
          }
        }
      }
    }
  }
  delay(150);
  return ADC_Button_State;
}

Edit: problem is menu doesn't change to inputSelected, just stays on sub switch/case routine.
Many Thanks in advance
Sam

you need to put in a while loop and a timer to wait for buttons to be pressed. otherwise the code whips by before you have a chance to press a button, I use a 6 second timer to jump out of the code if a button isn't pressed.

jasit

Hi, thanks for the reply. Adding a timer will cause it to exit after a certain time, but shouldn't the code i've written exit when an input is selected. }while (inputSelected != 0);
I was going to add a timeout eventually and a back button to exit menu items, i just got stuck at this hurdle. I don't want to have to wait (say 6 seconds) for my option to be verified?

Sam

This is what I did, 

[code]
int buttonPins[] ={31,32,33,34,35,36};
int buttonState[] ={0,0,0,0,0,0};

31,32,33 are the pins I use on the mega. I use an array so that I don't have to do so many if statements
the example below is when i go into a menu, I display the options on the screen and then wait for a response, if they don't respond in 6 seconds I break out of the code and go back to the previous or main loop.

long mil = millis();
 long timer = 0;
lcd.clear();
  lcd.print("Admin Mode:  1-Update");
  lcd.setCursor(0,1);
  lcd.print("2-FreeVend 3-Off");
int thisPin;
  // the array elements are numbered from 0 to (pinCount - 1).
  // use a for loop to initialize each pin as an output:
   int buttonpressed = 0;
     while(buttonpressed < 1){
       timer = millis();
       for (int thisPin = 0; thisPin < drinkPinCount; thisPin++)  {
            buttonState[thisPin] = digitalRead(buttonPins[thisPin]);
            buttonpressed += buttonState[thisPin];           
       }
       if(timer - mil > 6000) {buttonpressed = 1;}     
     }
     if(timer - mil < 6000){
      if (buttonState[0] == HIGH) {     
           lcd.print("Admin Mode: Update");
           lcd.setCursor(0,1);
           lcd.print(RFIDnum);
           delay(500);
        Serial.println("Admin mode 0");
        admintimeout = 0; 
        while(admintimeout <1){AddtoCard();}
      }
      if (buttonState[1] == HIGH) {     
           lcd.print("Admin Mode:");
           lcd.setCursor(0,1);
           lcd.print("Free Drink On");
           for (int setcost = 0; setcost < drinkPinCount; setcost++)  {
            drinkCost[setcost] = 0;
           }  
           FreeDrink();
           delay(500);
           Serial.println("Admin mode 1");
        
      }
      if (buttonState[2] == HIGH) {     
           lcd.print("Admin Mode:");
           lcd.setCursor(0,1);
           lcd.print("Free Drink Off");
           soundSad();
           soundSad();
           soundSad();
           delay(1500);
           ReadPrices();
           
        Serial.println("Admin mode 2");
     }
    
   
    }

[/code]

Hi Jasit,
That is a way around what I am trying to do, however, I will be adding more options to my menu and running this method every time will be quite slow?/quite big? Is there a way for me to do this using while loop around a case/select? Or am I just on a wild goose chase?

Many Thanks
Sam

Hi, I worked out what was doing it, the code was flying through the case, and setting inputSelected != 0 therefore ending the loop, thanks for all the help jasit!

Sam