Why does the timer shown on LCD reach the countdown later than it is supposed to

I am trying to implement a countdown timer showing how many seconds, minutes, hours, and days are remaining. The LCD is used for showing the remaining time.

However, the issue I am facing is that the timer shows a few seconds to a few minutes (depending on how long the countdown is) even after the time passes in real life. For example, if I set the timer for 1 hour, it shows that there are 30s remaining even though an hour has passed (using phone and clock as reference). The amount of time remaining seems to be proportional to the length of the countdown timer (longer countdown -> longer time remaining after completion)

My guess is that the code takes up some time each time the loop is run, but that interval seems to be too small to cause such an observable difference. Please advise on what could be the possible reason for this

Thanks a lot in advance!

I followed the schematic shown on the official page (https://docs.arduino.cc/learn/electronics/lcd-displays) to set up the LCD. The following is the code I used to countdown:

#include <LiquidCrystal.h>
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int S = 0; // count seconds
int M = 0; // count minutes
int H = 1; // count hours
int D = 0; // count days

int sec_to_min = 60;
int min_to_hour = 60;
int hour_to_day = 24;

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("hello, world!");
}

void loop() {

S--;
delay(1000);

if (S < 0) {
M--;
S = sec_to_min-1;
}
if (M < 0) {
H--;
M = min_to_hour-1;
}
if (H < 0) {
D--;
H = hour_to_day-1;
M = min_to_hour-1;
S = sec_to_min-1;
}

lcd.setCursor(0, 1);

if (D < 0) {
lcd.print("Countdown Finished");
while(1){
}
} else if (D < 10) {
lcd.print("0");
lcd.setCursor(1,1);
lcd.print(D);
} else {
lcd.print(D);
}

lcd.setCursor(2, 1);
lcd.print("D ");

if (H > 9) {
lcd.setCursor(4, 1);
lcd.print(H);
} else {
lcd.setCursor(4, 1);
lcd.print("0");
lcd.setCursor(5, 1);
lcd.print(H);
}

lcd.setCursor(6, 1);
lcd.print("H ");

if (M > 9) {
lcd.setCursor(8, 1);
lcd.print(M);
} else {
lcd.setCursor(8, 1);
lcd.print("0");
lcd.setCursor(9, 1);
lcd.print(M);
}

lcd.setCursor(10, 1);
lcd.print("M ");

if (S > 9) {
lcd.setCursor(12, 1);
lcd.print(S);
} else {
lcd.setCursor(12, 1);
lcd.print("0");
lcd.setCursor(13, 1);
lcd.print(S);
}
lcd.setCursor(14, 1);
lcd.print("S");
}

use code tag for proper code formatting.

Suggest you make a TIMER based on seconds.

Example, a 10 day setting would be 864,000 seconds.

When a non-blocking 1000 milli second TIMER expires, decrement the above TIMER.

When 1000ms expires, convert the TIMER to days/hours/minutes/seconds and display on the LCD.

Actually, an RTC like DS3231 is a much better and accurate solution.

unsigned      hr   = 1;
unsigned      mins;
unsigned long sec = (hr * 3600) + (60 * mins);
unsigned long msecLst;

char s [80];

// -----------------------------------------------------------------------------
void loop()
{
    unsigned long msec = millis ();
    if (msec - msecLst < 1000)
        return;

    msecLst = msec;

    if (0 == --sec)
        sec = 3600;

    hr   = sec / 3600;
    mins = (sec / 60) % 60;

    sprintf (s, " %2u:%02u:%02lu", hr, mins, sec % 60);
    Serial.println (s);
}

void setup() {
    Serial.begin (9600);
}
1 Like

Okay, I will retry the setup using millis() instead of delay(). Thanks!

I would like to show everytime an hour or day is expired. But I get the gist of what you are trying to say. Thanks!

Thanks a lot for your effort! This seems so much simpler.

Also, can you please explain why it isn't recommended to use the delay() function and what part of the code would take up time causing the slow-down? (would it be the lcd.setCursor or lcd.print statement or anything else?)

I used the delay() function so that the code is blocked from running the other statements unnecessarily, thinking that it might lead to a slow-down (it happened anyway)

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