Interrupt Deadlock

Hi,

I do trackdays in motorcycle.
I found a Lap timer based on arduino on internet : LCD 16*2 and uno with TLE4905.

The lap timer works perfectly, but I wanted to reduce the size and use a Oled 128*32.
I copied the code and change every codes for LCD and adapt for OLED.
No issue, everything works like i want.

The issue is on the "RUN" functions.

I will try to explain you the RUN mode :

  • start the chrono when entering the mode
    -when crossing magnetic loop on track (finish line or intermediate sector) it take the time and continue.
    So i works on intteruption with TLE4905 that call the void : CHRONO()

But this function can work also by pushing a button and not the TLE4905.

It works pefectly with button, but when the first interruption happen, i have a deadlock after Serial.Print, the first action of the chrono() function

I don't understand :

  • UNO + LCD = works perfectly with the same code execpt oled code
  • UNO/NANO + OLED : everything works good except the interruption.

The interruption calls chrono() and deadlock, but using btnRIGHT button, it also call chrono() but it works fine.

Laptimer.ino (22.1 KB)
test_laptimer_oled.ino (23.4 KB)

Please help me :slight_smile:

Please use code tags </> for code, as we do not like to download it.

Ok
Here they are, 1st original code for uno and lcd
2nd adaptation for oled

#include <LiquidCrystal.h>
#include <EEPROM.h>

int SensorPin = 2;
int lap = 0;          // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops  = 0;
int count = 0;        // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;

// variables de sélection des menus
int main_menu_index;

long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;

int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;

const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};


// organisation des données dans l'EEPROM
//
// addresse | type de donnée |      donnée      |
//    0     |      int       | Nbre de partiels |
//    1     |      int       |  Nbre de tours   |
//    2     | unsigned long  |  Best Lap Time   |
//    6     | unsigned long  |    partiel#1     |
//   10     | unsigned long  |    Partiel#2     |
//   15     |      int       | N meilleur tour  |
// 16->19   |      N/A       |  espace vacant   |
//   20     | unsigned long  |      Lap#1       |
//   24     | unsigned long  |      Lap#2       |
//                   ......
//


// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define debounceTime   200
#define NLapsMax        83
#define StopTime    600000

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  delay(200);
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 650)  return btnLEFT;
  if (adc_key_in < 850)  return btnSELECT;
  return btnNONE;

}

// ****************************** initialisation ******************************
void setup()
{
  pinMode(SensorPin, INPUT);
  digitalWrite(SensorPin, HIGH);
  lcd.begin(16, 2);              // start the library
  WelcomScreen();
  MainMenu();
}

// ****************************** écran d'accueil ******************************
void WelcomScreen() {
  lcd.setCursor(0, 0);
  lcd.print("Moiry Racing 58 ");
  lcd.setCursor(0, 1);
  lcd.print("Lap Timer  v1.0 ");
  delay(3000);
}

// ****************************** boucle ******************************
void loop() {
}

// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
  return lap * 12 + 4 * inter + 20;
}

// ****************************** Menu principal ******************************

