Hi All
I am building a new project that will control a heat transfer system in my house, i know there are heaps out there already. I have made a number of basic projects before but this one is a bit more complex as it is all separated by distance and not in a nice box so I am looking for a steer in the right direction.
The system has two rooms down stairs and two rooms up stairs and the inline multi speed fan in the attic. Each room will have its own damper to control the air flow and the goal is each room will have a controller as well as an air temperature sensor for the room. The master controller will be in the lounge where the inlet grille is located as well as a temperature sensor. Each location has a dedicated Cat6 running from where the room controller will be to the attic where the fan is. (each 24v damper is wired back there as well)
I have developed some basic code (not complete but works) on a single Uno with 4 relays to control the 4 dampers and 2 relays to control fan speed (no sensors yet). I now need to investigate controlling everything remotely over ethernet. I have searched google, the tutorials and posts and they all lead to running webservers, over the web, or controlling things with PC's etc.
At this stage I would like to just have an LCD with 4 buttons (Up, dn . left, right), this will eventually be a touch screen, connected to a uno with a i2c ethernet module that communicates to another uno in the attic that controls all of the relays for the dampers and fan. That's step one. Step two will then get data (temp) from each room as well as requests "I want warm air" the main control will determine if the air in lounge is actually warm enough to send to the room. (it will also work as cooling)
Can anyone point me in the direction of some tutorials or sample code that will allow me to instead of making, for example, pin 4 HIGH or LOW on the local uno actually make pin 4 HIGH or LOW on a remote uno via ethernet (UPD, TCIP??) that will solve step one. Step two can wait.
For what its worth my code is below, but its not overly relative as it only works locally on an a single board but serves as an example of what I am trying to do, it was taken from anther project I did to make a spa pool controller.
Cheers
Al
//
// Version YY/MM/DD Comments
// V1 20260424 beginning - Adapted from Spa Controller
// V1.1 20260508 bug fixes and timing delays fixed
//********************************************************************************
//Setup for blink of life
const byte heartbeatLED = 13; // blinks to indicate not blocking LED 13 is onboard - change to output if external LED
unsigned long currentHB_Millis; // stores the current time in loop
unsigned long heartbeatMillis; // resets in HeartBeat function
unsigned long currentPOL_Millis; // stores the current time in loop
unsigned long ProofofLifeMillis; // resets in HeartBeat function
//Setup Libaries
#include <JC_Button.h> // https://github.com/JChristensen/JC_Button
#include <LiquidCrystal_I2C.h> // Include LiquidCrystal_I2C library
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include "Wire.h"
//{ // Variables
#define LEDon HIGH //pin---[220R]----[>|]---GND
#define LEDoff LOW
#define isPUSHED LOW //INPUT_PULLUP---pin---[N.O. switch]---GND
#define isRELEASED HIGH
#define enabled true
#define disabled false
#define backlightON HIGH
#define backlightOFF LOW
#define turnON HIGH //NO on relay
#define turnOFF LOW //NC on Relay
#define OpenDamper HIGH //NO on relay
#define CloseDamper LOW //NC on relay
// 1111111
// 1234567890123456
#define welcomeText "Air Handler V1.0" // change this to display custom message
#define FIRST_LINE 0 //text position for first line
#define SECOND_LINE 1 //text position for second line
//ANALOGS
//INPUTS
const byte Button1 = 6; // Left
const byte Button2 = 7; // Up
const byte Button3 = 8; // Down
const byte Button4 = 9; // Right
// Button function per mode Idle Setruntime Running Setup
Button btnLEFT(Button1); // Damper selc neg exit Damper sel exit
//Button 1 long press Setrun time nul nul
Button btnUP(Button2); // Damper open time up val up
Button btnDOWN(Button3); // Damper close time dn val dn
Button btnRIGHT(Button4); // Damp Select pos Confirm Confirm
// Button 4 long press // Setup nul nul
//OUTPUTS
const byte Damper1Relay = 2; // Rotates damper Gamesroom
const byte Damper2Relay = 3; // Rotates damper Spare bedroom
const byte Damper3Relay = 4; // Rotates damper Office
const byte Damper4Relay = 5; // Rotates damper Master bedroom
const byte FanLowRelay = 10; // runs fan at lower speed
const byte FanHighRelay = 11; // Runs fan at higher spped
//Flags
//bool Backlightflag = false; // could move local - don't know what this did
bool CheckSettingsFlag = true;
bool GamesroomDamperFlag =false;
bool Guest_BedroomDamperFlag =false;
bool Office_DamperFlag =false;
bool Master_BedroomDamperFlag =false;
bool FanLowFlag =false;
bool FanHighFlag =false;
//timing variables to store begin times
unsigned long currentMillis; //stores current millis
unsigned long previousMillis; //stores previous millis
unsigned long SensorMillis; // could move local to loop
unsigned long readLcdMillis; // Time to Read LCD displays
unsigned long powerUpMillis; // could move local Delay time for startup
unsigned long backlightMillis; // Stores time for backlight timeout
unsigned long damperMillis; // Stores time for damper movement
//timers for delays
const unsigned long readLcdDelay = 3 * 1000ul;
const unsigned long powerUpDelay = 5 * 1000ul;
const unsigned long settingsDelay = 20 * 1000ul;
const unsigned long timeoutDelay = 20 * 1000ul;
const unsigned long backlightDelay = 60 * 1000ul;
const unsigned long backlightTimeOut = 40 * 1000ul; // was in typedef struct in spa control
const unsigned long damperDelay = 10 * 1000ul; // reduced for testing
//Runs the menu system
byte menuList = 1; // List of menu items 1-9 in a group
byte menuGroup = 0; //Group of menus 0 being top layer
byte menuItems; // definds how many menuitems in menulist
byte PreviousmenuGroup; //defines last menu group for menu depth
//Main States MainStateMachine(); Called from void loop
// 0 1 2 3 4 5 6 7 8 9 10
enum MSTATES {m_StartUp, m_CheckSettings, m_ConfirmSettings, m_Idle, m_SetDampers, m_CheckSys, m_MoveDampers, m_RunUp, m_Running, m_Shutdown, m_Settings};
MSTATES mState = m_StartUp;
MSTATES lastMstate;
//********************************************************************************
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(heartbeatLED, OUTPUT);
//************************************
//LCD is 16 columns by 2 rows
lcd.init();
lcd.backlight(); // Backlight on
//Relay outputs
pinMode(Damper1Relay, OUTPUT);
pinMode(Damper2Relay, OUTPUT);
pinMode(Damper3Relay, OUTPUT);
pinMode(Damper4Relay, OUTPUT);
pinMode(FanLowRelay, OUTPUT);
pinMode(FanHighRelay, OUTPUT);
//Switch inputs
btnLEFT.begin();
btnRIGHT.begin();
btnUP.begin();
btnDOWN.begin();
}
//********************************************************************************
void loop() {
//*************************
// Run Blink of life every loop
BlinkofLife();
//*************************
ProofofLife();
currentHB_Millis = millis(); // capture arduino run time just for blink of life
currentMillis = millis(); //Set current millis for various functions
//***************************************
// Read button inputs
btnLEFT.read();
btnRIGHT.read();
btnUP.read();
btnDOWN.read();
//****************************
// check sensors once per second
/*
if (mState == m_StartUp) // check the sensors every loop to stabilise values
{
Sensors();
}
else if (currentMillis - SensorMillis > 10 * 1000ul)
{
//restart the TIMER
SensorMillis = currentMillis;
Sensors();
}
*/
BackLightControl(); //sets backlight for LCD
//Check Statemachine
MainStateMachine();
}
//********************************************************************************
//END of LOOP
//********************************************************************************
//**********************************************
//FUNCTIONS
//**********************************************
// Standard Blink of life to be in all programs
void BlinkofLife() // basic function to blink LED to show code is not blocked
{
currentHB_Millis = millis();
if (currentHB_Millis - heartbeatMillis >= 800)
{
//restart the TIMER
heartbeatMillis = currentHB_Millis;
//Toggle heartbeat LED
digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
}
}
void ProofofLife() // basic function serial print for debugging comment out in final vervion
{
currentPOL_Millis = millis();
if (currentPOL_Millis - ProofofLifeMillis >= 2000)
{
//restart the TIMER
ProofofLifeMillis = currentHB_Millis;
Serial.println(mState);
Serial.println(FanLowFlag);
Serial.println(FanHighFlag);
Serial.println(GamesroomDamperFlag);
Serial.println(Guest_BedroomDamperFlag);
Serial.println(Office_DamperFlag);
Serial.println(Master_BedroomDamperFlag);
}
}
//********************************************************************************
// Welcome message at startup - set message in Define statements
void welcomeMessage()
{
// C R
lcd.setCursor(0, 0);
// 111111
// 0123456789012345
lcd.print(welcomeText); // set in #define statements
} //END of welcomeMessage()
//timeout function
void isTimeout()
{
if (currentMillis >= previousMillis + timeoutDelay) {
lcd.clear();
mState = lastMstate;
menuList = 1;
menuGroup = 0;
}// end if
if (btnLEFT.isPressed() || btnUP.isPressed() || btnDOWN.isPressed() || btnRIGHT.isPressed())
{
previousMillis = currentMillis; // reset the time out if a button is pushed
}
}// end timeout
void BackLightControl()
{
if (currentMillis - backlightMillis > backlightTimeOut) //this had a reference to ContSettings in spa control
{
//restart the TIMER
backlightMillis = currentMillis;
lcd.setBacklight(backlightOFF);
// Backlightflag = false;
}
else if (btnLEFT.isPressed() || btnUP.isPressed() || btnDOWN.isPressed() || btnRIGHT.isPressed())
{
lcd.backlight();
backlightMillis = currentMillis;
previousMillis = currentMillis; // reset the time out if a button is pushed
// Backlightflag = true;
}
}
//*******************************************************************************
// M A I N s t a t e M a c h i n e ( )
//********************************************************************************
void MainStateMachine()
{
switch (mState)
{
//********************* 0
case m_StartUp:
{
if (powerUpMillis > powerUpDelay)
{
//do the following once after power up delay
lcd.backlight();
lcd.clear();
//RTC.read(tm);
//LCD_Clock_Function(); // check RTC is working
readLcdMillis = currentMillis;
mState = m_CheckSettings; // Progress to next state
}
else
(powerUpMillis = currentMillis);
welcomeMessage(); // Show Welcome Message until power up delay reached
} //END case
break;
//********************1
case m_CheckSettings:
{
if (currentMillis >= readLcdMillis + readLcdDelay) // show date and time on LCD until delay reached
{
lcd.clear();
mState = m_ConfirmSettings;
}
else
{
readLcdMillis = currentMillis;
// Show_Time(FIRST_LINE);
// Show_Date(SECOND_LINE);
// welcomeMessage(); // Show Welcome Message - place holder until settings functions added
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("waiting"));
}
}
break;
//**********************2
case m_ConfirmSettings:
{
// CheckSettingsFlag = ConfirmTimeDate(); // returns true if accepted or false if edit required.
if (CheckSettingsFlag == true) // currently fixed in flags as true, needs to be changed to false
{
lcd.clear();
mState = m_Idle; // only progress once Check Settings Flag is true.
}
}
break;
//*********************3
case m_Idle:
{
lcd.setCursor(0, 0);
lcd.print(F("Idle"));
lcd.setCursor(0, 1);
lcd.print(F("Select Room"));
//Buttons
buttoninputs();// this moves to to set dampers
lastMstate = m_Idle; // ant timeout will lead here
} //END case
break;
//*********************4
case m_SetDampers:
{
isTimeout(); // times out to lastMstate
menuButtons(); // calls buttons to navigate menu
MenuFunctions(); // calls the main menu
}
break;
//*********************5
case m_CheckSys:
{
Serial.println("check sys");
// first if tests if all dampers now set to close but fan is still running then move to shutdown proceedure to turn off fan and close dampers
if(GamesroomDamperFlag == false && Guest_BedroomDamperFlag == false && Office_DamperFlag == false && Master_BedroomDamperFlag == false && FanLowFlag == true){
FanLowFlag = false;
FanHighFlag = false;
damperMillis = currentMillis;
lcd.clear();
mState =m_Shutdown;}
// Test if either gamesroom or guest bedroom has been set to open and the fan is already running then increase fan speed
else if ((GamesroomDamperFlag == true || Guest_BedroomDamperFlag == true) && FanLowFlag == true){
FanLowFlag = true;
FanHighFlag = true;
lcd.clear();
damperMillis = currentMillis;
mState = m_MoveDampers;
}
// Test if Office or master beedroom has been opened while the other is running then increase fan speed
else if (Office_DamperFlag == true && Master_BedroomDamperFlag == true && FanLowFlag == true){
FanLowFlag = true;
FanHighFlag = true;
lcd.clear();
damperMillis = currentMillis;
mState = m_MoveDampers;
}
// remaining option is a either office or masterbedroom is now running by itself and to decrease fan to low
else if (FanLowFlag == true && (Office_DamperFlag == true || Master_BedroomDamperFlag == true)){
FanHighFlag = false;
lcd.clear();
damperMillis = currentMillis;
mState = m_MoveDampers;
}
//If the program enters the system check and the fan is not going then proceed to startup to open first damper
else if (FanLowFlag == false){
FanLowFlag = true; // fanlow must always be running
lcd.clear();
damperMillis = currentMillis;
mState = m_RunUp;
}
} //END case
break;
//*********************6
case m_RunUp:
{
lcd.setCursor(0,0);
lcd.print (F("STARTUP"));
Serial.println("runup");
//start opens the first damper that is true as only one can be set at a time the first one will tigger startup
if(GamesroomDamperFlag == true){
digitalWrite (Damper1Relay, OpenDamper);
FanHighFlag = true;
} // Closes damper Gamesroom
if(Guest_BedroomDamperFlag == true){
digitalWrite (Damper2Relay, OpenDamper);
FanHighFlag = true;
} // Closes damper Spare bedroom
if(Office_DamperFlag == true){
digitalWrite (Damper3Relay, OpenDamper);
} // Closes damper Office
if(Master_BedroomDamperFlag == true){
digitalWrite (Damper4Relay, OpenDamper);
} //Closes damper Master bedroom
// if(GamesroomDamperFlag == TRUE || Guest_bedroomDamperFlag == TRUE){
// FanHighFlag = True;
// }
// if (Office_DamperFlag == True && Master_BedroomDamperFlag == TRUE){
// FanHighFlag = True;
// }
if (currentMillis >= damperMillis + damperDelay) { // delays while damper opens before going to running
if(FanLowFlag == true){
digitalWrite(FanLowRelay, turnON);
}
if(FanHighFlag == true){
digitalWrite(FanHighRelay, turnON);
}
lcd.clear();
mState = m_Running;
menuList = 1;
menuGroup = 0;
}// end if
//damperMillis = currentMillis;
}
break;
//*********************7
case m_MoveDampers:
{
// this state only entered if the fan and one damper is already open, test each damper to find any that are to open or close and then set
if ((digitalRead(Damper1Relay == CloseDamper) && GamesroomDamperFlag == true)){
digitalWrite(Damper1Relay, OpenDamper);
}
else {
digitalWrite(Damper1Relay, CloseDamper);
}
if ((digitalRead(Damper2Relay == CloseDamper) && Guest_BedroomDamperFlag == true)){
digitalWrite(Damper2Relay, OpenDamper);
}
else {
digitalWrite(Damper2Relay, CloseDamper);
}
if ((digitalRead(Damper3Relay == CloseDamper) && Office_DamperFlag == true)){
digitalWrite(Damper3Relay, OpenDamper);
}
else {
digitalWrite(Damper3Relay, CloseDamper);
}
if ((digitalRead(Damper4Relay == CloseDamper) && Master_BedroomDamperFlag == true)){
digitalWrite(Damper4Relay, OpenDamper);
}
else {
digitalWrite(Damper4Relay, CloseDamper);
}
if ((digitalRead(Damper1Relay == CloseDamper) && GamesroomDamperFlag == true)){
digitalWrite(Damper1Relay, OpenDamper);
}
else {
digitalWrite(Damper1Relay, CloseDamper);
}
if (currentMillis >= damperMillis + damperDelay) { // delays while damper opens to prevent damper being changed while moving
lcd.clear();
mState = m_Running;
menuList = 1;
menuGroup = 0;
}// end if
damperMillis = currentMillis;
} //END case
break;
//***********************8
case m_Running:
{
lcd.setCursor(0, 0);
lcd.print(F("Running"));
if(FanHighFlag == true && FanHighFlag == true){
lcd.setCursor(0,1);
lcd.print(F("fan high"));
}
else if (FanHighFlag == false){
lcd.setCursor(0,1);
lcd.print(F("fan low"));
}
//Button
buttoninputs(); //moves to set dampers
if(FanHighFlag == true){
digitalWrite(FanHighRelay, turnON);
}
else digitalWrite(FanHighRelay, turnOFF);
}
break;
//*********************9
case m_Shutdown:
{
lcd.setCursor(0, 0);
lcd.print (F("SHUTDOWN"));
digitalWrite (FanHighRelay, turnOFF);
digitalWrite (FanLowRelay, turnOFF);
FanLowFlag =false;
FanHighFlag =false;
digitalWrite (Damper1Relay, CloseDamper); // Closes damper Gamesroom
digitalWrite (Damper2Relay, CloseDamper); // Closes damper Spare bedroom
digitalWrite (Damper3Relay, CloseDamper); // Closes damper Office
digitalWrite (Damper4Relay, CloseDamper); //Closes damper Master bedroom
if (currentMillis >= damperMillis + damperDelay) { // delays while damper closes before going to idle
lcd.clear();
mState = m_Idle;
menuList = 1;
menuGroup = 0;
}// end if
lcd.setCursor(0, 1)
lcd.print(f("shutting Down"));
//shutdown function leds to idle state;
} //END case
break;
//*********************10
case m_Settings:
{
isTimeout(); //times out to previous state eith idle or run
lcd.setCursor(0, 0);
lcd.print(F("Settings"));
//Buttons
buttoninputs();
} //END case
break;
}
}
void buttoninputs() //used in main state machine
{
//****************************************************
if(btnLEFT.wasPressed()){
backlightMillis = currentMillis;
if(mState == m_Idle ){
lcd.clear();
mState = m_SetDampers;
}
else if(mState == m_SetDampers){
lcd.clear();
mState = lastMstate; //cancels out of set dampers
}
else if(mState == m_Running){
// If timer expires users can add 20 min to spa time
lcd.clear();
mState = m_SetDampers;
}
}// end Left Button was pressed
//**************************************************************************
/*
if(btnLEFT.pressedFor(1000)){
backlightMillis = currentMillis;
if(mState == m_InUse){
ExitTimeMillis = currentMillis; // start the exit delay timer
lcd.clear();
mState = m_ExitDelay;
}
}// end if Left Button Pressed for 1000ms
*/
//R I G H T B U T T O N **************************************************************************
if (btnRIGHT.wasPressed()){
backlightMillis = currentMillis;
if(mState == m_Idle || mState == m_Running){
lcd.clear();
mState = m_SetDampers;
}
} //end if button right was pressed
/*
//**************************************************************************
if(btnRIGHT.pressedFor(1000)){
backlightMillis = currentMillis;
if(mState == m_Idle || mState == m_Run){
lcd.clear();
mState = m_Settings;
}
else if(mState == m_Setflags){
lcd.clear();
//call menu turn on set
}
}// end if Left Button Pressed for 1000ms
*/
//U P B U T T O N ****************************************************************************
if (btnUP.wasPressed()){
if(mState == m_Idle || mState == m_Running){
lcd.clear();
mState == m_SetDampers;
}
} //end if button up was pressed
//D O W N B U T T O N ***************************************************************************
if (btnDOWN.wasPressed()){
backlightMillis = currentMillis;
if(mState == m_Idle || mState == m_Running){
lcd.clear();
mState == m_SetDampers;
}
}
} //End Button Input
//*************************************************
void menuButtons()
{
if (btnUP.wasPressed()){
Serial.println("button up");
lcd.clear();
if (menuList < menuItems) menuList++; //0 being the base menu
}
if (btnDOWN.wasPressed()){
Serial.println("button dn");
lcd.clear();
if (menuList > 1) menuList--;
}
if (btnRIGHT.wasPressed()){
Serial.println("button right");
if(menuGroup == 0){
lcd.clear();
menuGroup = menuList * 10; //moves to 10 20 30 40
menuList = 1;
}
else if (menuGroup != 0){
lcd.clear();
menuGroup = menuGroup + menuList; //moves to 11 12 13 21 22 22 23
menuList = 1;
}
}
if(btnLEFT.wasPressed()){
if (menuGroup == 0){
lcd.clear();
menuGroup = 0;// add in here that if menuList is equal of less than 5 and menuGroup 0 then set dampers off by going to menu case 1 2 3 . otherwise exit turning on would be 10 11 12
menuList = 1;
mState = lastMstate; //exits out
}
else if (menuGroup = PreviousmenuGroup){ //if we are in a sub menu move back
menuGroup = 0;
menuList = 1;
}
else
{
menuGroup = PreviousmenuGroup; // this needs checking
menuList = 1;
}
}
}
//bool GamesroomDamperFlag =false;
//bool Guest_BedroomDamperFlag =false;
//bool Office_DamperFlag =false;
//bool Master_BedroomDamperFlag =false;
void MenuFunctions(){
isTimeout(); // times out to lastMstate
switch (menuGroup){
case 0:
{
//show main menu 1-9
PreviousmenuGroup = 0;
MainMenu();
}
break;
case 10:
{
Master_BedroomDamperFlag = !Master_BedroomDamperFlag;
lcd.clear();
menuGroup = 0;
menuList = 1;
mState = m_CheckSys;
}
break;
case 20:
{
Office_DamperFlag = !Office_DamperFlag;
lcd.clear();
menuGroup = 0;
menuList = 1;
mState = m_CheckSys;
}
break;
case 30:
{
Guest_BedroomDamperFlag = !Guest_BedroomDamperFlag;
lcd.clear();
menuGroup = 0;
menuList = 1;
mState = m_CheckSys;
}
break;
case 40:
{
GamesroomDamperFlag = !GamesroomDamperFlag;
lcd.clear();
menuGroup = 0;
menuList = 1;
mState = m_CheckSys;
}
break;
case 50:
{
GamesroomDamperFlag =false;
Guest_BedroomDamperFlag =false;
Office_DamperFlag =false;
Master_BedroomDamperFlag =false;
mState = m_Shutdown;
}
break;
case 60:
{
// show Submenu 2 items
PreviousmenuGroup = 20;
Submenu2(); // select comfort times to edit
}
break;
case 70:
{
Submenu3();
}
case 71:
{
// mState = m_EditDateTime;
// tState = EditTime;
menuGroup = 0;
menuList = 1;
}
break;
}
}
//bool GamesroomDamperFlag =false;
//bool Guest_BedroomDamperFlag =false;
//bool Office_DamperFlag =false;
//bool Master_BedroomDamperFlag =false;
//bool FanLowFlag =false;
//bool FanHighFlag =false;
void MainMenu(){
menuItems = 7;
switch(menuList){
case 1:
{
// 1111111
// 1234567890123456
if(Master_BedroomDamperFlag == false){
lcd.setCursor(0,0);
lcd.print(F(" Master bedroom "));
lcd.setCursor(0,1);
lcd.print(F(" ON-> "));
}
else if (Master_BedroomDamperFlag == true){
lcd.print(F(" Master bedroom "));
lcd.setCursor(0,1);
lcd.print(F(" OFF-> "));
}
}
break;
case 2:
{
if(Office_DamperFlag == false){
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" Office "));
lcd.setCursor(0,1);
lcd.print(F(" ON-> "));
}
else if (Office_DamperFlag == true){
lcd.print(F(" Office "));
lcd.setCursor(0,1);
lcd.print(F(" OFF-> "));
}
}
break;
case 3:
{
if(Guest_BedroomDamperFlag == false){
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" Guest Bedroom "));
lcd.setCursor(0,1);
lcd.print(F(" ON-> "));
}
else if (Guest_BedroomDamperFlag == true){
lcd.print(F(" Guest Bedroom "));
lcd.setCursor(0,1);
lcd.print(F(" OFF-> "));
}
}
break;
case 4:
{
if(GamesroomDamperFlag == false){
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" Games Room "));
lcd.setCursor(0,1);
lcd.print(F(" ON-> "));
}
else if (GamesroomDamperFlag == true){
lcd.print(F(" Games Room "));
lcd.setCursor(0,1);
lcd.print(F(" OFF-> "));
}
}
break;
case 5:
{
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" All Off "));
lcd.setCursor(0,1);
lcd.print(F(" Yes-> "));
}
break;
case 6:
{
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" Set Run Time "));
lcd.setCursor(0,1);
lcd.print(F(" Enter->"));
}
break;
case 7:
{
lcd.setCursor(0,0);
// 1111111
// 1234567890123456
lcd.print(F(" Setting "));
lcd.setCursor(0,1);
lcd.print(F(" Enter->"));
}
break;
}
}
void Submenu2(){
menuItems = 1;
switch (menuList){
case 1:
{
lcd.setCursor(0,0);
lcd.print(F("Set Timer"));
}
break;
}
}
void Submenu3(){
menuItems = 1;
switch (menuList){
case 1:
{
lcd.setCursor(0,0);
lcd.print(F("Edit Time / Date"));
}
break;
}
}
//******************************************************************************************************************
//End Program
//*******************************************************************************************************************
//

