//Adapted from ahmedebeed555
// https://www.youtube.com/watch?v=1wWdtkLxMaQ
// https://www.instructables.com/Arduino-Digital-Clock-Without-RTC-Real-Time-Clock-/
//PLEASE NOTE: If we use delays at all in this code, we could lose entire minutes in time!
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
/* Keypad setup */
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {12, 11, 10, 9};
byte colPins[KEYPAD_COLS] = {8, 7, 6, 5};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 column and 4 rows
int RTCHour = 23;
int RTCMinute = 59;
int RTCSecond = 40;
int flag = 0;
int TIME = 0;
const int hourSet = 0;
const int minuteSet = 1;
int hourSetState = 0;
int minuteSetState = 0;
//millis controllers
int prevSecond;
//---------------------- KEY INPUTS ---------------------------
char getKeyInput(){
char key = 0;
while (key == 0) {
key = keypad.getKey();
if (key >= '0' && key <= '9') {
//lcd.print(key);
}
}
return key;
}
void printTimeHeader(){
lcd.setCursor(0, 0);
prevSecond = (millis()/1000)%60;
RTCSecond = prevSecond;
//RTCSecond = RTCSecond + 1;
lcd.print("TIME:" );
//print leading 0 if necessary
lcd.setCursor(5,0);
if (RTCHour < 10) lcd.print("0");
lcd.print(RTCHour);
lcd.print(":");
lcd.setCursor(8,0);
//print leading 0 if necessary
if (RTCMinute < 10) lcd.print("0");
lcd.print(RTCMinute);
lcd.print(":");
lcd.setCursor(11,0);
//print leading 0 if necessary
if (RTCSecond < 10) lcd.print("0");
lcd.print(RTCSecond);
}
void correctTime(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("TIME:" );
//print leading 0 if necessary
lcd.setCursor(5,0);
lcd.print("--");
lcd.print(":");
lcd.setCursor(8,0);
lcd.print("--");
lcd.print(":");
//no need to correct seconds
// lcd.setCursor(11,0);
// lcd.print("--");
//starting with hours:
int i = 0; //to count number of keys pressed. expecting 6
int j = 0; //to move the cursor to the right position
String keys = "";
int timevals[6];
while (keys.length() < 4){
keys += getKeyInput();
if(i == 2) j = 1; //move it to the correct position
lcd.setCursor((i + j + 5),0);
lcd.print(keys[i]);
//convert to int
timevals[i] = keys[i] - '0';
i++;
}
lcd.setCursor(0,1);
//untidy combination into the actual time: and lazy wrap around of time:
RTCHour = (timevals[0])*10 + timevals[1];
if (RTCHour >= 24) RTCHour -= 24;
RTCMinute = (timevals[2])*10 + timevals[3];
if (RTCMinute >= 60) RTCMinute -=60;
// RTCSecond = (timevals[4])*10 + timevals[5];
}
void updateLCDTime(){
prevSecond = RTCSecond;
//minutes
if (RTCSecond == 0)
{
RTCMinute ++;
}
if (RTCMinute >= 60)
{
RTCMinute = 0;
RTCHour = RTCHour + 1;
flag = flag + 1;
}
if (RTCHour >= 24)
{
RTCHour = 0;
}
//print leading 0 if necessary
lcd.setCursor(5,0);
if (RTCHour < 10) lcd.print("0");
lcd.print(RTCHour);
lcd.print(":");
lcd.setCursor(8,0);
//print leading 0 if necessary
if (RTCMinute < 10) lcd.print("0");
lcd.print(RTCMinute);
lcd.print(":");
lcd.setCursor(11,0);
//print leading 0 if necessary
if (RTCSecond < 10) lcd.print("0");
lcd.print(RTCSecond);
}
//---------------------------- SETUP ---------------------------------
void setup()
{
lcd.begin(16, 2);
pinMode(hourSet, INPUT_PULLUP);
pinMode(minuteSet, INPUT_PULLUP);
//RTCSecond = millis()/1000;
//give it time to settle before we start
//delay(1000);
RTCHour = 23;
RTCMinute = 59;
//initialise time screen
printTimeHeader();
}
//----------------------------------- LOOP ----------------------------
void loop()
{
RTCSecond = (millis()/1000)%60;
if (flag == 24) flag = 0;
//only change the necessary fields
//if (RTCSecond > prevSecond){ //until we solve the 0 issue
if (RTCSecond != prevSecond){
updateLCDTime();
}
//TODO: use keypad for correcting time
if (keypad.getKey() == '*'){
correctTime();
}
}