void MainMenu() {

  // initialisation des variables principales

  Ntops = EEPROM.read(0);           // lecture du nombre de boucles magnétiques
  Nlaps = EEPROM.read(1);           // No du dernier tour couvert
  NbestLap = EEPROM.read(15);       // No du meilleur tour
  address = (Nlaps) * 4 + 20;       // calcul de l'adresse de départ en fonction du nombre de tours
  BestTime = EEPROMReadlong(2);     // meilleur tour
  LapTime = EEPROMReadlong(address);// dernier tour chronométre
  count = 0;                        // remise Ă  jour du comptage des boucles
  main_menu_index = 0;
  a0 = 0;
  a1 = 0;
  chrono_stat = 0;
  updateMain();

  do {

    lcd_key = read_LCD_buttons();

    switch (lcd_key)
    {
      case btnRIGHT:
        {
          break;
        }
      case btnLEFT:
        {
          break;
        }
      case btnUP:
        {
          if (main_menu_index == 0) {
            main_menu_index = 6;
          } else {
            main_menu_index = main_menu_index - 1;
          }
          updateMain();
          break;
        }
      case btnDOWN:
        {
          if (main_menu_index == 6) {
            main_menu_index = 0;
          } else {
            main_menu_index = main_menu_index + 1;
          }
          updateMain();
          break;
        }
      case btnSELECT:
        {
          ModeSelect();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}

// ****************************** Mise Ă  jour de l'affichage du menu principal ******************************

void updateMain() {
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("Select Mode:");
  lcd.setCursor(13, 0);
  lcd.print(main_menu_index + 1);
  lcd.setCursor(14, 0);
  lcd.print("/7");
  lcd.setCursor(0, 1);
  lcd.print(MainMenuEntries[main_menu_index]);
}

// ****************************** sélection du mode ******************************
void ModeSelect() {
  switch (main_menu_index)
  {
    case 0:
      {
        RunMode();
        break;
      }
    case 1:
      {
        if (Nlaps > 0) {
          RetrDash();
        } else {
          NoData();
        }
        break;
      }
    case 2:
      {
        if (Nlaps > 0) {
          RetrDashAuto();
        } else {
          NoData();
        }
        break;
      }
    case 3:
      {
        SetTops();
        break;
      }
    case 4:
      {
        RetrPC();
        break;
      }
    case 5:
      {
        ChronoManu();
        break;
      }
    case 6:
      {
        EraseEEPROM();
        break;
      }
  }
}

// ****************************** mode RUN ******************************
void RunMode() {

  updateRUN();
  attachInterrupt(digitalPinToInterrupt(SensorPin), chrono, RISING);
  exit_loop = 0;

  do {
    lcd_key = read_LCD_buttons();  // read the buttons
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnRIGHT:
        {
          chrono();
          break;
        }
      case btnSELECT:
        {
          detachInterrupt(digitalPinToInterrupt(SensorPin));
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }

    // arrĂȘt du chrono au delĂ  de 10 minutes
    if ((millis() - a1) > StopTime) {
      chrono_stat = 0;
    }
  } while (exit_loop == 0);

}

// ****************************** update affichage RUN ******************************
void updateRUN() {
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("LP:");
  if (Nlaps < 10) {
    lcd.setCursor(4, 0);
  } else {
    lcd.setCursor(3, 0);
  }
  lcd.print(Nlaps);

  lcd.setCursor(0, 1);
  lcd.print("BL:");
  if (NbestLap < 10) {
    lcd.setCursor(4, 1);
  } else {
    lcd.setCursor(3, 1);
  }
  lcd.print(NbestLap);

  BestTime = EEPROMReadlong(2);
  PrintTime(BestTime, 1, 6);

  LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
  PrintTime(LapTime, 0, 6);
}


// ****************************** No data ******************************

void NoData() {
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("    NO DATA     ");
  delay(1000);
  MainMenu();
}

// ****************************** mode retrieve dash ******************************
void RetrDash() {

  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;


  do {

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnDOWN:
        {
          if (temp_lap > 1) {
            temp_lap--;
          } else {
            temp_lap = Nlaps;
          }
          updateRetrDash();
          break;
        }
      case btnUP:
        {
          if (temp_lap > Nlaps - 1) {
            temp_lap = 1;
          } else {
            temp_lap++;
          }
          updateRetrDash();
          break;
        }
      case btnLEFT:
        {
          inter = 1;
          updateRetrDash();
          break;
        }
      case btnRIGHT:
        {
          inter = 2;
          updateRetrDash();
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("LP:");
  lcd.setCursor(3, 0);
  lcd.print(temp_lap);
  address_temp = address_lap(temp_lap, 0);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime, 0, 6);
  lcd.setCursor(0, 1);
  lcd.print("P#");
  lcd.setCursor(2, 1);
  lcd.print(inter);
  address_temp = address_lap(temp_lap, inter);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime, 1, 6);
}

// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;
  a1 = millis();

  do {

    if (millis() - a1 > 1000) {
      if (inter == 1) {
        inter = 2;
        updateRetrDash();
      }
    }

    if (millis() - a1 > 2000) {
      temp_lap = temp_lap - 1;
      if (temp_lap == 0) temp_lap = Nlaps;
      inter = 1;
      updateRetrDash();
      a1 = millis();
    }

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {

  updateTops();
  exit_loop = 0;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (Ntops < 3) Ntops++;
          updateTops();
          break;
        }
      case btnLEFT:
        {
          if (Ntops > 1) Ntops--;
          updateTops();
          break;
        }
      case btnSELECT:
        {
          EEPROM.write(0, Ntops);
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}

// ****************************** Mise Ă  jour de l'affichage du nombre de boucles ******************************

void updateTops() {
  EraseDisplay();
  lcd.setCursor(1, 0);
  lcd.print("NBRE OF INTERM.:");
  lcd.setCursor(7, 1);
  lcd.print(Ntops - 1);
  lcd.setCursor(5, 1);
  lcd.print("<");
  lcd.setCursor(9, 1);
  lcd.print(">");
}

// ****************************** mode retrieve PC ******************************

void RetrPC() {
  EraseDisplay();
  exit_loop = 0;
  lcd.setCursor(0, 0);
  lcd.print(" READY TO SEND ");
  Serial.begin(9600);

  do
  {
    incomingByte = Serial.read();
    // incoming "S"
    if (incomingByte == 83) {
      SendToPC();
    }

    // incoming "E"
    if (incomingByte == 69) {
      EraseEEPROM();
    }

    // incoming "Q"
    if (incomingByte == 81) {
      Serial.end();
      MainMenu();
    }

    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnSELECT:
        {
          Serial.end();
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}


// ****************************** envoi des data PC ******************************

void SendToPC() {

  int temp_lap;
  Serial.println("START");

  for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {

    // liste des temps au tour
    address_temp = address_lap(temp_lap, 0);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;


    Serial.print("Lap:");
    Serial.print(temp_lap);
    Serial.print(" - ");
    Serial.print(minutes);
    Serial.print(":");
    if (secondes < 10) {
      Serial.print("0");
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(".");
    Serial.print(millisecs);


    // intermediate#1
    address_temp = address_lap(temp_lap, 1);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(" - inter#1: ");
    Serial.print(minutes);
    Serial.print(":");
    if (secondes < 10) {
      Serial.print("0");
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(".");
    Serial.print(millisecs);

    // intermediate#2
    address_temp = address_lap(temp_lap, 2);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(" - inter#2: ");
    Serial.print(minutes);
    Serial.print(":");
    if (secondes < 10) {
      Serial.print("0");
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(".");
    Serial.println(millisecs);
  }

  // meilleur temps
  Time = EEPROMReadlong(2);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.println("----------");

  Serial.print("Best lap: ");
  Serial.print(NbestLap);
  Serial.print(" - ");
  Serial.print(minutes);
  Serial.print(":");
  if (secondes < 10) {
    Serial.print("0");
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(".");
  Serial.print(millisecs);


  // inter#1
  Time = EEPROMReadlong(6);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(" - inter#1: ");
  Serial.print(minutes);
  Serial.print(":");
  if (secondes < 10) {
    Serial.print("0");
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(".");
  Serial.print(millisecs);


  // inter#2
  Time = EEPROMReadlong(10);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(" -inter#2: ");
  Serial.print(minutes);
  Serial.print(":");
  if (secondes < 10) {
    Serial.print("0");
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(".");
  Serial.println(millisecs);
  Serial.println("----------");
  Serial.println("END");

}




// ****************************** chronometre ******************************
void ChronoManu() {

  exit_loop = 0;
  ChronoManu_stat = 0;
  ResetTime = 1;
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("TIME:           ");
  PrintTime(0, 0, 6);
  ChronoManu_count = 0;
  a0 = 0UL;
  a1 = 0UL;
  Time = 0UL;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (ChronoManu_stat == 0) {
            ChronoManu_stat = 1;
            if (ResetTime == 1) {
              a1 = millis();
              a0 = millis();
              ChronoManu_count = 0;
              ResetTime = 0;
            }
          } else {
            PrintTime(Time, 0, 6);
            ChronoManu_stat = 0;
          }
          break;
        }
      case btnLEFT:
        {
          ResetTime = 1;
          a1 = millis();
          a0 = millis();
          EraseDisplay();
          lcd.setCursor(0, 0);
          lcd.print("TIME:           ");
          PrintTime(0, 0, 6);
          break;
        }
      case btnDOWN:
        {
          if (ChronoManu_stat == 1) {
            ChronoManu_count = ChronoManu_count + 1;
            lcd.setCursor(0, 1);
            lcd.print("LAP#            ");
            lcd.setCursor(4, 1);
            lcd.print(ChronoManu_count);
            PrintTime(Time1, 1, 6);
            a0 = millis();
          }
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
    if (ChronoManu_stat == 1) {
      lcd.setCursor(0, 0);
      lcd.print("TIME:");
      Time = millis() - a1;
      Time1 = millis() - a0;
      PrintTime(Time, 0, 6);
    } else {
      a1 = millis() - Time;
    }
  } while (exit_loop == 0);
}

void test() {

}


// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
  EraseDisplay();
  lcd.setCursor(0, 0);
  lcd.print("  ERASE DATA?   ");
  lcd.setCursor(0, 1);
  lcd.print(" NO<--   -->YES ");

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
            address = address_lap(Nlaps, 0);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 1);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 2);
            EEPROMWritelong(address, 0UL);
            lcd.setCursor(0, 0);
            lcd.print("   ERASING...   ");
            lcd.setCursor(0, 1);
            lcd.print("                ");
            lcd.setCursor(7, 1);
            lcd.print(Nlaps);
          }

          EEPROM.write(0, 1);
          EEPROM.write(1, 0);
          EEPROMWritelong(2, 3599999UL);
          EEPROMWritelong(6, 3599999UL);
          EEPROMWritelong(10, 3599999UL);
          EEPROMWritelong(15, 0);
          setup();
          break;
        }
      case btnLEFT:
        {
          MainMenu();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}




// ****************************** Affiche un chrono à l'écran ******************************

void PrintTime(unsigned long Time, int y, int x)
{

  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  if (minutes < 10) {
    lcd.setCursor(x, y);
    lcd.print(" ");
    lcd.setCursor(x + 1, y);
    lcd.print(minutes);
  } else {
    lcd.setCursor(x, y);
    lcd.print(minutes);
  }

  lcd.setCursor(x + 2, y);
  lcd.print(":");

  if (secondes < 10) {
    lcd.setCursor(x + 3, y);
    lcd.print("0");
    lcd.setCursor(x + 4, y);
    lcd.print(secondes);
  } else {
    lcd.setCursor(x + 3, y);
    lcd.print(secondes);
  }
  lcd.setCursor(x + 5, y);
  lcd.print(".");
  lcd.setCursor(x + 6, y);
  lcd.print(millisecs);
}


// ****************************** Efface l'affichage ******************************

void EraseDisplay() {
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
}


// ****************************** controle du chrono ******************************

void chrono() {

  Serial.println(millis() - a0);
  if (millis() - a0 > debounceTime) {
    if (chrono_stat == 1) {

      if (count > Ntops - 2) {
        LapTime = millis() - a1;
        a1 = millis();

        if (LapTime < BestTime) {
          BestTime = LapTime;
          NbestLap = Nlaps + 1;
          EEPROMWritelong(2, BestTime);
          EEPROMWritelong(6, interm[0]);
          EEPROMWritelong(10, interm[1]);
          EEPROM.write(15, NbestLap);
          lcd.setCursor(5, 0);
          lcd.print(">");
          lcd.setCursor(16, 0);
          lcd.print("<");
        }

        Nlaps = Nlaps + 1;
        EEPROM.write(1, Nlaps);
        address = address_lap(Nlaps, 0);
        EEPROMWritelong(address, LapTime);
        address = address_lap(Nlaps, 1);
        EEPROMWritelong(address, interm[0]);
        address = address_lap(Nlaps, 2);
        EEPROMWritelong(address, interm[1]);
        updateRUN();

        count = 0;
        if (Nlaps > NLapsMax) Nlaps = 0;

      } else {
        interm[count] = millis() - a1;
        count = count + 1;
      }

    } else {
      a1 = millis();
      chrono_stat = 1;
      count = 1;
    }
  }
  a0 = millis();
}


// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}


// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

I#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

int SensorPin = 2;
int lap = 0;          // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops  = 2;
int count = 0;        // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;
int testint=0;
// variables de sélection des menus
int main_menu_index;

long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;

int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;

const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};


// organisation des données dans l'EEPROM
//
// addresse | type de donnée |      donnée      |
//    0     |      int       | Nbre de partiels |
//    1     |      int       |  Nbre de tours   |
//    2     | unsigned long  |  Best Lap Time   |
//    6     | unsigned long  |    partiel#1     |
//   10     | unsigned long  |    Partiel#2     |
//   15     |      int       | N meilleur tour  |
// 16->19   |      N/A       |  espace vacant   |
//   20     | unsigned long  |      Lap#1       |
//   24     | unsigned long  |      Lap#2       |
//                   ......
//


// select the pins used on the LCD panel
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);
  
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define debounceTime   200
#define NLapsMax        83
#define StopTime    600000

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  delay(200);
  if (adc_key_in < 75)   return btnUP;
  if (adc_key_in < 260)  return btnSELECT;
  if (adc_key_in < 440)  return btnDOWN;
  if (adc_key_in < 620)  return btnRIGHT;
  if (adc_key_in < 800)  return btnLEFT;
  if (adc_key_in < 950)  return btnNONE;
  return btnNONE;
 

}

// ****************************** initialisation ******************************
void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin, INPUT);
  digitalWrite(SensorPin, HIGH);
  display.begin(SSD1306_SWITCHCAPVCC,0x3C);
     // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
 
 WelcomScreen();
  MainMenu();
}

// ****************************** écran d'accueil ******************************
void WelcomScreen() {
display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
display.println(F("Lap Timer V2"));
display.display();
  }

// ****************************** boucle ******************************
void loop() {
}

// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
  return lap * 12 + 4 * inter + 20;
}

// ****************************** Menu principal ******************************

void MainMenu() {

  // initialisation des variables principales
   
  Ntops = EEPROM.read(0);           // lecture du nombre de boucles magnétiques
  Nlaps = EEPROM.read(1);           // No du dernier tour couvert
  NbestLap = EEPROM.read(15);       // No du meilleur tour
  address = (Nlaps) * 4 + 20;       // calcul de l'adresse de départ en fonction du nombre de tours
  BestTime = EEPROMReadlong(2);     // meilleur tour
  LapTime = EEPROMReadlong(address);// dernier tour chronométre
  count = 0;                        // remise Ă  jour du comptage des boucles
  main_menu_index = 0;
  a0 = 0;
  a1 = 0;
  chrono_stat = 0;
  updateMain();

  do {
    lcd_key = read_LCD_buttons();

    switch (lcd_key)
    {
      case btnRIGHT:
        {
          break;
        }
      case btnLEFT:
        {
          break;
        }
      case btnDOWN:
        {
          if (main_menu_index == 0) {
            main_menu_index = 6;
          } else {
            main_menu_index = main_menu_index - 1;
          }
          updateMain();
          break;
        }
      case btnUP:
        {
          if (main_menu_index == 6) {
            main_menu_index = 0;
          } else {
            main_menu_index = main_menu_index + 1;
          }
          updateMain();
          break;
        }
      case btnSELECT:
        {
          ModeSelect();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}

// ****************************** Mise Ă  jour de l'affichage du menu principal ******************************

void updateMain() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("Select Mode:"));
  display.print(main_menu_index + 1);
  display.println(F("/7"));
  display.print(MainMenuEntries[main_menu_index]);
  display.display();
}

// ****************************** sélection du mode ******************************
void ModeSelect() {
  switch (main_menu_index)
  {
    case 0:
      {
        RunMode();
        break;
      }
    case 1:
      {
        if (Nlaps > 0) {
          RetrDash();
        } else {
          NoData();
        }
        break;
      }
    case 2:
      {
        if (Nlaps > 0) {
          RetrDashAuto();
        } else {
          NoData();
        }
        break;
      }
    case 3:
      {
        SetTops();
        break;
      }
    case 4:
      {
        RetrPC();
        break;
      }
    case 5:
      {
        ChronoManu();
        break;
      }
    case 6:
      {
        EraseEEPROM();
        break;
      }
  }
}

// ****************************** mode RUN ******************************
void RunMode() {
  
  updateRUN();
  attachInterrupt(digitalPinToInterrupt(SensorPin), chrono, RISING);
  exit_loop = 0;
 

  do {
    lcd_key = read_LCD_buttons();  // read the buttons
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnRIGHT:
        {
          chrono();
          break;
        }
      case btnSELECT:
        {
          detachInterrupt(digitalPinToInterrupt(SensorPin));
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }

    // arrĂȘt du chrono au delĂ  de 10 minutes
    if ((millis() - a1) > StopTime) {
      chrono_stat = 0;
    }
  } while (exit_loop == 0);

}

// ****************************** update affichage RUN ******************************
void updateRUN() {

  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
  PrintTime(LapTime);
  
  display.print(F("BL: "));
  BestTime = EEPROMReadlong(2);
  PrintTime(BestTime);
}


// ****************************** No data ******************************

void NoData() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("    NO DATA     "));
  display.display();
  delay(1000);
  MainMenu();
}

