Help creating a menu LCD Keypad Shield

Hi all,

I'm not sure if this is the right location, however this is what i'm trying to do:

I am making a wine brewbot (controls temp and stirs the wine while it ferments). I have a DF robot LCD keypad shield and I want to create a menu that allows me to incrementally change the maximum temperature of the heat pad and the speed of the stirring motor and then return to the temperature display and monitoring.

My problems:
I can select through the menus however I cannot change the motor speed and temperature and then return to the main temperature display.
I also cannot return from any point in the menu structure to the main temperature display.

This is my first serious programme project and I think i'm loosing the battle. Hopefully some of the knowledgeable on this forum could give some advise. this is what i've created thus far:

Regards,

Code to follow

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

 
// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 
//States for the menu.
int currentMenuItem = 0;
int lastState = 0;
int motorspeed = 0;
int Mainstate = 0;
#define RELAY_ON 0
#define RELAY_OFF 1
int state1;
int state2;
int Relay1Pin = 11;//Cooling system Relay
int Relay2Pin = 12;//Heating system Relay
float maxtemp = 25.00;// If max temp is exceeded relays are switched

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
//0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC
DeviceAddress Probe01 = { 0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC };

byte Thermo[8] = //icon for Thermometer
{
    B00100,
    B01010,
    B01010,
    B01110,
    B01110,
    B11111,
    B11111,
    B01110
};


void setup() {
  digitalWrite(Relay1Pin, RELAY_OFF);
  digitalWrite(Relay2Pin, RELAY_OFF);
  pinMode(Relay1Pin, OUTPUT);
  pinMode(Relay2Pin, OUTPUT); 
  //Serial.begin(9600);
  delay(1000);
  //start reading
  lcd.createChar(1,Thermo);
  sensors.begin();
  sensors.setResolution(Probe01, 10);
  //setup the LCD
  lcd.begin(16, 2); // start the library

   //Set the characters and column numbers.
   //lcd.begin(16, 2);
   //Print default title.
   //clearPrintTitle();
}
/*-------------------------------------------------------------(MAIN LOOP)----------------------------------------------------------*/ 
void loop() {

  statecheck();    
  if (Mainstate == 0){//If Menu buttons are not pushed read temp and display
    tempcall();
  }
  else{  
    digitalWrite(Relay1Pin, RELAY_OFF); // turns of heater and stirrer when menu is accessed
    digitalWrite(Relay2Pin, RELAY_OFF);
    mainMenu();//If menu buttons are pushed pass state into mainmenu function
  }
}

/*------------------------------------------------( Declare User-written Functions )-----------------------------------------------*/
int statecheck(){// Checks if menu buttons pressed to initiate the menu display
  //Refresh the button pressed.
     //State = 0 every loop cycle.
     //int state;
     //state = 0;
     int x = analogRead (0);
      //Check analog values from LCD Keypad Shield
    if (x < 90) {
     //Right
   } else if (x < 200) {
    //Up
     Mainstate = 1;
   } else if (x < 350){
    //Down
     Mainstate = 2;
    } else if (x < 500){
     //Left
     Mainstate = 3;
   } else if (x < 800){
      //Select
     Mainstate = 4;
   }
  return Mainstate;
}

void tempcall(){
  //read temperature and output via LCD
  sensors.requestTemperatures();
  lcd.clear();
  lcd.setCursor(1,0);
  lcd.write(byte(1));
  lcd.setCursor(3,0);
  //lcd.print(sensors.getTempCByIndex(0));
  float TEMP = sensors.getTempC(Probe01);
  lcd.print(TEMP);// -1.2 is calibration for the resistor used
  lcd.setCursor(7,0);
  lcd.print((char)223);
  lcd.print("C "); 
  Temperatureexceed(Probe01);//Turn on or off relays is certain temperature conditions are met
}

void Temperatureexceed(DeviceAddress deviceAddress)// Controls relays based on temperature readings
{
//float currenttemp = sensors.getTempCByIndex(0);
float currenttemp = sensors.getTempC(deviceAddress);

if(currenttemp <= maxtemp){
  state1 = RELAY_ON;//ON for cooling system
  state2 = RELAY_ON;//OFF for heating system
  
  lcd.setCursor(1,1);
  lcd.print("HEATER: ON "); 
  }
else{
    state1 = RELAY_OFF;// OFF for cooling system
    state2 = RELAY_OFF;//OFF for heating system
    lcd.setCursor(1,1);
    lcd.print("HEATER: OFF");
    }
digitalWrite(Relay1Pin, state1); 
digitalWrite(Relay2Pin, state2);
}
 
