user34609: I've made a game with 3 countdowns and 1 global countdown.

When we start, the global one, go from 45:00 to 00:00. 
The 1 go from 15:00 to 00:00 and if it reach 00:00:
The 2 start and go from 15:00 to 00:00 and it if reach 00:00:
The 3 start and go from 15:00 to 00:00

If you win little game, you can stop a countdown and start the next. If you win the 3 games, you stop the 3 countdown and the global too.
But sometime, my 2nd countdown stop itself, sometime at 13:58 or 10:54…
Is it possible that the millis() cause that bug ? Do you have an idea to improve my code and fix that ?
Fun fact : Sometime countdowns go from 01 to 60 instead of 00 to 59……
Sorry for my english, i'm not native speaker.
//14-06-17 Correctifs LED
//10-06-17 Correctif Jeu 1

#include "musical_notes.h"
#include "TM1637.h"                                    
#include "SevenSegmentTM1637.h"
#include "OnewireKeypad.h"
#include "Password.h"

SevenSegmentTM1637    displaya(4, 5);
SevenSegmentTM1637    displayb(6, 7);
SevenSegmentTM1637    displayc(8, 9);
SevenSegmentTM1637    displayd(50, 51);

TM1637 tm1637a(50, 51); //TIMER GLOBAL 45
TM1637 tm1637b(4, 5); //TIMER 1 15
TM1637 tm1637c(6, 7); //TIMER 2 15
TM1637 tm1637d(8, 9); //TIMER 3 15



char KEYS[] = {
  '1', '4', '7', '*',
  '2', '5', '8', '0',
  '3', '6', '9', '#',
  'A', 'B', 'C', 'D'
};
OnewireKeypad <Print, 16 > KP(Serial, KEYS, 4, 4, A0, 4700, 1000, ExtremePrec );
Password password = Password( "8751" );


//PREMIER JEU
int checkbranche = 23;
int checkbrancheb = 22;
int checkbranchec = 24;
int state = HIGH;     
int reading;   
int readingb;
int readingc;           
int previous = LOW;
int previousb = LOW;

int readingstart;
int checkstart = A1;

int speakerPin = 52;
int runOPEN = 0;
int runJEU1 = 0;
int runJEU2 = 0;
int runJEU3 = 0;
int runFAILGLOBAL = 0;

int winJEU1 = 0;
int winJEU2 = 0;
int winJEU3 = 0;
int winGLOBAL = 0;
int looseGLOBAL = 0;

int LED_jeu1_V = 30;
int LED_jeu1_R = 31;
int LED_jeu2_V = 33;
int LED_jeu2_R = 32;
int LED_jeu3_V = 35;
int LED_jeu3_R = 34;

int LED_jglobal1 = 36;
int LED_jglobal2 = 37;
int LED_jglobal3 = 38;
int LED_jglobal4 = 39;

int runcode = 0;

int second=0, minute=45, hour=0; // déclarer des variables de temps 
int second1=0, minute1=15, hour1=0; // déclarer des variables de temps 
int second2=0, minute2=15, hour2=0; // déclarer des variables de temps 
int second3=0, minute3=15, hour3=0; // déclarer des variables de temps 
long previousTime = 0;//détient temps précédent en ms 
long previousTime1 = 0;//détient temps précédent en ms 
long previousTime2 = 0;//détient temps précédent en ms 
long previousTime3 = 0;//détient temps précédent en ms 
long previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif 
long interval = 60000;//60 secondes de retard 
long interval1 = 60000;//60 secondes de retard 
long interval2 = 60000;//60 secondes de retard 
long interval3 = 60000;//60 secondes de retard 

int dismentel1 = 0; int fail1 = 0;
int dismentel2 = 0; int fail2 = 0;
int dismentel3 = 0; int fail3 = 0;
int dismentel4 = 0; int fail4 = 0;

char hour_str[4]; // Pour Convertir int en char 
char minute_str[4]; // Pour Convertir int en char 
char second_str[4]; // Pour Convertir int en char 
char timeInt_str[0];  // Pour Convertir int en char 

int accessgame = 3; //Activation de led quand les minutes arrivent à 3

unsigned char halfsecond=0;

void setup() {
  Serial.begin(19200);

  KP.SetHoldTime(3000);
  KP.SetKeypadVoltage(5.0);
  KP.ShowRange();

   displaya.begin();
   displayb.begin();  
   displayc.begin();
   displayd.begin();

   tm1637a.set(4); 
   tm1637a.init();
   tm1637a.point(POINT_ON); 

   tm1637b.set(4); 
   tm1637b.init();
   tm1637b.point(POINT_ON); 

   tm1637c.set(4); 
   tm1637c.init();
   tm1637c.point(POINT_ON); 

   tm1637d.set(4); 
   tm1637d.init();
   tm1637d.point(POINT_ON); 

   pinMode(checkbranche, INPUT);
   pinMode(checkbrancheb, INPUT);
   pinMode(checkbranchec, INPUT);
   pinMode(checkstart, INPUT);
   pinMode(speakerPin, OUTPUT);

   pinMode(LED_jeu1_V, OUTPUT);
   pinMode(LED_jeu1_R, OUTPUT);
   pinMode(LED_jeu2_V, OUTPUT);
   pinMode(LED_jeu2_R, OUTPUT);
   pinMode(LED_jeu3_V, OUTPUT);
   pinMode(LED_jeu3_R, OUTPUT);

   pinMode(LED_jglobal1, OUTPUT);
   pinMode(LED_jglobal2, OUTPUT);
   pinMode(LED_jglobal3, OUTPUT);
   pinMode(LED_jglobal4, OUTPUT);


   delay(1000);


};




