Help arduino countdown code doesn't repeat

Hi! so Im curently in a project that requires arduino to repeat countdown and show it on i2c lcd. But the code that i run doesn't repeated itself and after the countdown reach 00:00 it stops. is there any ways to repeat the countdown after it reach 00:00? Im working with arduino uno, and this is the code.

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
// Include Wire Library for I2C


// Define LCD pinout
const int  en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;

// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;

LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

long hour = 0, minute = 0, second = 59;
long countdown_time = (hour * 3600) + (minute * 60) + second;
void setup() {
  //  lcd.init();
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("HH:MM:SS");
}

void count() {
  long countdowntime_seconds = countdown_time - (millis() / 1000);
  if (countdowntime_seconds >= 0) {
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(0, 0);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }
  delay(500);
}

void loop() {

count();
}

thank you in advice!

That line is just making countdowntime_seconds more and more negative; there's nothing to make it >=0 again so this test if (countdowntime_seconds >= 0) continues to fail.

delay(500); Bad idea using delay( )

Master what is said here:

When millis() is greater than 59999 (60 seconds or greater) your count() function stops doing anything except the "delay(500);".

Usually, you start a timer by storing the start time:
static unsigned long startTime = millis()

Then you used elapsed time (millis() minus startTime) to see how long the timer has been running.

long countdowntime_seconds = countdown_time - ((millis() - startTime) / 1000);

Then, when the timer expires, you can restart it:

void count() {
  long countdowntime_seconds = countdown_time - ((millis() - startTime) / 1000);
  if (countdowntime_seconds >= 0) 
  {
. . .
  }
  else
  {
    startTime = millis();  // Restart countdown
  }
  delay(500);
}

consider, simple incrementing clock
not sure how you want to reset the countdown

#define MyHW
#ifdef MyHW
enum { POSITIVE };
struct LiquidCrystal_I2C {
    LiquidCrystal_I2C (int a, int b, int c, int d, int e,
                       int f, int g, int h, int i, int j ) { };

    void backlight (void)         { }
    void begin (int a, int b)     { }
    void clear (void)             { Serial.println (); }
    void setCursor (int a, int b) { Serial.println (); };

    void write (const char *s) { 
        Serial.print ("write -- ");
        Serial.println (s);
    };

    void print (int i)         { Serial.print   (i); };
    void print (const char *s) { Serial.print   (s); };

    void println (int i)         { Serial.println (i); };
    void println (const char *s) { Serial.println (s); };
};

#else
# include <Wire.h>
# include <LCD.h>
# include <LiquidCrystal_I2C.h>

#endif

const int  en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;
const int i2c_addr = 0x27;

LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

long hour = 0, minute = 0, second = 59;
long countdown_time = (hour * 3600) + (minute * 60) + second;

unsigned long msecLst;
unsigned long msecPeriod = 1000;

// -----------------------------------------------------------------------------
void count () {
    unsigned long msec = millis ();

    if ((msec - msecLst) < msecPeriod)
        return;
    msecLst = msec;

    int hour = msec /1000 / 3600;
    int min  = (msec /1000 / 60) % 60;
    int sec  = (msec /1000) % 60;

    char s [40];
    sprintf (s, "%2d:%02d:%02d", hour, min, sec);

    lcd.setCursor(0, 0);
    lcd.print (s);
}

// -----------------------------------------------------------------------------
void loop() {
    count();
}

// -----------------------------------------------------------------------------
void setup() {
    Serial.begin (9600);

    //  lcd.init();
    lcd.begin(16, 2);
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("HH:MM:SS");
}

looking at the code

enum?

struct??

sprintf (s, "%2d:%02d:%02d", ???

not knowing how long it will take to learn these things

code seems pretty unrelated to the repeating-problem

all in all a high probability to just drop the suggestion
waiting for an easier to understand code

my suggestion with some comments that shall explain how the code works.
The code compiles. But I haven't tested it on real hardware.
Your original constructor to create the I2C_LCD-object uses parameters like for a NON-I2C-LCD which seems strange to me

It might be that you are using a different I2C-LCD-library

#include <Wire.h>
#include <LiquidCrystal_I2C.h>


// Define I2C Address - change if reqiuired
const int i2c_addr = 0x27;

// an I2C-LCD just needs I2C-adress columms and lines to initialise
LiquidCrystal_I2C lcd(i2c_addr,16,2); //, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);
unsigned long hour = 0;
unsigned long minute = 0;
unsigned long second = 59;

unsigned long countdown_period = (hour * 3600UL) + (minute * 60) + second;


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

unsigned long MyTimer = 0;                   // Timer-variables MUST be of type unsigned long
unsigned long countdown_seconds_left;

void setup() {
  lcd.begin(16, 2);
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("HH:MM:SS");
  countdown_seconds_left = countdown_period; // initialise variable that is counting down to zero
  MyTimer = millis(); // initialise timer-variable with actual value of function millis()
}


void count() {

  if (countdown_seconds_left > 0) { // check if variable that counts down to zero is still ABOVE zero
    countdown_seconds_left--;       // if above zero decrement by one
  }
  else { // variable ciunting down has reached ZERO
    countdown_seconds_left = countdown_period; // initialise variable that is counting down to zero
    // what makes the countdown counting down again
  }

  if (countdown_seconds_left >= 0) {
    unsigned long countdown_hour = countdown_seconds_left / 3600;
    unsigned long countdown_minute = ((countdown_seconds_left / 60) % 60);
    unsigned long countdown_sec = countdown_seconds_left % 60;

    lcd.setCursor(0, 0);
    if (countdown_hour < 10) {
      lcd.print("0");
    }

    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }

    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }

    lcd.print(countdown_sec);
  }
}


void loop() {
  if ( TimePeriodIsOver(MyTimer, 1000) ) { 
    // if 1000 milliseconds have passed by
    count(); // ==> function "count()" is only called ONCE per second
  }
}

best regards Stefan

this works perfectly! thank you for the advice!

i have tried all libraries but the one that i use works the best for me, thank you for the advice !

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