void mainMenu() {// Sets up main menu
 //Refresh the button pressed.
   //State = 0 every loop cycle.
   int state;
   state = 0;
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);

     int x = analogRead (0);
      //Check analog values from LCD Keypad Shield
    if (x < 90) {
     //Right
   } else if (x < 200) {
    //Up
     state = 1;
   } else if (x < 350){
    //Down
     state = 2;
    } else if (x < 500){
     //Left
     state = 3;
   } else if (x < 800){
      //Select
     state = 4;
   }
 
  //If we are out of bounds on th menu then reset it.
  if (currentMenuItem < 0 || currentMenuItem > 4) {
   currentMenuItem = 0; 
  }
 
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1; 
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1;  
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Left
         currentMenuItem = 0; 
      }else if (state == 4) {
         //If Selected
         selectMenu(currentMenuItem); 
         currentMenuItem = 0; 
         
         
      }
      //Save the last State to compare.
      lastState = state;
   } 
   //Small delay
  delay(5);

}
 
//Display Menu Option based on Index.
void displayMenu(int x) {// Prints menu options
     switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("Set Motor Speed");
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("Set Max Temp");
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("Menu Option 3");
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("Menu Option 4");
        break;
    }
}
 
//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" CONFIGURE ");
  lcd.setCursor(0,1); 
}
 
//Show the selection on Screen.
void selectMenu(int x) {// Lowest menu level
  int state;
   switch (x) {
      case 1:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Speed");
        lcd.setCursor(0,1); 
        //Call the function that belongs to Option 1
        state = xcheck();
        changespeed(state);
        delay(1000);
        break;
      case 2:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Temperature");
        //Call the function that belongs to Option 2
        state = xcheck();
        changemaxtemp(state);
        lcd.setCursor(0,1); 
        delay(1000);
        break;
       case 3:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Option 3");
        //Call the function that belongs to Option 2
        lcd.setCursor(0,1); 
        delay(1000);
        break;
      case 4:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Option 4");
        //Call the function that belongs to Option 2
        lcd.setCursor(0,1); 
        delay(1000);
        break;
    }
}
int xcheck(){//Checks which button is pushed when changing temp or motor speed
    int x = analogRead (0);
    int state = 0;
      //Check analog values from LCD Keypad Shield
    if (x < 90) {
     //Right
   } else if (x < 200) {
    //Up
     state = 1;
   } else if (x < 350){
    //Down
     state = 2;
    } else if (x < 500){
     //Left
     state = 3;
   } else if (x < 800){
      //Select
     state = 4;
   }
   return state;
}

int changemaxtemp(int x){//Incrementally changes max temperature
  //maxtemp = maxtemp++
       switch (x) {
      case 1:
        maxtemp = maxtemp++;
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("Speed = ");
          lcd.setCursor(8,1); 
          lcd.print(maxtemp);
        break;
      case 2:
        maxtemp = maxtemp--;
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("Max Temp = ");
          lcd.setCursor(11,1); 
          lcd.print(maxtemp);
        break;
      case 3:
      break;
      case 4:
      break;
     }   
}

int changespeed(int x){//Incrementally changes motor speed
     switch (x) {
      case 1:
        motorspeed = motorspeed++;
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("Speed = ");
          lcd.setCursor(8,1); 
          lcd.print(motorspeed);
        break;
      case 2:
        motorspeed = motorspeed--;
          lcd.clear();
          lcd.setCursor(0,1);
          lcd.print("Speed = ");
          lcd.setCursor(8,1); 
          lcd.print(motorspeed);
        break;
      case 3:
      break;
      case 4:
      break;
     }   
}

The Hardware I have is:
Arduino Uno
DF Robot Keypad Shield
Dallas temp sensor
Heat pad
DC Motor for stiring

I might add: I would like to use the left button for exiting each menu (like a back button)

I've figured it out(possibly some bugs):

Hopefully this might help someone else.

The setup:
one dual relay connected to Arduino pins 11 and 12
One Wire Digital Temperature Sensor - DS18B20 connected to Arduino pin 2
~4.7 Kohm resistor between DS18B20 sense line and 5v line (refferTemp sensor tut)
A DFrobot LCD keypad shield (or clone)
An Arduino Uno (or clone)

What happens:
LCD displays the current temp, set temp and if the heater is on or off.
if the current temp is above set temp heater off
if the current temp is below temp heater on
other relay is always on but can be switched on or off based on same logic above
menu allow the user to increment set temp and motor speed (or some other variable)
user presses left button to return to monitoring.

some bugs i'm aware of:
when the user is in the menu the relays won't switch on or off if temperature is exceeded.
the user can only increment the speed or set temp by 1 and must re-enter menu to increment another 1

