Need help on an LCD countdown

Trying to create a code such that when an input is received (it can be assumed as a button), it displays a set of information and a countdown. My LCD has 4 rows and the screen can take up to four rows. I am wondering whether there is a way to run multiple countdowns on my LCD at once.

So far, I have managed to code everything except for the countdown feature. I attempted a while loop but it can't run multiple at once, meaning that I'm stuck on ideas for how to not have it countdown only one item at a time until zero.

Any advice? I am able to use many Arduinos and each have them control their own row, but I'm not sure how.

If it helps, I'm using Adafruit's 20x4 LCD.

If you wnt multipe timers running i would suggest using the millis() function. It's a internal timer that is is always counting in the background(up to 3days i think). You can learn more about it here.

I think it is somewhere in the sketch that I cannot see. Posting that using code tags should get you an answer.

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!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.