// ****************************** mode retrieve dash ******************************
void RetrDash() {

 temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;


  do {

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnDOWN:
        {
          if (temp_lap > 1) {
            temp_lap--;
          } else {
            temp_lap = Nlaps;
          }
          updateRetrDash();
          break;
        }
      case btnUP:
        {
          if (temp_lap > Nlaps - 1) {
            temp_lap = 1;
          } else {
            temp_lap++;
          }
          updateRetrDash();
          break;
        }
      case btnLEFT:
        {
          inter = 1;
          updateRetrDash();
          break;
        }
      case btnRIGHT:
        {
          inter = 2;
          updateRetrDash();
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  display.print(temp_lap);
  address_temp = address_lap(temp_lap, 0);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.setCursor(0, 1);
  display.print(F("P#"));
  display.setCursor(2, 1);
  display.print(inter);
  address_temp = address_lap(temp_lap, inter);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.display();
}

// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;
  a1 = millis();

  do {

    if (millis() - a1 > 1000) {
      if (inter == 1) {
        inter = 2;
        updateRetrDash();
      }
    }

    if (millis() - a1 > 2000) {
      temp_lap = temp_lap - 1;
      if (temp_lap == 0) temp_lap = Nlaps;
      inter = 1;
      updateRetrDash();
      a1 = millis();
    }

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {

  updateTops();
  exit_loop = 0;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (Ntops < 3) Ntops++;
          updateTops();
          break;
        }
      case btnLEFT:
        {
          if (Ntops > 1) Ntops--;
          updateTops();
          break;
        }
      case btnSELECT:
        {
          EEPROM.write(0, Ntops);
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}

// ****************************** Mise Ă  jour de l'affichage du nombre de boucles ******************************

void updateTops() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("NBRE OF INTERM.:"));
  display.print(F("     <"));
  display.print(Ntops - 1);
  display.println(F(">"));
  display.display();
}

// ****************************** mode retrieve PC ******************************

void RetrPC() {
  display.clearDisplay();
  exit_loop = 0;
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F(" READY TO SEND "));
  display.display();
  Serial.begin(9600);

  do
  {
    incomingByte = Serial.read();
    // incoming "S"
    if (incomingByte == 83) {
      SendToPC();
    }

    // incoming "E"
    if (incomingByte == 69) {
      EraseEEPROM();
    }

    // incoming "Q"
    if (incomingByte == 81) {
      Serial.end();
      MainMenu();
    }

    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnSELECT:
        {
          Serial.end();
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}


// ****************************** envoi des data PC ******************************

void SendToPC() {

  int temp_lap;
  Serial.println("START");

  for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {

    // liste des temps au tour
    address_temp = address_lap(temp_lap, 0);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;


    Serial.print(F("Lap:"));
    Serial.print(temp_lap);
    Serial.print(F(" - "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);


    // intermediate#1
    address_temp = address_lap(temp_lap, 1);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#1: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);

    // intermediate#2
    address_temp = address_lap(temp_lap, 2);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#2: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.println(millisecs);
  }

  // meilleur temps
  Time = EEPROMReadlong(2);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.println(F("----------"));

  Serial.print(F("Best lap: "));
  Serial.print(NbestLap);
  Serial.print(F(" - "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#1
  Time = EEPROMReadlong(6);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" - inter#1: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#2
  Time = EEPROMReadlong(10);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" -inter#2: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.println(millisecs);
  Serial.println(F("----------"));
  Serial.println(F("END"));

}




// ****************************** chronometre ******************************
void ChronoManu() {
   
 exit_loop = 0;
  ChronoManu_stat = 0;
  ResetTime = 1;
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("TIME:  "));
  PrintTime(0);
  display.display();
  ChronoManu_count = 0;
  a0 = 0UL;
  a1 = 0UL;
  Time = 0UL;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (ChronoManu_stat == 0) {
           ChronoManu_stat = 1;
            if (ResetTime == 1) {
              a1 = millis();
              a0 = millis();
              ChronoManu_count = 0;
              ResetTime = 0;
            }
          } else {
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.display();
            ChronoManu_stat = 0;
          }
          break;
        }
      case btnLEFT:
        {
          ResetTime = 1;
          a1 = millis();
          a0 = millis();
          display.clearDisplay();
          display.setTextSize(1); // Draw 2X-scale text
          display.setTextColor(WHITE);
          display.setCursor(0, 0);
          display.print(F("TIME:  "));
          PrintTime(0);
          display.display();
          break;
        }
      case btnDOWN:
        {
          if (ChronoManu_stat == 1) {
            ChronoManu_count = ChronoManu_count + 1;
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.print(F("LAP #"));
            display.print(ChronoManu_count);
            display.print("   ");
            PrintTime(Time1);
            display.display();
            a0 = millis();
          }
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
    if (ChronoManu_stat == 1) {

      display.setTextSize(1); // Draw 2X-scale text
      display.setTextColor(WHITE);
      display.setCursor(0, 0);
      display.fillRect(0, 0, 127, 6, BLACK);
      display.print(F("TIME:  "));
      Time = millis() - a1;
      Time1 = millis() - a0;
      PrintTime(Time);
    display.display();
    } else {
     a1 = millis() - Time;
   }
  } while (exit_loop == 0);
}


// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("  ERASE DATA?   "));
  display.print(F(" NO<--   -->YES "));
  display.display();

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
            address = address_lap(Nlaps, 0);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 1);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 2);
            EEPROMWritelong(address, 0UL);
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.println(F("   ERASING...   "));
            display.print(F("                "));
            display.print(Nlaps);
            display.display();
          }

          EEPROM.write(0, 1);
          EEPROM.write(1, 0);
          EEPROMWritelong(2, 3599999UL);
          EEPROMWritelong(6, 3599999UL);
          EEPROMWritelong(10, 3599999UL);
          EEPROMWritelong(15, 0);
          setup();
          break;
        }
      case btnLEFT:
        {
          MainMenu();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}