Code to follow

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 
//States for the menu.
int currentMenuItem = 0;
int lastState = 0;
int motorspeed = 11;
int minspeed = 10;
int maxspeed = 60;
boolean Mainstate = false;
#define RELAY_ON 0
#define RELAY_OFF 1
int state1;
int state2;
int Relay1Pin = 11;//Cooling system Relay
int Relay2Pin = 12;//Heating system Relay
float toptemp = 60.00;
float maxtemp = 28.00;// If max temp is exceeded relays are switched
float mintemp = 20.00;

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
//0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC
DeviceAddress Probe01 = { 0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC };

byte Thermo[8] = //icon for Thermometer
{
    B00100,
    B01010,
    B01010,
    B01110,
    B01110,
    B11111,
    B11111,
    B01110
};

byte Arrow[8] = { 8,12,10,9,10,12,8};
void setup() {
  digitalWrite(Relay1Pin, RELAY_OFF);
  digitalWrite(Relay2Pin, RELAY_OFF);
  pinMode(Relay1Pin, OUTPUT);
  pinMode(Relay2Pin, OUTPUT); 
  //Serial.begin(9600);
  delay(1000);
  //start reading
  lcd.createChar(1,Thermo);
  lcd.createChar(2,Arrow);
  sensors.begin();
  sensors.setResolution(Probe01, 10);
  //setup the LCD
  lcd.begin(16, 2); // start the library

}
/*-------------------------------------------------------------(MAIN LOOP)----------------------------------------------------------*/ 
void loop() {


  statecheck();   
  if (Mainstate == 0){//If Menu buttons are not pushed read temp and display
    tempcall();
  }
  else{  
    //digitalWrite(Relay1Pin, RELAY_OFF); // turns of heater and stirrer when menu is accessed
    //digitalWrite(Relay2Pin, RELAY_OFF);
    mainMenu();//If menu buttons are pushed pass state into mainmenu function
    
  }
 }   


/*------------------------------------------------( Declare User-written Functions )-----------------------------------------------*/
boolean statecheck(){// Checks if menu buttons pressed to initiate the menu display
  //Refresh the button pressed.
     //State = 0 every loop cycle.
     //int state;
     //state = 0;
    int x = analogRead (0);
      //Check analog values from LCD Keypad Shield
    if (x > 0 && x < 90) {
     //Right
   } else if (x > 91 && x < 250) {
    //Up
     Mainstate = true;
   } else if (x > 251 && x < 400){
    //Down
     Mainstate = true;
    } else if (x > 400 && x < 600){
     //Left
     Mainstate = true;
   } else if (x > 600 && x < 640){
      //Select
     Mainstate = true;
   }

  return Mainstate;
}

void tempcall(){
  //read temperature and output via LCD
  sensors.requestTemperatures();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.write(byte(1));
  lcd.setCursor(2,0);
  //lcd.print(sensors.getTempCByIndex(0));
  float TEMP = sensors.getTempC(Probe01);
  lcd.print(TEMP,1);//Second value is number of sig figs
  lcd.setCursor(6,0);
  lcd.print((char)223);
  lcd.print("C"); 
  lcd.setCursor(0,1);//9,0
  lcd.write(byte(2));
  lcd.setCursor(2,1);//9,0
  lcd.print(maxtemp,1); 
  lcd.print((char)223);
  lcd.print("C"); 
  Temperatureexceed(Probe01);//Turn on or off relays is certain temperature conditions are met

}
void Temperatureexceed(DeviceAddress deviceAddress)// Controls relays based on temperature readings
{
//float currenttemp = sensors.getTempCByIndex(0);
float currenttemp = sensors.getTempC(deviceAddress);

if(currenttemp <= maxtemp){
  state1 = RELAY_ON;//OFF for cooling system(If Stirrer instead always on)
  state2 = RELAY_ON;//ON for heating system
  
  lcd.setCursor(10,0);//1,1
  lcd.print("HEATER"); 
  lcd.setCursor(12,1);//1,1
  lcd.print("ON"); 
  }
else{
    state1 = RELAY_ON;// OFF for cooling system
    state2 = RELAY_OFF;//OFF for heating system
    lcd.setCursor(10,0);//1,1
    lcd.print("HEATER");
    lcd.setCursor(12,1);//1,1
    lcd.print("OFF"); 
    }
digitalWrite(Relay1Pin, state1); 
digitalWrite(Relay2Pin, state2);
}
 
