/*
Forum: https://forum.arduino.cc/t/day-timer-using-an-arduino/1238757
Wokwi: https://wokwi.com/projects/393161788734307329
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
const unsigned long secsPerMinute = 60;
const unsigned long secsPerHour = 60 * secsPerMinute;
const unsigned long maxSecsPerDay = 24 * secsPerHour;
unsigned long leftSecsPerDay;
unsigned long lastUpdate = 0;
int daysSpent = 0;
boolean countDownActive;
// Set the days to count here:
const int maxDaysSpent = 5;
void setup() {
Serial.begin(115200);
countDownActive = true;
lcd.backlight();
lcd.init();
lcd.begin(20, 4);
// Set a test date and time here the sketch
// shall start with
// E.g.: 5 days expired, at 23:59:55 hours:minutes:seconds
setTestDateTime(5, 23, 59, 55);
}
void loop() {
countDown();
}
void countDown() {
if (!countDownActive) {
return;
}
if (millis() - lastUpdate >= 1000) {
lastUpdate = millis();
leftSecsPerDay--;
if (leftSecsPerDay == 0) {
daysSpent++;
leftSecsPerDay = maxSecsPerDay;
}
if (daysSpent > maxDaysSpent) {
countDownActive = false;
}
if (countDownActive) {
printCountDown();
} else {
printLCD(" 0 - 00:00:00", 4, 2);
// Serial.println("Countdown stopped");
}
}
}
void printCountDown() {
int days = maxDaysSpent - daysSpent;
uint16_t hours = leftSecsPerDay / secsPerHour;
uint16_t minutes = (leftSecsPerDay - hours * secsPerHour) / secsPerMinute;
uint16_t seconds = leftSecsPerDay - hours * secsPerHour - minutes * secsPerMinute;
char buffer[40];
snprintf(buffer, sizeof(buffer), " %2d - %02d:%02d:%02d", days, hours, minutes, seconds);
// Serial.println(buffer);
printLCD(buffer, 4, 2);
}
void printLCD(char msg[40], int col, int row) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Days left");
lcd.setCursor(col, row);
lcd.print(msg);
}
void setTestDateTime(int daysDone, uint16_t hourAtDayDone, uint16_t minutesAtDayDone,
uint16_t secondsAtDayDone)
{
daysSpent = daysDone;
leftSecsPerDay = maxSecsPerDay - hourAtDayDone * secsPerHour - minutesAtDayDone * secsPerMinute - secondsAtDayDone;
}