// ****************************** Affiche un chrono à l'écran ******************************

void PrintTime(unsigned long Time)//, int y, int x)
{

  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
display.print(minutes);
display.print(F("'"));
display.print(secondes);
display.print(F("."));
display.println(millisecs);
display.display();
}



// ****************************** controle du chrono ******************************

void chrono() {

  Serial.println(millis() - a0);
  if (millis() - a0 > debounceTime) {
    if (chrono_stat == 1) {
      
      if (count > Ntops - 2) {
        LapTime = millis() - a1;
        a1 = millis();
        
        if (LapTime < BestTime) {
          BestTime = LapTime;
          NbestLap = Nlaps + 1;
          EEPROMWritelong(2, BestTime);
          EEPROMWritelong(6, interm[0]);
          EEPROMWritelong(10, interm[1]);
          EEPROM.write(15, NbestLap);
        }

        Nlaps = Nlaps + 1;
        EEPROM.write(1, Nlaps);
        address = address_lap(Nlaps, 0);
        EEPROMWritelong(address, LapTime);
        address = address_lap(Nlaps, 1);
        EEPROMWritelong(address, interm[0]);
        address = address_lap(Nlaps, 2);
        EEPROMWritelong(address, interm[1]);
        updateRUN();

        count = 0;
        if (Nlaps > NLapsMax) Nlaps = 0;
        
        } 
      else {
        interm[count] = millis() - a1;
        count = count + 1;
      }

    } else {
      a1 = millis();
      chrono_stat = 1;
      count = 1;
    }
  }
  a0 = millis();
}


// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}


// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

Each interrupt routine should be as short as possible. Serial.print() should not occur there. Set a flag and call the worker function from loop().

Hi
Thank you
I already try without Serial.print, but deadlock anyway.
with Serial.print active, when interrupt occures, the serial.print works then the deadlock happens.
I also try without all the oled display functions, deadlock anyway.

why on the original project it doesn't create deadlock? It also use interrupt and serial. print()

Thank you

I think i have a good understanding of the code, but as I am not the creator, i don't masterise it.

The LCD library seems not to use interrupts.

Set a flag in the ISR and call chrono() only from loop() when the flag is set.

Ugly hack: turn interrupts on in the ISR.

1 Like

Thank you.
I don't think a correctly understand.
I didn't use flag yet.

the ISR, now it is my chrono function.
I should remove chrono and create an ISR with a flag that goes from low to high.
And then right after the attachtointerrupt line, i call my chrono() functions, then drop down the flag?
Thank for the help

Correct.

volatile bool DoI = false;
void myisr()
{
if ( DoI == false )
{
DoI=true;
}
}

voiding loopie()
{

if (DoI)
{
 handleDoI();
DoI=false;
}

}

void handleDoI()
{
the code for the interrupt
}
1 Like

Thank you
I will do that asap and tell you

Hi again,

I do the modification, but interruption doesn't work at all, no interruption detect, I try with the hall effect sensro, but also a push button to be sure, and even connecting a ground cable to the cable from D2, nothing happen.
But the variable DoI is print in serial as True (1) at the launch of RunMode without any interruption since the beginning
I don't understand, all the rest of the program works fine.
So no deadlock but no interruption either.

thank you

#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

int SensorPin = 2;
int lap = 0;          // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops  = 2;
int count = 0;        // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;
int testint = 0;
// variables de sélection des menus
int main_menu_index;

volatile bool DoI = false;

long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;

int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;

const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};


// organisation des données dans l'EEPROM
//
// addresse | type de donnée |      donnée      |
//    0     |      int       | Nbre de partiels |
//    1     |      int       |  Nbre de tours   |
//    2     | unsigned long  |  Best Lap Time   |
//    6     | unsigned long  |    partiel#1     |
//   10     | unsigned long  |    Partiel#2     |
//   15     |      int       | N meilleur tour  |
// 16->19   |      N/A       |  espace vacant   |
//   20     | unsigned long  |      Lap#1       |
//   24     | unsigned long  |      Lap#2       |
//                   ......
//