boolean mainMenu() {// Sets up main menu
 //Refresh the button pressed.
   //State = 0 every loop cycle.
   int state;
   //boolean mainstate;
   state = 0;
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);
  //If we are out of bounds on th menu then reset it.
    if (currentMenuItem <= -1) {
   currentMenuItem = 4; 
   displayMenu(currentMenuItem);
  }
  if (currentMenuItem >= 5){
    currentMenuItem = 0;
    displayMenu(currentMenuItem);
  }

 state = xcheck();//Checks which button was pressed
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1; 
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1;  
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Left
          Mainstate = false;
          tempcall();// Needs to go back to main loop
      }else if (state == 4) {
         //If Selected
         selectMenu(currentMenuItem); 
         currentMenuItem = 0;    
      }
      //Save the last State to compare.
      lastState = state;
   } 

   //Small delay
  delay(5);
 
  return Mainstate;
}
 
//Display Menu Option based on Index.
void displayMenu(int x) {// Prints menu options
     switch (x) {
      case 1:
        clearPrintTitle();
        lcd.print ("Incr Max Temp");
        break;
      case 2:
        clearPrintTitle();
        lcd.print ("Decr Max Temp");
        break;
       case 3:
        clearPrintTitle();
        lcd.print ("Inc Motor Speed");
        break;
      case 4:
        clearPrintTitle();
        lcd.print ("Decr Motor Speed");
        break;
    }
}
 
//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("CONFIGURE ");
  lcd.setCursor(0,1); 
}

Other half:

//Show the selection on Screen.
void selectMenu(int x) {// Lowest menu level
  int statespeed;
  int statetemp;
   switch (x) {
       case 1:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Temperature");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Temp = ");
        //Call the function that belongs to Option 2
        incrmaxtemp();
        lcd.setCursor(0,1); 
        delay(1000);
        break;
      case 2:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Temperature");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Temp = ");
        //Call the function that belongs to Option 2
        decrmaxtemp();
        lcd.setCursor(0,1); 
        delay(1000);
        break;
        case 3:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Speed");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Speed = ");
        //Call the function that belongs to Option 1
        incrspeed();
        delay(1000);
        break;
      case 4:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Max Speed");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Speed = ");
        //Call the function that belongs to Option 1
        decrspeed();
        delay(1000);
        break;
    }
  
}
int xcheck(){//Checks which button is pushed when changing temp or motor speed
    int x = analogRead (0);
    int state = 0;
      //Check analog values from LCD Keypad Shield
    if (x > 0 && x < 90) {
     //Right
   } else if (x > 91 && x < 250) {
    //Up
     state = 1;
   } else if (x > 251 && x < 400){
    //Down
     state = 2;
    } else if (x > 400 && x < 600){
     //Left
     state = 3;
   } else if (x > 600 && x < 640){
      //Select
     state = 4;
   }
       
   return state;
}

int incrmaxtemp(){//Incrementally changes max temperature
  if (maxtemp+1 > toptemp){
      maxtemp = toptemp - 1;
    }
    maxtemp = maxtemp + 1;
    lcd.setCursor(7,1); 
    lcd.print(maxtemp);
    lcd.print((char)223);
    lcd.print("C "); 
    
}

int decrmaxtemp(){//Incrementally changes max temperature
    if (maxtemp-1 < mintemp){
      maxtemp = mintemp + 1;
    }
    maxtemp = maxtemp - 1;
    lcd.setCursor(7,1); 
    lcd.print(maxtemp);
    lcd.print((char)223);
    lcd.print("C "); 
    
}
int incrspeed(){//Incrementally changes motor speed
    if (motorspeed+1 > maxspeed){
    motorspeed = maxspeed - 1;
    }
    motorspeed = motorspeed + 1;
    lcd.setCursor(8,1); 
    lcd.print(motorspeed);
      
}
int decrspeed(){//Incrementally changes motor speed
    if (motorspeed-1 < minspeed){
    motorspeed = minspeed + 1;
    }
    motorspeed = motorspeed - 1;
    lcd.setCursor(8,1); 
    lcd.print(motorspeed);
      
}

I have not completely examined your code.

Just an idea:
To increment/decrement temperature or speed by more than one step in your functions:

  • have a state variable set whenever you call that function and loop with either a "while loop" or "for loop" within your function and
  • increment one step up or down until
  • you read a state change caused by your exit button (left button) to leave the function.

mchorse:
My problems:
I can select through the menus however I cannot change the motor speed and temperature and then return to the main temperature display.
I also cannot return from any point in the menu structure to the main temperature display.

