Hi @stormitystorm ,
here is an example of a simple countdown using the millis() function for one countdown:
Sketch Simple CountDownTimer
/*
Forum: https://forum.arduino.cc/t/need-help-on-an-lcd-countdown/1226322
Wokwi: https://wokwi.com/projects/390277926505100289
2024/02/20
ec2021
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
byte row = 0;
byte col = 3;
int value = 10+1;
unsigned long lastCount = 0;
unsigned long cdInterval = 1000;
char name[16] = "One";
boolean hasNewCountDownValue() {
if (value <= 0) return false;
if (millis() - lastCount > cdInterval) {
lastCount = millis();
value--;
return true;
}
return false;
}
void printToLCD() {
char buf[16];
snprintf(buf, 16, "%s %5d", name, value);
lcd.setCursor(col, row);
lcd.print(buf);
}
void setup() {
Serial.begin(115200);
Serial.println("Start");
lcd.init();
lcd.setCursor(0, 0);
lcd.clear();
lcd.backlight();
}
void loop() {
if (hasNewCountDownValue() ) {
printToLCD();
}
evaluateSerialCmd();
}
void evaluateSerialCmd() {
if (Serial.available()) {
char c = Serial.read();
if ( c == '1') {
if (value == 0) {
value = 10+1;
}
}
}
}
You can use Serial commands '1' or '2' to restart count down one or two if they are done. Use 'a' or 'A' to restart both.
You can check it out on Wokwi; https://wokwi.com/projects/390277926505100289
One simple but not recommended way would be just to copy the functions and variables and give them separate names ... However that means that code with identical functionality is copied and makes skteches hard to maintain and debug.
There are many possibilities to increase the number of countdown timers based on arrays, structs and/or classes ... Feel free to check this one out which is based on a structure that combines the most relevant data and functions for several count down objects:
Sketch CountDownTimer
/*
Forum: https://forum.arduino.cc/t/need-help-on-an-lcd-countdown/1226322
Wokwi: https://wokwi.com/projects/390275218801696769
2024/02/20
ec2021
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
struct CountDownType {
byte row = 0;
byte col = 0;
int value = 0;
int startValue = 0;
unsigned long lastCount = 0;
unsigned long cdInterval = 1000;
char name[16] = "";
void init(unsigned long countDownInterval, byte Col, byte Row, char Name[16]) {
cdInterval = countDownInterval;
row = Row;
col = Col;
strncpy( name, Name, 16);
}
void start(int startVal) {
value = startVal + 1;
}
boolean hasNewCountDownValue() {
if (value <= 0) return false;
if (millis() - lastCount > cdInterval) {
lastCount = millis();
value--;
return true;
}
return false;
}
void printToLCD() {
char buf[16];
snprintf(buf, 16, "%s %5d", name, value);
lcd.setCursor(col, row);
lcd.print(buf);
}
};
CountDownType cdOne;
CountDownType cdTwo;
void setup() {
Serial.begin(115200);
Serial.println("Start");
lcd.init();
lcd.setCursor(0, 0);
lcd.clear();
lcd.backlight();
cdOne.init(1000, 3, 0, "One ");
cdTwo.init( 500, 3, 1, "Two ");
cdOne.start(10);
cdTwo.start(20);
}
void loop() {
if (cdOne.hasNewCountDownValue() ) {
cdOne.printToLCD();
}
if (cdTwo.hasNewCountDownValue() ) {
cdTwo.printToLCD();
}
evaluateSerialCmd();
}
void evaluateSerialCmd() {
if (Serial.available()) {
char c = Serial.read();
switch (c) {
case '1':
if (cdOne.value == 0) {
cdOne.start(10);
}
break;
case '2':
if (cdTwo.value == 0) {
cdTwo.start(20);
}
break;
case 'A':
case 'a':
if (cdOne.value == 0 && cdTwo.value == 0) {
cdOne.start(10);
cdTwo.start(20);
}
break;
}
}
}
You can use Serial commands '1' to restart count down one if done.
Again on Wokwi: https://wokwi.com/projects/390275218801696769
You can of course also develop your own multiple countdowns using the functions of the first sketch together with arrays for the different "timers" ... That would be a nice exercise!
Good luck and have fun!