// select the pins used on the LCD panel
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define debounceTime   200
#define NLapsMax        83
#define StopTime    600000

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  delay(200);
  if (adc_key_in < 75)   return btnUP;
  if (adc_key_in < 260)  return btnSELECT;
  if (adc_key_in < 440)  return btnDOWN;
  if (adc_key_in < 620)  return btnRIGHT;
  if (adc_key_in < 800)  return btnLEFT;
  if (adc_key_in < 950)  return btnNONE;
  return btnNONE;


}

// ****************************** initialisation ******************************
void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin, INPUT);
  digitalWrite(SensorPin, HIGH);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }

  WelcomScreen();
  MainMenu();
}

// ****************************** écran d'accueil ******************************
void WelcomScreen() {
  display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("Lap Timer V2"));
  display.display();
}

// ****************************** boucle ******************************
void loop() {
}

// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
  return lap * 12 + 4 * inter + 20;
}

// ****************************** Menu principal ******************************

void MainMenu() {

  // initialisation des variables principales

  Ntops = EEPROM.read(0);           // lecture du nombre de boucles magnétiques
  Nlaps = EEPROM.read(1);           // No du dernier tour couvert
  NbestLap = EEPROM.read(15);       // No du meilleur tour
  address = (Nlaps) * 4 + 20;       // calcul de l'adresse de départ en fonction du nombre de tours
  BestTime = EEPROMReadlong(2);     // meilleur tour
  LapTime = EEPROMReadlong(address);// dernier tour chronométre
  count = 0;                        // remise Ă  jour du comptage des boucles
  main_menu_index = 0;
  a0 = 0;
  a1 = 0;
  chrono_stat = 0;
  updateMain();

  do {
    lcd_key = read_LCD_buttons();

    switch (lcd_key)
    {
      case btnRIGHT:
        {
          break;
        }
      case btnLEFT:
        {
          break;
        }
      case btnDOWN:
        {
          if (main_menu_index == 0) {
            main_menu_index = 6;
          } else {
            main_menu_index = main_menu_index - 1;
          }
          updateMain();
          break;
        }
      case btnUP:
        {
          if (main_menu_index == 6) {
            main_menu_index = 0;
          } else {
            main_menu_index = main_menu_index + 1;
          }
          updateMain();
          break;
        }
      case btnSELECT:
        {
          ModeSelect();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}

// ****************************** Mise Ă  jour de l'affichage du menu principal ******************************

void updateMain() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("Select Mode:"));
  display.print(main_menu_index + 1);
  display.println(F("/7"));
  display.print(MainMenuEntries[main_menu_index]);
  display.display();
}

// ****************************** sélection du mode ******************************
void ModeSelect() {
  switch (main_menu_index)
  {
    case 0:
      {
        RunMode();
        break;
      }
    case 1:
      {
        if (Nlaps > 0) {
          RetrDash();
        } else {
          NoData();
        }
        break;
      }
    case 2:
      {
        if (Nlaps > 0) {
          RetrDashAuto();
        } else {
          NoData();
        }
        break;
      }
    case 3:
      {
        SetTops();
        break;
      }
    case 4:
      {
        RetrPC();
        break;
      }
    case 5:
      {
        ChronoManu();
        break;
      }
    case 6:
      {
        EraseEEPROM();
        break;
      }
  }
}

// ****************************** mode RUN ******************************
void RunMode() {

  updateRUN();
  attachInterrupt(digitalPinToInterrupt(SensorPin), myisr, RISING);
  exit_loop = 0;
  Serial.println("DOI state");
  Serial.println(DoI);

  if (DoI)
  {
    chrono();
    DoI = false;
  }

  do {
    lcd_key = read_LCD_buttons();  // read the buttons
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnRIGHT:
        {
          chrono();
          break;
        }
      case btnSELECT:
        {
          detachInterrupt(digitalPinToInterrupt(SensorPin));
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }

    // arrĂȘt du chrono au delĂ  de 10 minutes
    if ((millis() - a1) > StopTime) {
      chrono_stat = 0;
    }
  } while (exit_loop == 0);

}

// ****************************** update affichage RUN ******************************
void updateRUN() {

  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
  PrintTime(LapTime);

  display.print(F("BL: "));
  BestTime = EEPROMReadlong(2);
  PrintTime(BestTime);
}


// ****************************** No data ******************************

void NoData() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("    NO DATA     "));
  display.display();
  delay(1000);
  MainMenu();
}

// ****************************** mode retrieve dash ******************************
void RetrDash() {

  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;


  do {

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnDOWN:
        {
          if (temp_lap > 1) {
            temp_lap--;
          } else {
            temp_lap = Nlaps;
          }
          updateRetrDash();
          break;
        }
      case btnUP:
        {
          if (temp_lap > Nlaps - 1) {
            temp_lap = 1;
          } else {
            temp_lap++;
          }
          updateRetrDash();
          break;
        }
      case btnLEFT:
        {
          inter = 1;
          updateRetrDash();
          break;
        }
      case btnRIGHT:
        {
          inter = 2;
          updateRetrDash();
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  display.print(temp_lap);
  address_temp = address_lap(temp_lap, 0);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.setCursor(0, 1);
  display.print(F("P#"));
  display.setCursor(2, 1);
  display.print(inter);
  address_temp = address_lap(temp_lap, inter);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.display();
}

// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;
  a1 = millis();

  do {

    if (millis() - a1 > 1000) {
      if (inter == 1) {
        inter = 2;
        updateRetrDash();
      }
    }

    if (millis() - a1 > 2000) {
      temp_lap = temp_lap - 1;
      if (temp_lap == 0) temp_lap = Nlaps;
      inter = 1;
      updateRetrDash();
      a1 = millis();
    }

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {

  updateTops();
  exit_loop = 0;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (Ntops < 3) Ntops++;
          updateTops();
          break;
        }
      case btnLEFT:
        {
          if (Ntops > 1) Ntops--;
          updateTops();
          break;
        }
      case btnSELECT:
        {
          EEPROM.write(0, Ntops);
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}

// ****************************** Mise Ă  jour de l'affichage du nombre de boucles ******************************

void updateTops() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("NBRE OF INTERM.:"));
  display.print(F("     <"));
  display.print(Ntops - 1);
  display.println(F(">"));
  display.display();
}

// ****************************** mode retrieve PC ******************************

void RetrPC() {
  display.clearDisplay();
  exit_loop = 0;
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F(" READY TO SEND "));
  display.display();
  Serial.begin(9600);

  do
  {
    incomingByte = Serial.read();
    // incoming "S"
    if (incomingByte == 83) {
      SendToPC();
    }

    // incoming "E"
    if (incomingByte == 69) {
      EraseEEPROM();
    }

    // incoming "Q"
    if (incomingByte == 81) {
      Serial.end();
      MainMenu();
    }

    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnSELECT:
        {
          Serial.end();
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}


// ****************************** envoi des data PC ******************************

void SendToPC() {

  int temp_lap;
  Serial.println("START");

  for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {

    // liste des temps au tour
    address_temp = address_lap(temp_lap, 0);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;


    Serial.print(F("Lap:"));
    Serial.print(temp_lap);
    Serial.print(F(" - "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);


    // intermediate#1
    address_temp = address_lap(temp_lap, 1);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#1: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);

    // intermediate#2
    address_temp = address_lap(temp_lap, 2);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#2: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.println(millisecs);
  }

  // meilleur temps
  Time = EEPROMReadlong(2);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.println(F("----------"));

  Serial.print(F("Best lap: "));
  Serial.print(NbestLap);
  Serial.print(F(" - "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#1
  Time = EEPROMReadlong(6);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" - inter#1: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#2
  Time = EEPROMReadlong(10);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" -inter#2: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.println(millisecs);
  Serial.println(F("----------"));
  Serial.println(F("END"));

}




// ****************************** chronometre ******************************
void ChronoManu() {

  exit_loop = 0;
  ChronoManu_stat = 0;
  ResetTime = 1;
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("TIME:  "));
  PrintTime(0);
  display.display();
  ChronoManu_count = 0;
  a0 = 0UL;
  a1 = 0UL;
  Time = 0UL;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (ChronoManu_stat == 0) {
            ChronoManu_stat = 1;
            if (ResetTime == 1) {
              a1 = millis();
              a0 = millis();
              ChronoManu_count = 0;
              ResetTime = 0;
            }
          } else {
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.display();
            ChronoManu_stat = 0;
          }
          break;
        }
      case btnLEFT:
        {
          ResetTime = 1;
          a1 = millis();
          a0 = millis();
          display.clearDisplay();
          display.setTextSize(1); // Draw 2X-scale text
          display.setTextColor(WHITE);
          display.setCursor(0, 0);
          display.print(F("TIME:  "));
          PrintTime(0);
          display.display();
          break;
        }
      case btnDOWN:
        {
          if (ChronoManu_stat == 1) {
            ChronoManu_count = ChronoManu_count + 1;
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.print(F("LAP #"));
            display.print(ChronoManu_count);
            display.print("   ");
            PrintTime(Time1);
            display.display();
            a0 = millis();
          }
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
    if (ChronoManu_stat == 1) {

      display.setTextSize(1); // Draw 2X-scale text
      display.setTextColor(WHITE);
      display.setCursor(0, 0);
      display.fillRect(0, 0, 127, 6, BLACK);
      display.print(F("TIME:  "));
      Time = millis() - a1;
      Time1 = millis() - a0;
      PrintTime(Time);
      display.display();
    } else {
      a1 = millis() - Time;
    }
  } while (exit_loop == 0);
}


// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("  ERASE DATA?   "));
  display.print(F(" NO<--   -->YES "));
  display.display();

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
            address = address_lap(Nlaps, 0);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 1);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 2);
            EEPROMWritelong(address, 0UL);
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.println(F("   ERASING...   "));
            display.print(F("                "));
            display.print(Nlaps);
            display.display();
          }

          EEPROM.write(0, 1);
          EEPROM.write(1, 0);
          EEPROMWritelong(2, 3599999UL);
          EEPROMWritelong(6, 3599999UL);
          EEPROMWritelong(10, 3599999UL);
          EEPROMWritelong(15, 0);
          setup();
          break;
        }
      case btnLEFT:
        {
          MainMenu();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}