With LCD Keypad Shield configuration menus I typically provide a short phrase in the first line of the display while in edit mode, like "Edit temp:" or "Edit speed", and in the second line the user gets two options to leave the edit mode: OK or Abort. The "OK" is showed as text along with the edited value like:
"23.2°C OK".
This second line which displays the edited value and OK has a blinking block cursor at the editablecharacter.
For selecting OK, the user moves the cursor to the right until it is on the O or on the K of OK, then presses "Select" and the edit mode menu will end with a "Save and Exit"function.

For selecting Abort, the user just moves the cursor to the right until the cursor meets the right side of the line. When the cursor is moved fully to the right end of the line, the edit mode menu will end with a "Abort and Exit" function and returns to normal mode. I think I could create some example code for that if you let me know the short phrase to display along with the minimum and maximum values for the configuration, like
"Edit temp", min= 15.8°C, max = 27.3°C
"Edit speed, min= 000, max = 255
or something like that , as you like, I currently neither know all the configuration values you might want to edit nor I do know the min/max range of the values the user shall be able to enter for the configured values in the menu editor. You don't need editable configuration menu for "date or "time", do you?

Thanks for the replies rpt007 and jurs. Spurred on by your replies I've come up with code that now:

On start up asks the user to select which type of brewing they would like to do (red wine, white wine, cider or beer) and adjusts the set temperature to the optimum fermentation temperature based on type.

Displays the set temp, current temp and whether the heater is on or off.

Has a menu to:
with the use of the DS3231 real time clock module, that displays the time, date and temp of the
DS3231 Real time clock module.

a menu to change the set temperature between a max min range set in the code.

and a menu to change the set motor speed from 0-255.

This code also will back out of each menu if the left button is pushed or an amount of time has passed with out user input.

It currently controls two relays.

I have another code which uses PID gains to control the temperature however I would like to see how the simpler code controls the temperature without PID first. As finding the PID gains will take some modelling or a lot of trial and error, and seeing as I just spent the last 6 months learning PID control at uni I feel like having rest from it.

Code to follow

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DS3231.h>
// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Init the DS3231 using the hardware interface
DS3231  rtc(SDA, SCL); 
//States for the menu.
int introspeed = 3000;// Intro screen delay
int keyspeed = 250; //Delay on button push
int dispspeed = 500; // display delay
int currentMenuItem = 0;
int lastState = 0;
int motorspeed = 200;
int minspeed = 0;
int maxspeed = 255;
boolean Mainstate = false;
#define RELAY_ON 0
#define RELAY_OFF 1
int state1;
int state2;
int Relay1Pin = 11;//Cooling system Relay
int Relay2Pin = 12;//Heating system Relay
float toptemp = 60.00;
float settemp = 28.00;// If max temp is exceeded relays are switched
float mintemp = 0.00;

unsigned long timeoutTime = 0;  // this is set and compared to millis to see when the user last did something.
const int menuTimeout = 10000; // time to timeout in a menu when user doesn't do anything.

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
//0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC
DeviceAddress Probe01 = { 0x28, 0xFD, 0x69, 0x15, 0x06, 0x00, 0x00, 0xAC };

byte Thermo[8] = //icon for Thermometer
{
    B00100,
    B01010,
    B01010,
    B01110,
    B01110,
    B11111,
    B11111,
    B01110
};

byte Timesym[8] = {0,14,21,23,17,14,0,0};
byte Arrow[8] = { 8,12,10,9,10,12,8};
byte Wine[8] = {31,17,17,10,4,4,4,31};