// run loop (forever)
void loop() {

readingstart = digitalRead(checkstart);
reading = digitalRead(checkbranche);
readingb = digitalRead(checkbrancheb);
readingc = digitalRead(checkbranchec); 


if (runcode < 1) {
Serial.println("WHAT");


      if (readingstart == HIGH) {

        for (; runOPEN < 1; runOPEN++) {
          uhoh();
         } 


    countdown();


Serial.print(halfsecond);
Serial.println(" ");


  if (dismentel1 == 1) {digitalWrite(LED_jglobal1, HIGH);} else {digitalWrite(LED_jglobal1, LOW);}
  if (dismentel2 == 1) {digitalWrite(LED_jglobal2, HIGH);} else {digitalWrite(LED_jglobal2, LOW);}
  if (dismentel3 == 1) {digitalWrite(LED_jglobal3, HIGH);} else {digitalWrite(LED_jglobal3, LOW);}
  if (dismentel4 == 1) {digitalWrite(LED_jglobal4, HIGH);} else {digitalWrite(LED_jglobal4, LOW);}


// GESTION DU JEU 1 //
  if (reading == LOW) {  //REVISION 1 HIGH -> LOW
      countdown1();

      if (second1 > 0 && minute1 >= 0) { 
          int8_t timeDisp1[4];          
          timeDisp1[0] = minute1 / 10;   
          timeDisp1[1] = minute1 % 10;   
          timeDisp1[2] = second1 / 10;   
          timeDisp1[3] = second1 % 10;   
          tm1637b.display(timeDisp1);

      if (minute1 < accessgame) {
        digitalWrite(LED_jeu1_V, LOW);
        digitalWrite(LED_jeu1_R, HIGH);        
      } else {
        digitalWrite(LED_jeu1_V, HIGH);
        digitalWrite(LED_jeu1_R, LOW);
      }

          dismentel1 = 0;

      } else {
          displaya.print("FAIL");
            digitalWrite(LED_jeu1_V, HIGH);
            digitalWrite(LED_jeu1_R, LOW);
            for (; runJEU1 < 1; runJEU1++) {
              squeak();
            } 
           fail1 = 1;
      }

  } else {
      displaya.print("--5-");
      digitalWrite(LED_jeu1_V, LOW);
      digitalWrite(LED_jeu1_R, HIGH);
      for (; winJEU1 < 1; winJEU1++) {
        wingame();
       }        
       dismentel1 = 1;
  }


// GESTION DU JEU 1 //


// GESTION DU JEU 2 // 
  if (readingb == HIGH) {
    dismentel2 = 1;
  }

  if ((dismentel1 == 1 or fail1 == 1) && dismentel2 == 0) {  
    countdown2();

    if (second2 > 0 && minute2 >= 0) { 
      int8_t timeDisp2[4];          
      timeDisp2[0] = minute2 / 10;   
      timeDisp2[1] = minute2 % 10;   
      timeDisp2[2] = second2 / 10;   
      timeDisp2[3] = second2 % 10;   
      tm1637c.display(timeDisp2);   
      if (minute2 < accessgame) {
        digitalWrite(LED_jeu2_V, LOW);
        digitalWrite(LED_jeu2_R, HIGH);        
      } else {
        digitalWrite(LED_jeu2_V, HIGH);
        digitalWrite(LED_jeu2_R, LOW);
      }
      dismentel2 = 0;  
    } else {
        displayb.print("FAIL");
          digitalWrite(LED_jeu2_V, HIGH);
          digitalWrite(LED_jeu2_R, LOW);
          for (; runJEU2 < 1; runJEU2++) {
            squeak();
          } 
         fail2 = 1;
    }

  } else if ((dismentel1 == 1 or fail1 == 1)  && dismentel2 == 1){
      displayb.print("-7--");
      digitalWrite(LED_jeu2_V, LOW);
      digitalWrite(LED_jeu2_R, HIGH);  
      for (; winJEU2 < 1; winJEU2++) {
        wingame();
       }        
       dismentel2 = 1;
  } else { 
    displayb.print("----");
      digitalWrite(LED_jeu2_V, HIGH);
      digitalWrite(LED_jeu2_R, HIGH);
      }

// GESTION DU JEU 2 // 


// GESTION DU JEU 3 // 


  if (readingc == HIGH) {
    dismentel3 = 1;
  }

  if ((dismentel2 == 1 or fail2 == 1) && dismentel3 == 0) {  
    countdown3();

    if (second3 > 0 && minute3 >= 0) { 
      int8_t timeDisp3[4];          
      timeDisp3[0] = minute3 / 10;   
      timeDisp3[1] = minute3 % 10;   
      timeDisp3[2] = second3 / 10;   
      timeDisp3[3] = second3 % 10;   
      tm1637d.display(timeDisp3);   
      if (minute3 < accessgame) {
        digitalWrite(LED_jeu3_V, LOW);
        digitalWrite(LED_jeu3_R, HIGH);        
      } else {
        digitalWrite(LED_jeu3_V, HIGH);
        digitalWrite(LED_jeu3_R, LOW);
      }
      dismentel3 = 0;  
    } else {
        displayc.print("FAIL");
          digitalWrite(LED_jeu3_V, HIGH);
          digitalWrite(LED_jeu3_R, LOW);
          for (; runJEU3 < 1; runJEU3++) {
            squeak();
          } 
         fail3 = 1;
    }

  } else if ((dismentel2 == 1 or fail2 == 1)  && dismentel3 == 1){
      displayc.print("---1");
      digitalWrite(LED_jeu3_V, LOW);
      digitalWrite(LED_jeu3_R, HIGH);  
      for (; winJEU3 < 1; winJEU3++) {
        wingame();
       }        
       dismentel3 = 1;
  } else { 
    displayc.print("----");
      digitalWrite(LED_jeu3_V, HIGH);
      digitalWrite(LED_jeu3_R, HIGH);
      }

      } else {

second=0; minute=45; hour=0; // déclarer des variables de temps 
second1=0; minute1=15; hour1=0; // déclarer des variables de temps 
second2=0; minute2=15; hour2=0; // déclarer des variables de temps 
second3=0; minute3=15; hour3=0; // déclarer des variables de temps 
previousTime = 0;//détient temps précédent en ms 
previousTime1 = 0;//détient temps précédent en ms 
previousTime2 = 0;//détient temps précédent en ms 
previousTime3 = 0;//détient temps précédent en ms 
previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif 
interval = 60000;//60 secondes de retard 
interval1 = 60000;//60 secondes de retard 
interval2 = 60000;//60 secondes de retard 
interval3 = 60000;//60 secondes de retard 
runOPEN = 0;
dismentel1 = 0; fail1 = 0;
dismentel2 = 0; fail2 = 0;
dismentel3 = 0; fail3 = 0;
dismentel4 = 0; fail4 = 0;
    displaya.print("-   ");
    displayd.print("-   ");


      }

}

// GESTION DU JEU 3 // 


// VALIDATION GLOBALE PAR DIGICODE //
  char Key;
  byte KState = KP.Key_State();

  if (KState == PRESSED) {
    if ( Key = KP.Getkey() ) {
      Serial << "Pressed: " << Key << "\n";
      switch (Key) {
        case '*': checkPassword(); break;
        case '#': password.reset(); break;
        default: password.append(Key);
      }
    }
  }
  else if (KState == HELD) {
    Serial << "Key:" << KP.Getkey() << " being held\n";
  }
// VALIDATION GLOBALE PAR DIGICODE //




};