// ****************************** Affiche un chrono à l'écran ******************************

void PrintTime(unsigned long Time)//, int y, int x)
{

  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
  display.print(minutes);
  display.print(F("'"));
  display.print(secondes);
  display.print(F("."));
  display.println(millisecs);
  display.display();
}



// ****************************** controle du chrono ******************************

void chrono() {

  Serial.println(millis() - a0);
  if (millis() - a0 > debounceTime) {
    if (chrono_stat == 1) {

      if (count > Ntops - 2) {
        LapTime = millis() - a1;
        a1 = millis();

        if (LapTime < BestTime) {
          BestTime = LapTime;
          NbestLap = Nlaps + 1;
          EEPROMWritelong(2, BestTime);
          EEPROMWritelong(6, interm[0]);
          EEPROMWritelong(10, interm[1]);
          EEPROM.write(15, NbestLap);
        }

        Nlaps = Nlaps + 1;
        EEPROM.write(1, Nlaps);
        address = address_lap(Nlaps, 0);
        EEPROMWritelong(address, LapTime);
        address = address_lap(Nlaps, 1);
        EEPROMWritelong(address, interm[0]);
        address = address_lap(Nlaps, 2);
        EEPROMWritelong(address, interm[1]);
        updateRUN();

        count = 0;
        if (Nlaps > NLapsMax) Nlaps = 0;

      }
      else {
        interm[count] = millis() - a1;
        count = count + 1;
      }

    } else {
      a1 = millis();
      chrono_stat = 1;
      count = 1;
    }
  }
  a0 = millis();
}


// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}


// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

void myisr()
{
  if ( DoI == false )
  {
    DoI = true;
  }
}

I have done a simple sketch just to check wiring and interruption program, it works perfectly

Why do you check DoI in myisr()? Just set it and done.

Why do you detachInterrupt() at all?

Check DoI in loop(), not buried in some function.

I check it with a IF because Idahowalker does it in his codes :sweat_smile:

The Serial.print(DoI) I use is in normal loop ,not interrupt one, but it is at TRUE even at the beginning of RunMODE even if it is stated at false at the beginning of the program.
But it doesn't trigg the chrono() even at true as it should do
Honnestly I don't understand all, i try to do what you suggest.

The detach is done by the creator of the code when we exit Runmode, in order to there is no interruption in the other mode.
The issue I have is inside RunMode, no interruption is detected inside RunMODE. Detach happen only when exiting.
I just check without the detach (commenting it) but still no interruption detect, but my physical setup is ok with a simple code for interruption test.

Yesterday the interruption was detect but deadlock, now no interruption at all

I just succed having interrupt and the feeling it is working correctly, I have to do a lot of simulation and tests
because sometimes the best lap time is 0.5s and after it goes at arround 25minutes :slight_smile:

here is the modifiication and code :
writing the if (DoI){chrono();} inside the Do function of RunMODe and not at the beginning of the RunMODE funct

After testing I will tell you.

thank you for the help until now

#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

int SensorPin = 2;
int lap = 0;          // numéro du tour en cours
int Nlaps = 0;
int NbestLap = 0;
int Ntops  = 2;
int count = 0;        // comptage des boucles
int chrono_stat = 0;
byte incomingByte;
int ChronoManu_stat = 0;
int ResetTime = 0;
int ChronoManu_count = 0;
int exit_loop = 0;
int testint = 0;
// variables de sélection des menus
int main_menu_index;

volatile bool DoI = false;

long address = 0;
long address_temp = 0;
unsigned long BestTime;
unsigned long LapTime;
unsigned long heures;
unsigned long minutes;
unsigned long secondes;
unsigned long millisecs;
unsigned long a0;
unsigned long a1;
unsigned long interm[] = {0, 0};
unsigned long TManu;
int inter;

int temp_lap;
unsigned long Time = 0;
unsigned long Time1 = 0;

const String MainMenuEntries[] = {" LAP TIMER", " RETRIEVE LAPS", " RETR. LAPS AUTO", " NBR of INTERM.", " RETRIEVE on PC", " CHRONOMETER", " ERASE EEPROM"};


// organisation des données dans l'EEPROM
//
// addresse | type de donnée |      donnée      |
//    0     |      int       | Nbre de partiels |
//    1     |      int       |  Nbre de tours   |
//    2     | unsigned long  |  Best Lap Time   |
//    6     | unsigned long  |    partiel#1     |
//   10     | unsigned long  |    Partiel#2     |
//   15     |      int       | N meilleur tour  |
// 16->19   |      N/A       |  espace vacant   |
//   20     | unsigned long  |      Lap#1       |
//   24     | unsigned long  |      Lap#2       |
//                   ......
//


// select the pins used on the LCD panel
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define debounceTime   200
#define NLapsMax        83
#define StopTime    600000

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  delay(200);
  if (adc_key_in < 75)   return btnUP;
  if (adc_key_in < 260)  return btnSELECT;
  if (adc_key_in < 440)  return btnDOWN;
  if (adc_key_in < 620)  return btnRIGHT;
  if (adc_key_in < 800)  return btnLEFT;
  if (adc_key_in < 950)  return btnNONE;
  return btnNONE;


}

