Help with Countdown timer

Hello guys! I’m trying to include a countdown timer that resets every 5 minutes. But the timer would reset only in the multiples of five, so it would reset at 5, 10, 15, 20, 25 till 00. For example:

If the timer began at 10:02, it will count down to 10:05 → RESET
then from 10:05 to 10:10 → RESET
10:10 to 10:15 → RESET

The code I’m trying to include a countdown timer function in is: (I’ve borrowed the countdown timer code from this page).

#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#include <elapsedMillis.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

unsigned int SwitchDuration = 2500;
elapsedMillis timeElapsed;

void setup() {
  Serial.begin(115200);     // initialize serial communication only for debugging purpose
  u8g2.begin();
}

void loop() {


  u8g2.firstPage();
  do {

    // Switch frames every 2.5 seconds.
    // FRAME 1 =======================================
    if (timeElapsed <= SwitchDuration)
    {
      // Countdown Timer:
      int timerDuration = 300000;
      unsigned long runMillis = timerDuration - millis();
      unsigned long allSeconds = runMillis / 1000;
      int runHours = allSeconds / 3600;
      int secsRemaining = allSeconds % 3600;
      int runMinutes = secsRemaining / 60;
      int runSeconds = secsRemaining % 60;
      u8g2.setFont(u8g2_font_logisoso24_tn);
      u8g2.setCursor(0, 25);
      u8g2.print(runMinutes); u8g2.print(":"); u8g2.print(runSeconds);
      
      // FRAME 2 =======================================
    } else if (timeElapsed <= SwitchDuration * 2)
    {
      u8g2.setFont(u8g2_font_logisoso20_tn);
      u8g2.setCursor(6, 27);
      u8g2.print("2");

      // FRAME 3 =======================================
    } else if (timeElapsed <= SwitchDuration * 3)
    {
      u8g2.setFont(u8g2_font_logisoso20_tn);
      u8g2.setCursor(6, 27);
      u8g2.print("3");

      // FRAME (Blank) =================================
    } else if (timeElapsed <= SwitchDuration * 4)
    {
      timeElapsed = 0;
    }

  }
  while ( u8g2.nextPage() );
}

There are two problems with this setup:

  1. The timer function is independent works on its own so if it is initiated at 10:03, it will count down to 10:08 instead of the needed 10:05 → RESET routine.
  2. The other problem when I compile the borrowed code seperately, it works well, however, when include it in my code, it only counts down to 2 minutes 20 seconds.

Looking for better ways to make a countdown timer. The setup will also involve a DS3231. So if that could be involved, please suggest a way to do it as well.

Thanks.

Antrix:
If the timer began at 10:02, it will count down to 10:05 -> RESET
then from 10:05 to 10:10 -> RESET
10:10 to 10:15 -> RESET

How do you count DOWN from 10:02 to 10:05?!?
Do you mean:
I want a minutes and seconds count-down timer that counts down to the next 5-minute clock interval.

If you start the timer at 10:47:23 (clock time) the timer would show 2:37 (2 minutes and 37 seconds until 10:50:00) and then count down by seconds until it reaches 0:00 at 10:50:00 before going to 4:59 (4 minutes and 59 seconds until 10:55:00) a second later.

Precisely! That is how I need it to work. But I'm unsure of how to implement this through code. I tired various rudimentary combinations, only to realize I need some experienced advise.

To start with you will need a source of clock time. I’d recommend an RTC (Real-Time Clock) module. There is a library called “Time” that can manage the time for you. From that you can get the current time and date in seconds since some fixed time.

There are 300 seconds in each 5-minute interval. The number of seconds that have passes in the interval are TimeInSeconds % 300. Subtract that from 300 to get the number of seconds left in the interval.

johnwasser:
To start with you will need a source of clock time. I'd recommend an RTC (Real-Time Clock) module. There is a library called "Time" that can manage the time for you. From that you can get the current time and date in seconds since some fixed time.