void beep (int speakerPin, float noteFrequency, long noteDuration)
{    
  int x;
  // Convert the frequency to microseconds
  float microsecondsPerWave = 1000000/noteFrequency;
  // Calculate how many HIGH/LOW cycles there are per millisecond
  float millisecondsPerCycle = 1000/(microsecondsPerWave * 2);
  // Multiply noteDuration * number or cycles per millisecond
  float loopTime = noteDuration * millisecondsPerCycle;
  // Play the note for the calculated loopTime.
  for (x=0;x<loopTime;x++)   
          {   
              digitalWrite(speakerPin,HIGH); 
              delayMicroseconds(microsecondsPerWave); 
              digitalWrite(speakerPin,LOW); 
              delayMicroseconds(microsecondsPerWave); 
          } 
} 

void waka() {
  for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);

            beep(speakerPin, note_Bb5,300); //B b
          delay(50);
          beep(speakerPin, note_C6,300); //C
          delay(50);
          beep(speakerPin, note_Ab5,300); //A b
          delay(50);
          beep(speakerPin, note_Ab4,300); //A b
          delay(50);
          beep(speakerPin, note_Eb5,500); //E b   
          delay(500);   
}

void squeak() {
//  for (int i=100; i<5000; i=i*1.45) {
//    beep(speakerPin,i,60);
//  }
//  delay(10);
  for (int i=3500; i>10; i=i/1.15) {
    beep(speakerPin,i,60);
  }
}
void wingame() {
  for (int i=100; i<5000; i=i*1.45) {
    beep(speakerPin,i,60);
  }

}

void uhoh() {
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<5000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
 delay(300);

  for (int i=1000; i<3000; i=i*1.03) {
    beep(speakerPin,i,10);
  }
  for (int i=3000; i>1000; i=i*.97) {
    beep(speakerPin,i,10);
  }
}

void checkPassword()
{
  if (password.evaluate()) {
    Serial.println("Success");
    runcode = 1;
    displayd.print(" YOU");
    displayd.print(" YOU");
    displaya.print(" ARE");
    displaya.print(" ARE");
    displayb.print(" THE");
    displayb.print(" THE");
    displayc.print("BEST");
    displayc.print("BEST");
    digitalWrite(LED_jglobal4, HIGH);

    for (; winGLOBAL < 1; winGLOBAL++) {
      waka();
     }     
    password.reset();
  } else {
    Serial.println("Wrong");
    password.reset();


    for (; looseGLOBAL < 1; looseGLOBAL++) {
    squeak();
    looseGLOBAL = 0;
    } 


  }
}
/********************************************************************** 
 *                        GLOBAL                                      * 
 **********************************************************************/ 