void setup() {
  rtc.begin();

  //The following lines can be uncommented to set the date and time
  //rtc.setDOW(MONDAY);     // Set Day-of-Week to SUNDAY 
  //rtc.setTime(1, 41, 0);     // Set the time to 12:00:00 (24hr format)
 //rtc.setDate(6, 14, 2016);   // Set the date to January 1st, 2014
  digitalWrite(Relay1Pin, RELAY_OFF);
  digitalWrite(Relay2Pin, RELAY_OFF);
  pinMode(Relay1Pin, OUTPUT);
  pinMode(Relay2Pin, OUTPUT); 
  //delay(dispspeed);
  //start reading
  lcd.createChar(1,Thermo);
  lcd.createChar(2,Arrow);
  lcd.createChar(3,Timesym);
  lcd.createChar(4,Wine);
  sensors.begin();
  sensors.setResolution(Probe01, 10);
  //setup the LCD
  lcd.begin(16, 2); // start the library
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("BREWBOT Ver. 1.0");
  lcd.setCursor(1,1);
  lcd.print("Brew Tech 2016");
  delay(introspeed);
  lcd.clear();
   lcd.setCursor(2,0);
   lcd.print("PLEASE PUSH");
   delay(dispspeed*2);
   lcd.clear();
   lcd.setCursor(3,0);
   lcd.print("UP OR DOWN");
   delay(dispspeed*2);
   lcd.clear();
   lcd.setCursor(3,0);
   lcd.print("TO SELECT");
   delay(dispspeed*2);
   lcd.clear();
   lcd.setCursor(2,0);
   lcd.print("BREWING TYPE");
   delay(dispspeed*2);
  boolean choice = false;
  while(!choice){
    //Refresh the button pressed.
   //State = 0 every loop cycle.
   int state;
   //boolean mainstate;
   state = 0;
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);
  //If we are out of bounds on th menu then reset it.
  void displayChoiceMenu(int x);
  float choicefnc(int x);
   int xcheck();
    if (currentMenuItem <= -1) {// menus count from 0,1, etc
       currentMenuItem = 4; // increase to number of menus requred +1
   displayChoiceMenu(currentMenuItem);
  }
  if (currentMenuItem >= 5){//Increase to number of menus required
    currentMenuItem = 0;
    displayChoiceMenu(currentMenuItem);
  }
   state = xcheck();//Checks which button was pressed
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1; 
          displayChoiceMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1;  
          displayChoiceMenu(currentMenuItem);
      }else if (state == 4) {
         //If Selected
           if(currentMenuItem ==1){
             settemp = 25.00;// Optimum temp for Red Wine 
           }
          if(currentMenuItem ==2){
             settemp = 12.00;// Optimum temp for Red Wine 
          }
          if(currentMenuItem ==3){
            settemp = 15.00;// Optimum temp for Cider 
          }
          if(currentMenuItem ==4){
            settemp = 15.00;// Optimum temp for Beer
          }
           
         currentMenuItem = 0; 
         choice = true;  
         lcd.clear();
         lcd.setCursor(1,0);
         lcd.write(byte(2));
         lcd.setCursor(2,0);
         lcd.print("TYPE SELECTED");
         delay(dispspeed*2); 
         break;  
      }
      //Save the last State to compare.
      lastState = state;
   } 
  }
}
/*-------------------------------------------------------------(MAIN LOOP)----------------------------------------------------------*/
void loop() {
    boolean stillSelecting = true;  // set because user is still selecting. 
    timeoutTime = millis() + menuTimeout; // set initial timeout limit.  
    do   // loop while waiting for user to select.
    {
        statecheck();   
        if (Mainstate == 0){//If Menu buttons are not pushed read temp and display
          tempcall();
        }
        else{  
          mainMenu();//If menu buttons are pushed pass state into mainmenu function  
    if (timeoutTime<millis()){  // user hasn't done anything in awhile
        stillSelecting = false;  // tell loop to bail out. 
          tempcall(); 
        }      
      }
    }
    while (stillSelecting == true);  
  
}

/*------------------------------------------------( Declare User-written Functions )-----------------------------------------------*/
boolean statecheck(){// Checks if menu buttons pressed to initiate the menu display
  //Refresh the button pressed.
    int x = analogRead (0);
      //Check analog values from LCD Keypad Shield
    if (x > 0 && x < 90) {//Right
   } else if (x > 91 && x < 250) {//Up
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     Mainstate = true;
   } else if (x > 251 && x < 400){//Down
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     Mainstate = true;
    } else if (x > 400 && x < 600){//Left
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     Mainstate = true;
   } else if (x > 600 && x < 700){//Select
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     Mainstate = true;
   }

  return Mainstate;
}

void tempcall(){
  //read temperature and output via LCD
  sensors.requestTemperatures();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.write(byte(4));
  //lcd.write(byte(1));
  lcd.setCursor(2,0);//(2,0)
  float TEMP = sensors.getTempC(Probe01);
  lcd.print(TEMP,1);//Second value is number of sig figs
  lcd.setCursor(6,0);//(6,0)
  lcd.print((char)223);
  lcd.print("C"); 
  lcd.setCursor(0,1);//(0,1)
  lcd.write(byte(1));
  lcd.setCursor(2,1);//(2,1)
  lcd.print(settemp,1); 
  lcd.print((char)223);
  lcd.print("C"); 
  Temperatureexceed(Probe01);//Turn on or off relays is certain temperature conditions are met
}

