Hi @roamingal ,
here is a sketch that also performs a day countdown based on the millis() function
- therefore precision limited to the internal Arduino millis() function and
- it will start from the beginning in case of a restart (which could be handled in case a RTC would be used)
/*
Forum: https://forum.arduino.cc/t/day-timer-using-an-arduino/1238757
Wokwi: https://wokwi.com/projects/393146816707048449
*/
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;
// 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 {
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);
}
void setTestDateTime(int daysDone, uint16_t hourAtDayDone, uint16_t minutesAtDayDone,
uint16_t secondsAtDayDone)
{
daysSpent = daysDone;
leftSecsPerDay = maxSecsPerDay - hourAtDayDone * secsPerHour - minutesAtDayDone * secsPerMinute - secondsAtDayDone;
}
You can check it out on Wokwi: https://wokwi.com/projects/393146816707048449
I have implemented a simple function that sets certain variables which is only required for testing purposes:
// 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);
Based on the naming of the variables and functions, it should (I hope) be more or less “self-explanatory” (I hope
).
Good luck!
ec2021
A version for LCD on Wokwi https://wokwi.com/projects/393161788734307329 :
Sketch for LCD
/*
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;
}