There are 300 seconds in each 5-minute interval. The number of seconds that have passes in the interval are TimeInSeconds % 300. Subtract that from 300 to get the number of seconds left in the interval.

Ok, I'll get back to you with the codes that I tried using DS3231 and the now.minute() function to keep track of time.

Hi, I tried the following primitive method in an effort to make the countdown timer:

      long oneMinute = 60000;
      long timeRemaining;
      long milisTime = (now.minute()*60*1000)+(now.second()*1000);
      long fiveMinutes = 5*oneMinute;
      if (now.minute() > 0 && now.minute() < 5){
         timeRemaining = (fiveMinutes- milisTime) /1000; //Seconds
      }

This doesnt’t work the intended way.

if (now.minute() > 0 && now.minute() < 5) {

This is ‘true’ if the current minute is 1, 2, 3, or 4. From 10:05:00 to 11:00:59 it does nothing.

It also doesn’t make much sense to do calculations in milliseconds when you only need seconds. It just means multiplying everything by 1000 and then dividing everything by 1000 later. It also means using ‘long’ integers because 3,600,000 (60601000 milliseconds in an hour) is way too big to fit in an ‘int’.

Perhaps what you want is more like:

int timeInSeconds = now.minute() * 60 + now.second();
int timeRemaining = 300 - (timeInSeconds % 300);
int remainingMinutes = timeRemaining / 60;
int remainingSeconds = timeRemaining % 60;

johnwasser:
Perhaps what you want is more like:

int timeInSeconds = now.minute() * 60 + now.second();

int timeRemaining = 300 - (timeInSeconds % 300);
int remainingMinutes = timeRemaining / 60;
int remainingSeconds = timeRemaining % 60;

Ah! This is remarkably straightforward compared all the trapezing I was doing with code. I'll implement this and come back with the results.

Hi John, sorry for the delay. I made some changes to the code you suggested and the following apparatus works as intended. I had to use “(now.minute() >= 0 && now.minute() < 5)”. Please let me know of a more efficient method.

  int X;
  if (now.minute() >= 0 && now.minute() < 5) {
    X = 300;
  } else if (now.minute() >= 5 && now.minute() < 10) {
    X = 600;
  } else if (now.minute() >= 10 && now.minute() < 15) {
    X = 900;
  } else if (now.minute() >= 15 && now.minute() < 20) {
    X = 1200;
  } else if (now.minute() >= 20 && now.minute() < 25) {
    X = 1500;
  } else if (now.minute() >= 25 && now.minute() < 30) {
    X = 1800;
  } else if (now.minute() >= 30 && now.minute() < 35) {
    X = 2100;
  } else if (now.minute() >= 35 && now.minute() < 40) {
    X = 2400;
  } else if (now.minute() >= 40 && now.minute() < 45) {
    X = 2700;
  } else if (now.minute() >= 45 && now.minute() < 50) {
    X = 3000;
  } else if (now.minute() >= 50 && now.minute() < 55) {
    X = 3300;
  } else if (now.minute() >= 55 && now.minute() < 60) {
    X = 3600;
  }
  int timeInSeconds = now.minute() * 60 + now.second();
  int timeRemaining = X - (timeInSeconds);
  int remainingMinutes = timeRemaining / 60;
  int remainingSeconds = timeRemaining % 60;

Why all those if/elses? Just calculate. Much simpler.

int X = now.minute() / 5 * 300 + 300;

should do the job as it's all integers, so the decimals are dropped from the division.

This should give the same result:

int X = int(now.minute() / 5) * 300 + 300;

wvmarle:
Why all those if/elses? Just calculate. Much simpler.

int X = now.minute() / 5 * 300 + 300;

should do the job as it's all integers, so the decimals are dropped from the division.

This should give the same result:

int X = int(now.minute() / 5) * 300 + 300;

Thanks wvmarle. Please associate that to my inexperience in programming. Thank you for optimizing the algorithm.