void Temperatureexceed(DeviceAddress deviceAddress)// Controls relays based on temperature readings
{
//float currenttemp = sensors.getTempCByIndex(0);
float currenttemp = sensors.getTempC(deviceAddress);

if(currenttemp <= settemp){
  state1 = RELAY_ON;//OFF for cooling system(If Stirrer instead always on)
  state2 = RELAY_ON;//ON for heating system
  
  lcd.setCursor(10,0);//1,1
  lcd.print("HEATER"); 
  lcd.setCursor(12,1);//1,1
  lcd.print("ON"); 
  }
else{
    state1 = RELAY_OFF;// OFF for cooling system
    state2 = RELAY_OFF;//OFF for heating system
    lcd.setCursor(10,0);//1,1
    lcd.print("HEATER");
    lcd.setCursor(12,1);//1,1
    lcd.print("OFF"); 
    }
digitalWrite(Relay1Pin, state1); 
digitalWrite(Relay2Pin, state2);
}
 
boolean mainMenu() {// Sets up main menu
 //Refresh the button pressed.
   //State = 0 every loop cycle.
   int state;
   //boolean mainstate;
   state = 0;
  //Set the Row 0, Col 0 position.
  lcd.setCursor(0,0);
  //If we are out of bounds on th menu then reset it.
    if (currentMenuItem <= -1) {// menus count from 0,1, etc
   currentMenuItem = 3; // increase to number of menus requred -1
   displayMenu(currentMenuItem);
  }
  if (currentMenuItem >= 4){//Increase to number of menus required
    currentMenuItem = 0;
    displayMenu(currentMenuItem);
  }
  int xcheck();
 state = xcheck();//Checks which button was pressed
   //If we have changed Index, saves re-draws.
   if (state != lastState) {
      if (state == 1) {
         //If Up
          currentMenuItem = currentMenuItem - 1; 
          displayMenu(currentMenuItem);
      } else if (state == 2) {
         //If Down
          currentMenuItem = currentMenuItem + 1;  
          displayMenu(currentMenuItem);
      } else if (state == 3) {
         //If Left
          Mainstate = false;
          currentMenuItem = 0;
          tempcall();// Needs to go back to main loop
      }else if (state == 4) {
         //If Selected
         selectMenu(currentMenuItem); 
         currentMenuItem = 0;    
      }
      //Save the last State to compare.
      lastState = state;
   } 

  return Mainstate;
}

//Display Menu Option based on Index.
void displayChoiceMenu(int x) {// Prints menu options
     switch (x) {
       case 1:
        lcd.clear();
        lcd.setCursor(4,0);
        lcd.print ("RED WINE");        
        break;
      case 2:
        lcd.clear();
        lcd.setCursor(3,0);
        lcd.print ("WHITE WINE");
        break;
      case 3:
        lcd.clear();
        lcd.setCursor(5,0);
        lcd.print ("CIDER");
        break;
      case 4:  
        lcd.clear();
        lcd.setCursor(6,0);
        lcd.print ("BEER");
        break;
    }
}
 

  
}
//Display Menu Option based on Index.
void displayMenu(int x) {// Prints menu options
     switch (x) {
       case 1:
        lcd.clear();
        lcd.setCursor(6,0);
        lcd.print ("VIEW");        
        lcd.setCursor(6,1);
        lcd.print ("TIME");
        break;
      case 2:
        clearPrintTitle();
        lcd.setCursor(6,1);
        lcd.print ("TEMP");
        break;
      case 3:
        clearPrintTitle();
        lcd.setCursor(6,1);
        lcd.print ("SPEED");
        break;
    }
}
 
//Print a basic header on Row 1.
void clearPrintTitle() {
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("CONFIGURE:");
}
 
//Show the selection on Screen.
void selectMenu(int x) {// Lowest menu level
int switchtemp();
int switchspeed();
void disptime();
   switch (x) {   
        case 2:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Set Temperature");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Temp = ");
        //Call the function that belongs to Option 2      
        switchtemp(); 
        lcd.setCursor(0,1); 
        delay(dispspeed);
        break;
        case 3:
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print ("Set Speed");
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Speed = ");
        //Call the function that belongs to Option 2
        switchspeed();
        lcd.setCursor(0,1); 
        delay(dispspeed);
        break;
        case 1:
          boolean stillSelecting = true;  // set because user is still selecting. 
          timeoutTime = millis() + menuTimeout; // set initial timeout limit.  
           do{    // loop while waiting for user to select.
            disptime(); 
            int s = 0; 
            s = xcheck();
            if (s == 3) { 
                stillSelecting = false;  // tell loop to bail out.
            }
        //return stillSelecting;    
        if (timeoutTime<millis()){  // user hasn't done anything in awhile
        stillSelecting = false;  // tell loop to bail out.   
            }
           }   
              
       while (stillSelecting == true);  
       lcd.clear(); 
       break;
    }
}