// ****************************** initialisation ******************************
void setup()
{
  Serial.begin(9600);
  pinMode(SensorPin, INPUT);
  digitalWrite(SensorPin, HIGH);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }

  //WelcomScreen();
  //MainMenu();
}

// ****************************** écran d'accueil ******************************
void WelcomScreen() {
  display.clearDisplay();
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("Lap Timer V2"));
  display.display();
}

// ****************************** boucle ******************************
void loop() {
   WelcomScreen();
  MainMenu();
}

// ****************************** adressage de l'EEPROM ******************************
long address_lap(int lap, int inter) {
  return lap * 12 + 4 * inter + 20;
}

// ****************************** Menu principal ******************************

void MainMenu() {

  // initialisation des variables principales

  Ntops = EEPROM.read(0);           // lecture du nombre de boucles magnétiques
  Nlaps = EEPROM.read(1);           // No du dernier tour couvert
  NbestLap = EEPROM.read(15);       // No du meilleur tour
  address = (Nlaps) * 4 + 20;       // calcul de l'adresse de départ en fonction du nombre de tours
  BestTime = EEPROMReadlong(2);     // meilleur tour
  LapTime = EEPROMReadlong(address);// dernier tour chronométre
  count = 0;                        // remise Ă  jour du comptage des boucles
  main_menu_index = 0;
  a0 = 0;
  a1 = 0;
  chrono_stat = 0;
  updateMain();

  do {
    lcd_key = read_LCD_buttons();

    switch (lcd_key)
    {
      case btnRIGHT:
        {
          break;
        }
      case btnLEFT:
        {
          break;
        }
      case btnDOWN:
        {
          if (main_menu_index == 0) {
            main_menu_index = 6;
          } else {
            main_menu_index = main_menu_index - 1;
          }
          updateMain();
          break;
        }
      case btnUP:
        {
          if (main_menu_index == 6) {
            main_menu_index = 0;
          } else {
            main_menu_index = main_menu_index + 1;
          }
          updateMain();
          break;
        }
      case btnSELECT:
        {
          ModeSelect();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}

// ****************************** Mise Ă  jour de l'affichage du menu principal ******************************

void updateMain() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("Select Mode:"));
  display.print(main_menu_index + 1);
  display.println(F("/7"));
  display.print(MainMenuEntries[main_menu_index]);
  display.display();
}

// ****************************** sélection du mode ******************************
void ModeSelect() {
  switch (main_menu_index)
  {
    case 0:
      {
        RunMode();
        break;
      }
    case 1:
      {
        if (Nlaps > 0) {
          RetrDash();
        } else {
          NoData();
        }
        break;
      }
    case 2:
      {
        if (Nlaps > 0) {
          RetrDashAuto();
        } else {
          NoData();
        }
        break;
      }
    case 3:
      {
        SetTops();
        break;
      }
    case 4:
      {
        RetrPC();
        break;
      }
    case 5:
      {
        ChronoManu();
        break;
      }
    case 6:
      {
        EraseEEPROM();
        break;
      }
  }
}

// ****************************** mode RUN ******************************
void RunMode() {

  updateRUN();
  attachInterrupt(digitalPinToInterrupt(SensorPin), myisr, RISING);
  exit_loop = 0;
 

  do {
     Serial.println("DOI state");
  Serial.println(DoI);
    if (DoI){
    chrono();
    DoI = false;}
    
    lcd_key = read_LCD_buttons();  // read the buttons
    
    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnRIGHT:
        {
          chrono();
          break;
        }
      case btnSELECT:
        {
          //detachInterrupt(digitalPinToInterrupt(SensorPin));
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }

    // arrĂȘt du chrono au delĂ  de 10 minutes
    if ((millis() - a1) > StopTime) {
      chrono_stat = 0;
    }
  } while (exit_loop == 0);

}

// ****************************** update affichage RUN ******************************
void updateRUN() {

  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  LapTime = EEPROMReadlong(address_lap(Nlaps, 0));
  PrintTime(LapTime);

  display.print(F("BL: "));
  BestTime = EEPROMReadlong(2);
  PrintTime(BestTime);
}


// ****************************** No data ******************************

void NoData() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("    NO DATA     "));
  display.display();
  delay(1000);
  MainMenu();
}

// ****************************** mode retrieve dash ******************************
void RetrDash() {

  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;


  do {

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnDOWN:
        {
          if (temp_lap > 1) {
            temp_lap--;
          } else {
            temp_lap = Nlaps;
          }
          updateRetrDash();
          break;
        }
      case btnUP:
        {
          if (temp_lap > Nlaps - 1) {
            temp_lap = 1;
          } else {
            temp_lap++;
          }
          updateRetrDash();
          break;
        }
      case btnLEFT:
        {
          inter = 1;
          updateRetrDash();
          break;
        }
      case btnRIGHT:
        {
          inter = 2;
          updateRetrDash();
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** affichage de RetrDash ******************************
void updateRetrDash() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("LP: "));
  display.print(temp_lap);
  address_temp = address_lap(temp_lap, 0);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.setCursor(0, 1);
  display.print(F("P#"));
  display.setCursor(2, 1);
  display.print(inter);
  address_temp = address_lap(temp_lap, inter);
  LapTime = EEPROMReadlong(address_temp);
  PrintTime(LapTime);
  display.display();
}

// ****************************** mode retrieve dash AUTO ******************************
void RetrDashAuto() {
  temp_lap = Nlaps;
  inter = 1;
  updateRetrDash();
  exit_loop = 0;
  a1 = millis();

  do {

    if (millis() - a1 > 1000) {
      if (inter == 1) {
        inter = 2;
        updateRetrDash();
      }
    }

    if (millis() - a1 > 2000) {
      temp_lap = temp_lap - 1;
      if (temp_lap == 0) temp_lap = Nlaps;
      inter = 1;
      updateRetrDash();
      a1 = millis();
    }

    lcd_key = read_LCD_buttons();

    switch (lcd_key)               // depending on which button was pushed, we perform an action
    {
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);

}


// ****************************** mode réglage du nombre de boucles ******************************
void SetTops() {

  updateTops();
  exit_loop = 0;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (Ntops < 3) Ntops++;
          updateTops();
          break;
        }
      case btnLEFT:
        {
          if (Ntops > 1) Ntops--;
          updateTops();
          break;
        }
      case btnSELECT:
        {
          EEPROM.write(0, Ntops);
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}

// ****************************** Mise Ă  jour de l'affichage du nombre de boucles ******************************

void updateTops() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("NBRE OF INTERM.:"));
  display.print(F("     <"));
  display.print(Ntops - 1);
  display.println(F(">"));
  display.display();
}

// ****************************** mode retrieve PC ******************************

