#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 20, 4);
char *pszMenuItems[] =
{
"clock",
"MenuItem2",
"MenuItem3",
"MenuItem4"
};
void action1(void);
void action2(void);
void action3(void);
void action4(void);
typedef void(*myFunc)();
myFunc Functions[4] =
{
&action1,
&action2,
&action3,
&action4
};
int upButton = 10;
int downButton = 11;
int selectButton = 12;
int menu = 1;
void setup()
{
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(selectButton, INPUT_PULLUP);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (!rtc.isrunning()) {
Serial.println("RTC lost power, lets set the time!");
// Comment out below lines once you set the date & time.
// Following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(__DATE__, __TIME__));
}
updateMenu();
}
void loop()
{
static unsigned long
timeButtonRead = 0;
static byte
lastupButton = 0xff,
lastselButton = 0xff,
lastdownButton = 0xff;
byte
currButton;
unsigned long
timeNow;
//check buttons every 75mS
timeNow = millis();
if (timeNow - timeButtonRead < 75)
return;
timeButtonRead = timeNow;
//read the button...
currButton = digitalRead(downButton);
//...if it's state is not the same as last...
if (currButton != lastdownButton)
{
//...save the new state
lastdownButton = currButton;
//if it's low indicating it has been pressed...
if (currButton == LOW)
{
//process action; in this case, if menu is greater than 1...
if (menu > 1)
{
//...decrement it
menu--;
//and update the menu
updateMenu();
}//if
}//if
}//if
//same comments for downbutton apply for up and select
currButton = digitalRead(upButton);
if (currButton != lastupButton)
{
lastupButton = currButton;
if (currButton == LOW)
{
if (menu < 4)
{
menu++;
updateMenu();
}//if
}//if
}//if
currButton = digitalRead(selectButton);
if (currButton != lastselButton)
{
lastselButton = currButton;
if (currButton == LOW)
{
//call the function pointed to by menu in the Functions[] array
Functions[menu - 1]();
//when it returns, update the menu
updateMenu();
}//if
}//if
}//loop
void updateMenu()
{
lcd.clear();
Serial.print("\n\n\n\n");
for (int i = 0; i < 4; i++)
{
lcd.setCursor(0, i);
//if menu line is selected, print a '>', otherwise a space
if (i == (menu - 1))
{
Serial.print(">");
lcd.print(">");
}
else
{
Serial.print(" ");
lcd.print(" ");
}//else
//print the text of the line item
Serial.println(pszMenuItems[i]);
lcd.print(pszMenuItems[i]);
}//for
}//updateMenu
void action1()
{
while(true){
DateTime now = rtc.now(); //Attaches now to action1 scope
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Current Date & Time: ");
lcd.setCursor(0, 1);
lcd.print(now.year(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd .print(now.day(), DEC);
lcd.print(" ");
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
delay(1500)
}
}
//action1
void action2()
{
lcd.clear();
lcd.print(">Executing #2");
Serial.println(">Executing #2");
delay(1500);
}//action2
void action3()
{
lcd.clear();
lcd.print(">Executing #3");
Serial.println(">Executing #3");
delay(1500);
}//action3
void action4()
{
lcd.clear();
lcd.print(">Executing #4");
Serial.println(">Executing #4");
delay(1500);
}//action4
Instead of using delay to exit the function pointers, how can I exit the loop by pressing select once?
I tried while(!digitalRead(selectButton) == LOW){
delay(1500)} and even return; in place of delay
I even tried using a if loop instead with no luck, the screen exits but re enters the loop super fast while trying any of the buttons.
I would like to have a button press exit the loop and would prefer to add a 4th button as a exit button so I can work on variables in the menu without delay blocking input. :o