int xcheck(){//Checks which button is pushed when changing temp or motor speed
    int x = analogRead (0);
    int state = 0;
      //Check analog values from LCD Keypad Shield
    if (x > 0 && x < 90) {//Right  
   } else if (x > 91 && x < 250) {//Up
     timeoutTime = millis()+menuTimeout;  // reset timeout timer 
     state = 1;
   } else if (x > 251 && x < 400){//Down
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     state = 2;
    } else if (x > 400 && x < 600){ //Left
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     state = 3;
   } else if (x > 600 && x < 700){ //Select
     timeoutTime = millis()+menuTimeout;  // reset timeout timer
     state = 4;
   }    
   return state;
}

int switchtemp(){
    boolean done = false;
    timeoutTime = millis()+menuTimeout;  // reset timeout timer
    while(!done){
       if (timeoutTime<millis()){  // user hasn't done anything in awhile
        done = true;
        }      
       else {
      int s = 0;
      boolean set = false;
      s = xcheck(); 
      if (s != lastState) {
      lcd.setCursor(7,1); 
      lcd.print(settemp,1);
      lcd.print((char)223);
      lcd.print("C "); 
      if (s == 1) {// Up
         if (settemp+1 > toptemp){
           settemp = toptemp - 1;
           lcd.setCursor(7,1); 
           lcd.print("MAX TEMP");
           delay(keyspeed);
           lcd.setCursor(7,1); 
           lcd.print("          ");
           }
         settemp = settemp + 1;     
         delay(keyspeed);
      }
      if (s == 2) {// Down
        if (settemp-1 < mintemp){
           settemp = mintemp + 1;
           lcd.setCursor(7,1); 
           lcd.print("MIN TEMP");
           delay(keyspeed);
           lcd.setCursor(7,1); 
           lcd.print("          ");
           }
         settemp = settemp - 1; 
         delay(keyspeed);
      }
        
      if (s == 3) {//Back / Left
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("SET TEMP CHANGED");
        delay(dispspeed);
        done = true;
      }
      if (s == 4) {//Select
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("PRESS LEFT");
        delay(dispspeed);
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("TO SET TEMP");
        delay(dispspeed);
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Temp = ");
      }
      
      lastState = s;
      }
      }
    }
    
     Mainstate = false;
     tempcall();// Needs to go back to main loop
}

int switchspeed(){
    boolean done = false;
    timeoutTime = millis()+menuTimeout;  // reset timeout timer
    while(!done){
            if (timeoutTime<millis()){  // user hasn't done anything in awhile
              done = true;      
        } 
        else{
      int s = 0;
      boolean set = false;
      s = xcheck(); 
      if (s != lastState) {
      lcd.setCursor(8,1); 
      lcd.print(motorspeed,1);
      lcd.print(" RPM");

      if (s == 1) {// Up
         if (motorspeed+1 > maxspeed){
            motorspeed = maxspeed - 5;
            lcd.setCursor(8,1); 
            lcd.print("MAX RPM");
            delay(keyspeed);
            lcd.setCursor(8,1); 
            lcd.print("          ");
            }
          motorspeed = motorspeed + 5;  
          delay(keyspeed);
      }
      if (s == 2) {// Down
        if (motorspeed-1 < minspeed){
          motorspeed = minspeed + 5;
          lcd.setCursor(8,1); 
          lcd.print("MIN RPM");
          delay(keyspeed);
          lcd.setCursor(8,1); 
          lcd.print("          ");
          }
          motorspeed = motorspeed - 5;
          delay(keyspeed);
      }
        
      if (s == 3) {//Back / Left
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("SPEED CHANGED");
        delay(dispspeed);    
        done = true;
      }
      if (s == 4) {//Select
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("PRESS LEFT");
        delay(dispspeed);
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1); 
        lcd.print("TO SET SPEED");
        delay(dispspeed);
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(0,1);
        lcd.print("Speed = ");
      }   
      lastState = s;
      }
    }
    }
     Mainstate = false;
     tempcall();// Needs to go back to main loop
}

void disptime(){   
           lcd.clear();
           lcd.setCursor(0,0);//(3,0)
           lcd.write(byte(3));
           lcd.setCursor(2,0);//(5,0)
           // Send time
           lcd.print(rtc.getTimeStr()); 
           // Get RTC Temp
           lcd.setCursor(11,0);
           lcd.write(byte(1));
           lcd.setCursor(12,0);
           lcd.print(rtc.getTemp());
           // Send date
           lcd.setCursor(1,1);
           lcd.print(rtc.getDOWStr(FORMAT_SHORT));
           lcd.setCursor(5,1);
           lcd.print(rtc.getDateStr());      
           // Wait one second before repeating :)
           delay (1000);