void RetrPC() {
  display.clearDisplay();
  exit_loop = 0;
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F(" READY TO SEND "));
  display.display();
  Serial.begin(9600);

  do
  {
    incomingByte = Serial.read();
    // incoming "S"
    if (incomingByte == 83) {
      SendToPC();
    }

    // incoming "E"
    if (incomingByte == 69) {
      EraseEEPROM();
    }

    // incoming "Q"
    if (incomingByte == 81) {
      Serial.end();
      MainMenu();
    }

    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnSELECT:
        {
          Serial.end();
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (exit_loop == 0);
}


// ****************************** envoi des data PC ******************************

void SendToPC() {

  int temp_lap;
  Serial.println("START");

  for (temp_lap = 1; temp_lap < Nlaps + 1 ; temp_lap++) {

    // liste des temps au tour
    address_temp = address_lap(temp_lap, 0);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;


    Serial.print(F("Lap:"));
    Serial.print(temp_lap);
    Serial.print(F(" - "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);


    // intermediate#1
    address_temp = address_lap(temp_lap, 1);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#1: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.print(millisecs);

    // intermediate#2
    address_temp = address_lap(temp_lap, 2);
    Time = EEPROMReadlong(address_temp);
    heures = Time / 3600000;
    minutes = (Time - heures * 3600000) / 60000;
    secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
    millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

    Serial.print(F(" - inter#2: "));
    Serial.print(minutes);
    Serial.print(F(":"));
    if (secondes < 10) {
      Serial.print(F("0"));
      Serial.print(secondes);
    } else {
      Serial.print(secondes);
    }
    Serial.print(F("."));
    Serial.println(millisecs);
  }

  // meilleur temps
  Time = EEPROMReadlong(2);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.println(F("----------"));

  Serial.print(F("Best lap: "));
  Serial.print(NbestLap);
  Serial.print(F(" - "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#1
  Time = EEPROMReadlong(6);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" - inter#1: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.print(millisecs);


  // inter#2
  Time = EEPROMReadlong(10);
  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;

  Serial.print(F(" -inter#2: "));
  Serial.print(minutes);
  Serial.print(F(":"));
  if (secondes < 10) {
    Serial.print(F("0"));
    Serial.print(secondes);
  } else {
    Serial.print(secondes);
  }
  Serial.print(F("."));
  Serial.println(millisecs);
  Serial.println(F("----------"));
  Serial.println(F("END"));

}




// ****************************** chronometre ******************************
void ChronoManu() {

  exit_loop = 0;
  ChronoManu_stat = 0;
  ResetTime = 1;
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("TIME:  "));
  PrintTime(0);
  display.display();
  ChronoManu_count = 0;
  a0 = 0UL;
  a1 = 0UL;
  Time = 0UL;

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          if (ChronoManu_stat == 0) {
            ChronoManu_stat = 1;
            if (ResetTime == 1) {
              a1 = millis();
              a0 = millis();
              ChronoManu_count = 0;
              ResetTime = 0;
            }
          } else {
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.display();
            ChronoManu_stat = 0;
          }
          break;
        }
      case btnLEFT:
        {
          ResetTime = 1;
          a1 = millis();
          a0 = millis();
          display.clearDisplay();
          display.setTextSize(1); // Draw 2X-scale text
          display.setTextColor(WHITE);
          display.setCursor(0, 0);
          display.print(F("TIME:  "));
          PrintTime(0);
          display.display();
          break;
        }
      case btnDOWN:
        {
          if (ChronoManu_stat == 1) {
            ChronoManu_count = ChronoManu_count + 1;
            display.clearDisplay();
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.print(F("TIME:  "));
            PrintTime(Time);
            display.print(F("LAP #"));
            display.print(ChronoManu_count);
            display.print("   ");
            PrintTime(Time1);
            display.display();
            a0 = millis();
          }
          break;
        }
      case btnSELECT:
        {
          exit_loop = 1;
          updateMain();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
    if (ChronoManu_stat == 1) {

      display.setTextSize(1); // Draw 2X-scale text
      display.setTextColor(WHITE);
      display.setCursor(0, 0);
      display.fillRect(0, 0, 127, 6, BLACK);
      display.print(F("TIME:  "));
      Time = millis() - a1;
      Time1 = millis() - a0;
      PrintTime(Time);
      display.display();
    } else {
      a1 = millis() - Time;
    }
  } while (exit_loop == 0);
}


// ****************************** mode erase EEPROM ******************************
void EraseEEPROM() {
  display.clearDisplay();
  display.setTextSize(1); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(F("  ERASE DATA?   "));
  display.print(F(" NO<--   -->YES "));
  display.display();

  do {
    lcd_key = read_LCD_buttons();
    switch (lcd_key)
    {
      case btnRIGHT:
        {
          for (Nlaps = 0; Nlaps < NLapsMax; Nlaps++) {
            address = address_lap(Nlaps, 0);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 1);
            EEPROMWritelong(address, 0UL);
            address = address_lap(Nlaps, 2);
            EEPROMWritelong(address, 0UL);
            display.setTextSize(1); // Draw 2X-scale text
            display.setTextColor(WHITE);
            display.setCursor(0, 0);
            display.println(F("   ERASING...   "));
            display.print(F("                "));
            display.print(Nlaps);
            display.display();
          }

          EEPROM.write(0, 1);
          EEPROM.write(1, 0);
          EEPROMWritelong(2, 3599999UL);
          EEPROMWritelong(6, 3599999UL);
          EEPROMWritelong(10, 3599999UL);
          EEPROMWritelong(15, 0);
          setup();
          break;
        }
      case btnLEFT:
        {
          MainMenu();
          break;
        }
      case btnNONE:
        {
          break;
        }
    }
  } while (1);
}




// ****************************** Affiche un chrono à l'écran ******************************

void PrintTime(unsigned long Time)//, int y, int x)
{

  heures = Time / 3600000;
  minutes = (Time - heures * 3600000) / 60000;
  secondes = (Time - heures * 3600000 - 60000 * minutes) / 1000;
  millisecs = Time - heures * 3600000 - 60000 * minutes - secondes * 1000;
  display.print(minutes);
  display.print(F("'"));
  display.print(secondes);
  display.print(F("."));
  display.println(millisecs);
  display.display();
}



// ****************************** controle du chrono ******************************

void chrono() {

  Serial.println(millis() - a0);
  if (millis() - a0 > debounceTime) {
    if (chrono_stat == 1) {

      if (count > Ntops - 2) {
        LapTime = millis() - a1;
        a1 = millis();

        if (LapTime < BestTime) {
          BestTime = LapTime;
          NbestLap = Nlaps + 1;
          EEPROMWritelong(2, BestTime);
          EEPROMWritelong(6, interm[0]);
          EEPROMWritelong(10, interm[1]);
          EEPROM.write(15, NbestLap);
        }

        Nlaps = Nlaps + 1;
        EEPROM.write(1, Nlaps);
        address = address_lap(Nlaps, 0);
        EEPROMWritelong(address, LapTime);
        address = address_lap(Nlaps, 1);
        EEPROMWritelong(address, interm[0]);
        address = address_lap(Nlaps, 2);
        EEPROMWritelong(address, interm[1]);
        updateRUN();

        count = 0;
        if (Nlaps > NLapsMax) Nlaps = 0;

      }
      else {
        interm[count] = millis() - a1;
        count = count + 1;
      }

    } else {
      a1 = millis();
      chrono_stat = 1;
      count = 1;
    }
  }
  a0 = millis();
}


// ****************************** routine d'écriture d'un long dans l'EEPROM ******************************
void EEPROMWritelong(int address, long value)
{
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}


// ****************************** routine de lecture d'un long dans l'EEPROM ******************************
long EEPROMReadlong(long address)
{
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

void myisr()
{
  if ( DoI == false )
  {
    DoI = true;
  }
}

I see another issue: MainMenu calls ModeSelect, which calls NoData, which calls MainMenu, which calls ModeSelect, which calls NoData, which calls MainMenu.... I'm sure you get the picture. Every time you call a function, the system needs to push a return address to a stack (when a function returns, the return address is "popped" from the stack). If you have something that calls itself, either directly or indirectly, the stack can fill up and that can cause a crash or some other problem like data corruption. It looks like NoData should just return rather than call MainMenu.

Yes.
As i said, i try to adapt an existing project.
I struggled to understand the spirit of the code.
And the creator built it as a navigation menu, going in a mode and regarding the button presed on lcd screen shield, you launch the timer or go back to main menu.
No data, is a function that display a message if no time data is write in the eeprom.
For me calling mainmenu is a way to return.
But I don't think a correctly understand what you suggest for return

There is some function i am not using in the original project and my next move is to put the project into a diet.
Just keeping magnetic triggered lap timer, sending to pc, inter setup, and erasing eeprom data.

Thank you allnfor the advise and comments

Commonly accepted practice is attachInterrupt() once in setup() and no detach.

Ok, thanks for the tip

Hi everybody,

everything is working good.
Maybe it not realy clean coded but it is working :slight_smile:

thank you very much

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