void countdown(){ 

 static unsigned long lastTick = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second > 0) { 
    if (millis() - lastTick >= 1000) { 
      lastTick = millis(); 
      second--; 

      int8_t timeDisp[4];          
      timeDisp[0] = minute / 10;   
      timeDisp[1] = minute % 10;   
      timeDisp[2] = second / 10;   
      timeDisp[3] = second % 10;   
      tm1637a.display(timeDisp);   
      tm1637a.point(POINT_ON);

    } 
  } else {
       displayd.print("FAIL");
      for (; runFAILGLOBAL < 1; runFAILGLOBAL++) {
          squeak();
      }    
  }
 // décrémenter une minute toutes les 60 secondes 
  if (minute > 0) { 
    if (second <= 0) { 
      minute--; 
      second = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour > 0) { 
    if (minute <= 0) { 
      hour--; 
      minute = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis = millis(); 
  if (currentMillis - previousTime > interval) 
  { 
    previousTime = currentMillis; 
    previousDelay = currentMillis; 
  } 

  if (currentMillis - previousDelay > 100) {//100ms durée de chirp 
  } 
} //close countdown(); 


/********************************************************************** 
 *                        JEU1                                        * 
 **********************************************************************/ 
void countdown1(){ 

 static unsigned long lastTick1 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis1 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second1 > 0) { 
    if (millis() - lastTick1 >= 1000) { 
      lastTick1 = millis(); 
      second1--; 

    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute1 > 0) { 
    if (second1 <= 0) { 
      minute1--; 
      second1 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour1 > 0) { 
    if (minute1 <= 0) { 
      hour1--; 
      minute1 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis1 = millis(); 
  if (currentMillis1 - previousTime1 > interval1) 
  { 
    previousTime1 = currentMillis1; 
    previousDelay1 = currentMillis1; 
  } 

  if (currentMillis1 - previousDelay1 > 100) {//100ms durée de chirp 
  } 





} //close countdown1();


/********************************************************************** 
 *                        JEU2                                        * 
 **********************************************************************/ 
void countdown2(){ 

 static unsigned long lastTick2 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis2 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second2 > 0) { 
    if (millis() - lastTick2 >= 1000) { 
      lastTick2 = millis(); 
      second2--; 
    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute2 > 0) { 
    if (second2 <= 0) { 
      minute2--; 
      second2 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour2 > 0) { 
    if (minute2 <= 0) { 
      hour2--; 
      minute2 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis2 = millis(); 
  if (currentMillis2 - previousTime2 > interval1) 
  { 
    previousTime2 = currentMillis2; 
    previousDelay2 = currentMillis2; 
  } 

  if (currentMillis2 - previousDelay2 > 100) {//100ms durée de chirp 
  }





} //close countdown2();



/********************************************************************** 
 *                        JEU3                                        * 
 **********************************************************************/ 
void countdown3(){ 

 static unsigned long lastTick3 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis3 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second3 > 0) { 
    if (millis() - lastTick3 >= 1000) { 
      lastTick3 = millis(); 
      second3--; 


    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute3 > 0) { 
    if (second3 <= 0) { 
      minute3--; 
      second3 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour3 > 0) { 
    if (minute3 <= 0) { 
      hour3--; 
      minute3 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis3 = millis(); 
  if (currentMillis3 - previousTime3 > interval1) 
  { 
    previousTime3 = currentMillis3; 
    previousDelay3 = currentMillis3; 
  } 

  if (currentMillis3 - previousDelay3 > 100) {//100ms durée de chirp 
  } 
} //close countdown2(); 


user13425: That code is a mess. I'm sure you can refactor a lot of it. To get you started here's a C++ class you can use as a countdown timer. I just whipped this up, but it should work. However, it does not handle the case where millis() overflows (after about 50 days).
class Countdown {
public:
    const uint32_t ms_per_hour = 60l * 60l * 1000l;
    const uint32_t ms_per_minute = 60l * 1000l;
    const uint32_t ms_per_second = 1000l;

    // Constructor
    Countdown(int hours, int minutes, int seconds) {
        duration = hours * ms_per_hour +
                   minutes * ms_per_minute  +
                   seconds * ms_per_second ;
        started = false;
        finished = false;
    }
    // Call this to start the countdown
    void start() {
        started = true;
        finished = false;
        start_time = millis();
    }

    // Stop the timer
    void stop() {
        finished = true;
    }

    // Is timer running?
    bool is_running() {
        return started == true && finished == false;
    }

    // Call this to check if the countdown is finished
    bool times_up() {
        if (finished) return true;
        else if (!started) return false;
        if (elapsed_time() >= duration) {
            finished = true;
            return true;
        }
        return false;
    }

    // Returns a string representation of how much time has passed
    const char * get_elapsed(const char *format="hh:mm:ss") {
        return ms_to_string(format, elapsed_time());
    }
    // Returns a string representation of how much time is left
    const char * get_remaining(const char *format="hh:mm:ss") {
        return ms_to_string(format, duration - elapsed_time());
    }

    // Returns an array of decimal digits for display of time passed
    const char * get_digits_elapsed(const char *format="mmss") {
        return ms_to_digits(format, elapsed_time());
    }
    // Returns an array of decimal digits for display of time remaining
    const char * get_digits_remaining(const char *format="mmss") {
        return ms_to_digits(format, duration - elapsed_time());
    }

protected:
    unsigned long elapsed_time() {
        return millis() - start_time;
    }

    bool started, finished;
    uint32_t duration, start_time;
    char buffer[32];

    char * ms_to_digits(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    buffer[index++] = (char)(val / 10);
                    i += 1;
                }
                buffer[index++] = char(val % 10);
            }
        }
        return buffer;
    }

    char * ms_to_string(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        buffer[0] = 0;
        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    index += sprintf(&buffer[index], "%02d", val);
                    i += 1;
                }
                else {
                  index += sprintf(&buffer[index], "%d", val);
                }
            }
            else {
                buffer[index++] = format[i];
            }
        }
        buffer[index] = '\0';
        return buffer;
    }
};

To use it, you would create 3 objects:
Countdown cd1(0, 45, 0);  // 45 minutes
Countdown cd2(0, 15, 0);  // 15 minutes
Countdown cd3(0, 15, 0);  // 15 minutes

Then, start #1 in setup:
void setup() {
    cd1.start();
}

And in loop:
void loop() {
    if (cd3.times_up()) {
       // game over
    }
    else if (cd2.times_up()) {
        // 2nd timer expired, do something
        if (!cd3.is_running()) cd3.start();  // Start #3
        // update display
        tm1637d.display(c3.get_digits_remaining());
    }
    else if (cd1.times_up()) {
        // 1st timer expired, do something
        if (!cd2.is_running()) cd2.start();  // Start #2
        // update display
        tm1637c.display(c2.get_digits_remaining());
    }
    else {
        // update display
        tm1637b.display(c1.get_digits_remaining());
    }
}


34609: <p>I've made a game with 3 countdowns and 1 global countdown.</p>

<ul>
<li><p>When we start, the global one, go from 45:00 to 00:00. </p></li>
<li><p>The 1 go from 15:00 to 00:00 and if it reach 00:00:</p></li>
<li><p>The 2 start and go from 15:00 to 00:00 and it if reach 00:00:</p></li>
<li><p>The 3 start and go from 15:00 to 00:00</p></li>
</ul>

<p>If you win little game, you can stop a countdown and start the next. If you win the 3 games, you stop the 3 countdown and the global too.</p>

<p>But sometime, my 2nd countdown stop itself, sometime at 13:58 or 10:54…</p>

<p>Is it possible that the <strong>millis()</strong> cause that bug ? Do you have an idea to improve my code and fix that ?</p>

<p>Fun fact : Sometime countdowns go from 01 to 60 instead of 00 to 59……</p>

<p>Sorry for my english, i'm not native speaker.</p>

<pre><code>//14-06-17 Correctifs LED
//10-06-17 Correctif Jeu 1

#include "musical_notes.h"
#include "TM1637.h"                                    
#include "SevenSegmentTM1637.h"
#include "OnewireKeypad.h"
#include "Password.h"

SevenSegmentTM1637    displaya(4, 5);
SevenSegmentTM1637    displayb(6, 7);
SevenSegmentTM1637    displayc(8, 9);
SevenSegmentTM1637    displayd(50, 51);

TM1637 tm1637a(50, 51); //TIMER GLOBAL 45
TM1637 tm1637b(4, 5); //TIMER 1 15
TM1637 tm1637c(6, 7); //TIMER 2 15
TM1637 tm1637d(8, 9); //TIMER 3 15



char KEYS[] = {
  '1', '4', '7', '*',
  '2', '5', '8', '0',
  '3', '6', '9', '#',
  'A', 'B', 'C', 'D'
};
OnewireKeypad &lt;Print, 16 &gt; KP(Serial, KEYS, 4, 4, A0, 4700, 1000, ExtremePrec );
Password password = Password( "8751" );


//PREMIER JEU
int checkbranche = 23;
int checkbrancheb = 22;
int checkbranchec = 24;
int state = HIGH;     
int reading;   
int readingb;
int readingc;           
int previous = LOW;
int previousb = LOW;

int readingstart;
int checkstart = A1;

int speakerPin = 52;
int runOPEN = 0;
int runJEU1 = 0;
int runJEU2 = 0;
int runJEU3 = 0;
int runFAILGLOBAL = 0;

int winJEU1 = 0;
int winJEU2 = 0;
int winJEU3 = 0;
int winGLOBAL = 0;
int looseGLOBAL = 0;

int LED_jeu1_V = 30;
int LED_jeu1_R = 31;
int LED_jeu2_V = 33;
int LED_jeu2_R = 32;
int LED_jeu3_V = 35;
int LED_jeu3_R = 34;

int LED_jglobal1 = 36;
int LED_jglobal2 = 37;
int LED_jglobal3 = 38;
int LED_jglobal4 = 39;

int runcode = 0;

int second=0, minute=45, hour=0; // déclarer des variables de temps 
int second1=0, minute1=15, hour1=0; // déclarer des variables de temps 
int second2=0, minute2=15, hour2=0; // déclarer des variables de temps 
int second3=0, minute3=15, hour3=0; // déclarer des variables de temps 
long previousTime = 0;//détient temps précédent en ms 
long previousTime1 = 0;//détient temps précédent en ms 
long previousTime2 = 0;//détient temps précédent en ms 
long previousTime3 = 0;//détient temps précédent en ms 
long previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif 
long previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif 
long interval = 60000;//60 secondes de retard 
long interval1 = 60000;//60 secondes de retard 
long interval2 = 60000;//60 secondes de retard 
long interval3 = 60000;//60 secondes de retard 

int dismentel1 = 0; int fail1 = 0;
int dismentel2 = 0; int fail2 = 0;
int dismentel3 = 0; int fail3 = 0;
int dismentel4 = 0; int fail4 = 0;

char hour_str[4]; // Pour Convertir int en char 
char minute_str[4]; // Pour Convertir int en char 
char second_str[4]; // Pour Convertir int en char 
char timeInt_str[0];  // Pour Convertir int en char 

int accessgame = 3; //Activation de led quand les minutes arrivent à 3

unsigned char halfsecond=0;

void setup() {
  Serial.begin(19200);

  KP.SetHoldTime(3000);
  KP.SetKeypadVoltage(5.0);
  KP.ShowRange();

   displaya.begin();
   displayb.begin();  
   displayc.begin();
   displayd.begin();

   tm1637a.set(4); 
   tm1637a.init();
   tm1637a.point(POINT_ON); 

   tm1637b.set(4); 
   tm1637b.init();
   tm1637b.point(POINT_ON); 

   tm1637c.set(4); 
   tm1637c.init();
   tm1637c.point(POINT_ON); 

   tm1637d.set(4); 
   tm1637d.init();
   tm1637d.point(POINT_ON); 

   pinMode(checkbranche, INPUT);
   pinMode(checkbrancheb, INPUT);
   pinMode(checkbranchec, INPUT);
   pinMode(checkstart, INPUT);
   pinMode(speakerPin, OUTPUT);

   pinMode(LED_jeu1_V, OUTPUT);
   pinMode(LED_jeu1_R, OUTPUT);
   pinMode(LED_jeu2_V, OUTPUT);
   pinMode(LED_jeu2_R, OUTPUT);
   pinMode(LED_jeu3_V, OUTPUT);
   pinMode(LED_jeu3_R, OUTPUT);

   pinMode(LED_jglobal1, OUTPUT);
   pinMode(LED_jglobal2, OUTPUT);
   pinMode(LED_jglobal3, OUTPUT);
   pinMode(LED_jglobal4, OUTPUT);


   delay(1000);


};




// run loop (forever)
void loop() {

readingstart = digitalRead(checkstart);
reading = digitalRead(checkbranche);
readingb = digitalRead(checkbrancheb);
readingc = digitalRead(checkbranchec); 


if (runcode &lt; 1) {
Serial.println("WHAT");


      if (readingstart == HIGH) {

        for (; runOPEN &lt; 1; runOPEN++) {
          uhoh();
         } 


    countdown();


Serial.print(halfsecond);
Serial.println(" ");


  if (dismentel1 == 1) {digitalWrite(LED_jglobal1, HIGH);} else {digitalWrite(LED_jglobal1, LOW);}
  if (dismentel2 == 1) {digitalWrite(LED_jglobal2, HIGH);} else {digitalWrite(LED_jglobal2, LOW);}
  if (dismentel3 == 1) {digitalWrite(LED_jglobal3, HIGH);} else {digitalWrite(LED_jglobal3, LOW);}
  if (dismentel4 == 1) {digitalWrite(LED_jglobal4, HIGH);} else {digitalWrite(LED_jglobal4, LOW);}


// GESTION DU JEU 1 //
  if (reading == LOW) {  //REVISION 1 HIGH -&gt; LOW
      countdown1();

      if (second1 &gt; 0 &amp;&amp; minute1 &gt;= 0) { 
          int8_t timeDisp1[4];          
          timeDisp1[0] = minute1 / 10;   
          timeDisp1[1] = minute1 % 10;   
          timeDisp1[2] = second1 / 10;   
          timeDisp1[3] = second1 % 10;   
          tm1637b.display(timeDisp1);

      if (minute1 &lt; accessgame) {
        digitalWrite(LED_jeu1_V, LOW);
        digitalWrite(LED_jeu1_R, HIGH);        
      } else {
        digitalWrite(LED_jeu1_V, HIGH);
        digitalWrite(LED_jeu1_R, LOW);
      }

          dismentel1 = 0;

      } else {
          displaya.print("FAIL");
            digitalWrite(LED_jeu1_V, HIGH);
            digitalWrite(LED_jeu1_R, LOW);
            for (; runJEU1 &lt; 1; runJEU1++) {
              squeak();
            } 
           fail1 = 1;
      }

  } else {
      displaya.print("--5-");
      digitalWrite(LED_jeu1_V, LOW);
      digitalWrite(LED_jeu1_R, HIGH);
      for (; winJEU1 &lt; 1; winJEU1++) {
        wingame();
       }        
       dismentel1 = 1;
  }


// GESTION DU JEU 1 //


// GESTION DU JEU 2 // 
  if (readingb == HIGH) {
    dismentel2 = 1;
  }

  if ((dismentel1 == 1 or fail1 == 1) &amp;&amp; dismentel2 == 0) {  
    countdown2();

    if (second2 &gt; 0 &amp;&amp; minute2 &gt;= 0) { 
      int8_t timeDisp2[4];          
      timeDisp2[0] = minute2 / 10;   
      timeDisp2[1] = minute2 % 10;   
      timeDisp2[2] = second2 / 10;   
      timeDisp2[3] = second2 % 10;   
      tm1637c.display(timeDisp2);   
      if (minute2 &lt; accessgame) {
        digitalWrite(LED_jeu2_V, LOW);
        digitalWrite(LED_jeu2_R, HIGH);        
      } else {
        digitalWrite(LED_jeu2_V, HIGH);
        digitalWrite(LED_jeu2_R, LOW);
      }
      dismentel2 = 0;  
    } else {
        displayb.print("FAIL");
          digitalWrite(LED_jeu2_V, HIGH);
          digitalWrite(LED_jeu2_R, LOW);
          for (; runJEU2 &lt; 1; runJEU2++) {
            squeak();
          } 
         fail2 = 1;
    }

  } else if ((dismentel1 == 1 or fail1 == 1)  &amp;&amp; dismentel2 == 1){
      displayb.print("-7--");
      digitalWrite(LED_jeu2_V, LOW);
      digitalWrite(LED_jeu2_R, HIGH);  
      for (; winJEU2 &lt; 1; winJEU2++) {
        wingame();
       }        
       dismentel2 = 1;
  } else { 
    displayb.print("----");
      digitalWrite(LED_jeu2_V, HIGH);
      digitalWrite(LED_jeu2_R, HIGH);
      }

// GESTION DU JEU 2 // 


// GESTION DU JEU 3 // 


  if (readingc == HIGH) {
    dismentel3 = 1;
  }

  if ((dismentel2 == 1 or fail2 == 1) &amp;&amp; dismentel3 == 0) {  
    countdown3();

    if (second3 &gt; 0 &amp;&amp; minute3 &gt;= 0) { 
      int8_t timeDisp3[4];          
      timeDisp3[0] = minute3 / 10;   
      timeDisp3[1] = minute3 % 10;   
      timeDisp3[2] = second3 / 10;   
      timeDisp3[3] = second3 % 10;   
      tm1637d.display(timeDisp3);   
      if (minute3 &lt; accessgame) {
        digitalWrite(LED_jeu3_V, LOW);
        digitalWrite(LED_jeu3_R, HIGH);        
      } else {
        digitalWrite(LED_jeu3_V, HIGH);
        digitalWrite(LED_jeu3_R, LOW);
      }
      dismentel3 = 0;  
    } else {
        displayc.print("FAIL");
          digitalWrite(LED_jeu3_V, HIGH);
          digitalWrite(LED_jeu3_R, LOW);
          for (; runJEU3 &lt; 1; runJEU3++) {
            squeak();
          } 
         fail3 = 1;
    }

  } else if ((dismentel2 == 1 or fail2 == 1)  &amp;&amp; dismentel3 == 1){
      displayc.print("---1");
      digitalWrite(LED_jeu3_V, LOW);
      digitalWrite(LED_jeu3_R, HIGH);  
      for (; winJEU3 &lt; 1; winJEU3++) {
        wingame();
       }        
       dismentel3 = 1;
  } else { 
    displayc.print("----");
      digitalWrite(LED_jeu3_V, HIGH);
      digitalWrite(LED_jeu3_R, HIGH);
      }

      } else {

second=0; minute=45; hour=0; // déclarer des variables de temps 
second1=0; minute1=15; hour1=0; // déclarer des variables de temps 
second2=0; minute2=15; hour2=0; // déclarer des variables de temps 
second3=0; minute3=15; hour3=0; // déclarer des variables de temps 
previousTime = 0;//détient temps précédent en ms 
previousTime1 = 0;//détient temps précédent en ms 
previousTime2 = 0;//détient temps précédent en ms 
previousTime3 = 0;//détient temps précédent en ms 
previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif 
previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif 
interval = 60000;//60 secondes de retard 
interval1 = 60000;//60 secondes de retard 
interval2 = 60000;//60 secondes de retard 
interval3 = 60000;//60 secondes de retard 
runOPEN = 0;
dismentel1 = 0; fail1 = 0;
dismentel2 = 0; fail2 = 0;
dismentel3 = 0; fail3 = 0;
dismentel4 = 0; fail4 = 0;
    displaya.print("-   ");
    displayd.print("-   ");


      }

}

// GESTION DU JEU 3 // 


// VALIDATION GLOBALE PAR DIGICODE //
  char Key;
  byte KState = KP.Key_State();

  if (KState == PRESSED) {
    if ( Key = KP.Getkey() ) {
      Serial &lt;&lt; "Pressed: " &lt;&lt; Key &lt;&lt; "\n";
      switch (Key) {
        case '*': checkPassword(); break;
        case '#': password.reset(); break;
        default: password.append(Key);
      }
    }
  }
  else if (KState == HELD) {
    Serial &lt;&lt; "Key:" &lt;&lt; KP.Getkey() &lt;&lt; " being held\n";
  }
// VALIDATION GLOBALE PAR DIGICODE //




};


void beep (int speakerPin, float noteFrequency, long noteDuration)
{    
  int x;
  // Convert the frequency to microseconds
  float microsecondsPerWave = 1000000/noteFrequency;
  // Calculate how many HIGH/LOW cycles there are per millisecond
  float millisecondsPerCycle = 1000/(microsecondsPerWave * 2);
  // Multiply noteDuration * number or cycles per millisecond
  float loopTime = noteDuration * millisecondsPerCycle;
  // Play the note for the calculated loopTime.
  for (x=0;x&lt;loopTime;x++)   
          {   
              digitalWrite(speakerPin,HIGH); 
              delayMicroseconds(microsecondsPerWave); 
              digitalWrite(speakerPin,LOW); 
              delayMicroseconds(microsecondsPerWave); 
          } 
} 

void waka() {
  for (int i=1000; i&lt;3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i&gt;1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i&lt;3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i&gt;1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i&lt;3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i&gt;1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i&lt;3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);

            beep(speakerPin, note_Bb5,300); //B b
          delay(50);
          beep(speakerPin, note_C6,300); //C
          delay(50);
          beep(speakerPin, note_Ab5,300); //A b
          delay(50);
          beep(speakerPin, note_Ab4,300); //A b
          delay(50);
          beep(speakerPin, note_Eb5,500); //E b   
          delay(500);   
}

void squeak() {
//  for (int i=100; i&lt;5000; i=i*1.45) {
//    beep(speakerPin,i,60);
//  }
//  delay(10);
  for (int i=3500; i&gt;10; i=i/1.15) {
    beep(speakerPin,i,60);
  }
}
void wingame() {
  for (int i=100; i&lt;5000; i=i*1.45) {
    beep(speakerPin,i,60);
  }

}

void uhoh() {
  for (int i=1000; i&lt;2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i&gt;500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i&lt;2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i&gt;500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i&lt;2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i&gt;500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i&lt;2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i&gt;500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i&lt;5000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
 delay(300);

  for (int i=1000; i&lt;3000; i=i*1.03) {
    beep(speakerPin,i,10);
  }
  for (int i=3000; i&gt;1000; i=i*.97) {
    beep(speakerPin,i,10);
  }
}

void checkPassword()
{
  if (password.evaluate()) {
    Serial.println("Success");
    runcode = 1;
    displayd.print(" YOU");
    displayd.print(" YOU");
    displaya.print(" ARE");
    displaya.print(" ARE");
    displayb.print(" THE");
    displayb.print(" THE");
    displayc.print("BEST");
    displayc.print("BEST");
    digitalWrite(LED_jglobal4, HIGH);

    for (; winGLOBAL &lt; 1; winGLOBAL++) {
      waka();
     }     
    password.reset();
  } else {
    Serial.println("Wrong");
    password.reset();


    for (; looseGLOBAL &lt; 1; looseGLOBAL++) {
    squeak();
    looseGLOBAL = 0;
    } 


  }
}
/********************************************************************** 
 *                        GLOBAL                                      * 
 **********************************************************************/ 
void countdown(){ 

 static unsigned long lastTick = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second &gt; 0) { 
    if (millis() - lastTick &gt;= 1000) { 
      lastTick = millis(); 
      second--; 

      int8_t timeDisp[4];          
      timeDisp[0] = minute / 10;   
      timeDisp[1] = minute % 10;   
      timeDisp[2] = second / 10;   
      timeDisp[3] = second % 10;   
      tm1637a.display(timeDisp);   
      tm1637a.point(POINT_ON);

    } 
  } else {
       displayd.print("FAIL");
      for (; runFAILGLOBAL &lt; 1; runFAILGLOBAL++) {
          squeak();
      }    
  }
 // décrémenter une minute toutes les 60 secondes 
  if (minute &gt; 0) { 
    if (second &lt;= 0) { 
      minute--; 
      second = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour &gt; 0) { 
    if (minute &lt;= 0) { 
      hour--; 
      minute = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis = millis(); 
  if (currentMillis - previousTime &gt; interval) 
  { 
    previousTime = currentMillis; 
    previousDelay = currentMillis; 
  } 

  if (currentMillis - previousDelay &gt; 100) {//100ms durée de chirp 
  } 
} //close countdown(); 


/********************************************************************** 
 *                        JEU1                                        * 
 **********************************************************************/ 
void countdown1(){ 

 static unsigned long lastTick1 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis1 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second1 &gt; 0) { 
    if (millis() - lastTick1 &gt;= 1000) { 
      lastTick1 = millis(); 
      second1--; 

    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute1 &gt; 0) { 
    if (second1 &lt;= 0) { 
      minute1--; 
      second1 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour1 &gt; 0) { 
    if (minute1 &lt;= 0) { 
      hour1--; 
      minute1 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis1 = millis(); 
  if (currentMillis1 - previousTime1 &gt; interval1) 
  { 
    previousTime1 = currentMillis1; 
    previousDelay1 = currentMillis1; 
  } 

  if (currentMillis1 - previousDelay1 &gt; 100) {//100ms durée de chirp 
  } 





} //close countdown1();


/********************************************************************** 
 *                        JEU2                                        * 
 **********************************************************************/ 
void countdown2(){ 

 static unsigned long lastTick2 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis2 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second2 &gt; 0) { 
    if (millis() - lastTick2 &gt;= 1000) { 
      lastTick2 = millis(); 
      second2--; 
    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute2 &gt; 0) { 
    if (second2 &lt;= 0) { 
      minute2--; 
      second2 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour2 &gt; 0) { 
    if (minute2 &lt;= 0) { 
      hour2--; 
      minute2 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis2 = millis(); 
  if (currentMillis2 - previousTime2 &gt; interval1) 
  { 
    previousTime2 = currentMillis2; 
    previousDelay2 = currentMillis2; 
  } 

  if (currentMillis2 - previousDelay2 &gt; 100) {//100ms durée de chirp 
  }





} //close countdown2();



/********************************************************************** 
 *                        JEU3                                        * 
 **********************************************************************/ 
void countdown3(){ 

 static unsigned long lastTick3 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde 
  static unsigned long currentMillis3 = 0; 
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction) 
  // diminuer à une seconde tous 1000 millisecondes 
  if (second3 &gt; 0) { 
    if (millis() - lastTick3 &gt;= 1000) { 
      lastTick3 = millis(); 
      second3--; 


    } 
  } 
 // décrémenter une minute toutes les 60 secondes 
  if (minute3 &gt; 0) { 
    if (second3 &lt;= 0) { 
      minute3--; 
      second3 = 60; // remettre les secondes à 60 
    } 
  } 
  // décrémenter une heure tous les 60 minutes 
  if (hour3 &gt; 0) { 
    if (minute3 &lt;= 0) { 
      hour3--; 
      minute3 = 60; // réinitialiser minutes à 60 
    }//closes if 
  }//closes if 

  //le code ci-dessous bips de la sirène une fois par minute. 
  currentMillis3 = millis(); 
  if (currentMillis3 - previousTime3 &gt; interval1) 
  { 
    previousTime3 = currentMillis3; 
    previousDelay3 = currentMillis3; 
  } 

  if (currentMillis3 - previousDelay3 &gt; 100) {//100ms durée de chirp 
  } 
} //close countdown2(); 
</code></pre>
 13425: <p>That code is a mess. I'm sure you can refactor a lot of it. To get you started here's a C++ class you can use as a countdown timer. I just whipped this up, but it should work. <strike>However, it does not handle the case where <code>millis()</code> overflows (after about 50 days).</strike></p>

<pre class="lang-cpp prettyprint-override"><code>class Countdown {
public:
    const uint32_t ms_per_hour = 60l * 60l * 1000l;
    const uint32_t ms_per_minute = 60l * 1000l;
    const uint32_t ms_per_second = 1000l;

    // Constructor
    Countdown(int hours, int minutes, int seconds) {
        duration = hours * ms_per_hour +
                   minutes * ms_per_minute  +
                   seconds * ms_per_second ;
        started = false;
        finished = false;
    }
    // Call this to start the countdown
    void start() {
        started = true;
        finished = false;
        start_time = millis();
    }

    // Stop the timer
    void stop() {
        finished = true;
    }

    // Is timer running?
    bool is_running() {
        return started == true &amp;&amp; finished == false;
    }

    // Call this to check if the countdown is finished
    bool times_up() {
        if (finished) return true;
        else if (!started) return false;
        if (elapsed_time() &gt;= duration) {
            finished = true;
            return true;
        }
        return false;
    }

    // Returns a string representation of how much time has passed
    const char * get_elapsed(const char *format="hh:mm:ss") {
        return ms_to_string(format, elapsed_time());
    }
    // Returns a string representation of how much time is left
    const char * get_remaining(const char *format="hh:mm:ss") {
        return ms_to_string(format, duration - elapsed_time());
    }

    // Returns an array of decimal digits for display of time passed
    const char * get_digits_elapsed(const char *format="mmss") {
        return ms_to_digits(format, elapsed_time());
    }
    // Returns an array of decimal digits for display of time remaining
    const char * get_digits_remaining(const char *format="mmss") {
        return ms_to_digits(format, duration - elapsed_time());
    }

protected:
    unsigned long elapsed_time() {
        return millis() - start_time;
    }

    bool started, finished;
    uint32_t duration, start_time;
    char buffer[32];

    char * ms_to_digits(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    buffer[index++] = (char)(val / 10);
                    i += 1;
                }
                buffer[index++] = char(val % 10);
            }
        }
        return buffer;
    }

    char * ms_to_string(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        buffer[0] = 0;
        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    index += sprintf(&amp;buffer[index], "%02d", val);
                    i += 1;
                }
                else {
                  index += sprintf(&amp;buffer[index], "%d", val);
                }
            }
            else {
                buffer[index++] = format[i];
            }
        }
        buffer[index] = '\0';
        return buffer;
    }
};
</code></pre>

<p>To use it, you would create 3 objects:</p>

<pre class="lang-cpp prettyprint-override"><code>Countdown cd1(0, 45, 0);  // 45 minutes
Countdown cd2(0, 15, 0);  // 15 minutes
Countdown cd3(0, 15, 0);  // 15 minutes
</code></pre>

<p>Then, start #1 in setup:</p>

<pre class="lang-cpp prettyprint-override"><code>void setup() {
    cd1.start();
}
</code></pre>

<p>And in loop:</p>

<pre class="lang-cpp prettyprint-override"><code>void loop() {
    if (cd3.times_up()) {
       // game over
    }
    else if (cd2.times_up()) {
        // 2nd timer expired, do something
        if (!cd3.is_running()) cd3.start();  // Start #3
        // update display
        tm1637d.display(c3.get_digits_remaining());
    }
    else if (cd1.times_up()) {
        // 1st timer expired, do something
        if (!cd2.is_running()) cd2.start();  // Start #2
        // update display
        tm1637c.display(c2.get_digits_remaining());
    }
    else {
        // update display
        tm1637b.display(c1.get_digits_remaining());
    }
}
</code></pre>
