Deux voies de chronométrage

Bonjour à tous, après le Test de Rapidité, je suis entrain de réaliser un système de chronométrage sur deux voies d'escalade. Bien entendu, les 2 voies sont indépendantes et chronométrées séparément. Le départ est donné à partir d'un tapis sensible On/Off et l'arrêt par un bouton poussoir (comme le "test de rapidité"). L'affichage des temps se fait par 2 matrices WS2812 64x8. Un tableau déporté affiche les 2 temps au millième sur un lcd 20x4 avec la commande de Remise à zéro des compteurs pour l'arbitre.
J'en suis arrivé à ce que le lcd et un afficheur fonctionnent bien. Sauf que le temps (par millis) compte environ 40 sec dans une minute au chronomètre de mon téléphone; et qu'il n'y a qu'un afficheur qui fonctionne.
Auriez-vous une astuce pour afficher les 2 compteurs sur mes matrices et remédier au décalage de comptage ?
Voici mon code :


```cpp
// Chronometre_simple-start/Stop/Reset

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define DATA_PIN1 9
#define DATA_PIN2 8
Adafruit_NeoMatrix matrix1 = Adafruit_NeoMatrix(56, 8, DATA_PIN1, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoMatrix Led2 = Adafruit_NeoMatrix(56, 8, DATA_PIN2, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);

const uint16_t colors1[] = { matrix1.Color(255, 0, 0), matrix1.Color(0, 255, 0), matrix1.Color(0, 0, 255), matrix1.Color(255, 255, 255) };
const uint16_t colors2[] = { Led2.Color(255, 0, 0), Led2.Color(0, 255, 0), Led2.Color(0, 0, 255), Led2.Color(255, 255, 255) };

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
int BtStartStop1 = 4;
int BtStartStop2 = 3;
int BtReset = 2;
bool EtatBtStartStop1;
bool EtatBtStartStop2;
bool EtatBtReset;

int EtatBoutonAppuyer1;
int EtatChronoOnOFF1;
int TempsEcoule1;
int Milliseconde1;
int Seconde1;
int Minute1;
int Heure1;
unsigned long currentTime1 = 0;
unsigned long previousTime1 = 0;

int EtatBoutonAppuyer2;
int EtatChronoOnOFF2;
int TempsEcoule2;
int Milliseconde2;
int Seconde2;
int Minute2;
int Heure2;
unsigned long currentTime2 = 0;
unsigned long previousTime2 = 0;


void setup() {
  pinMode(BtStartStop1, INPUT_PULLUP);
  pinMode(BtStartStop2, INPUT_PULLUP);
  pinMode(BtReset, INPUT_PULLUP);
  pinMode(DATA_PIN1, OUTPUT);
  pinMode(DATA_PIN2, OUTPUT);
  lcd.begin(20, 4);
  lcd.setCursor(0, 0);
  lcd.print("Chrono au 1/1000 sec");
  lcd.setCursor(0, 1);
  lcd.print("V");
  lcd.setCursor(0, 2);
  lcd.print("1");
  lcd.setCursor(0, 3);
  lcd.print("2");
  matrix1.begin();
  matrix1.setBrightness(10);
  matrix1.setTextWrap(true);
  Led2.begin();
  Led2.setBrightness(10);
  Led2.setTextWrap(true);
}
int x1 = matrix1.width();
int x2 = Led2.width();
int pass = 1;

void loop() {
  lcd.backlight();
  matrix1.fillScreen(0);
  Led2.fillScreen(0);
  EtatBtStartStop1 = digitalRead(BtStartStop1);
  EtatBtStartStop2 = digitalRead(BtStartStop2);
  EtatBtReset = digitalRead(BtReset);

  if (EtatBtStartStop1 == LOW && EtatBoutonAppuyer1 == 0) {
    EtatBoutonAppuyer1 = 1;
    EtatChronoOnOFF1 = !EtatChronoOnOFF1;
  }
  if (EtatBtReset == LOW && EtatChronoOnOFF1 == 0 && EtatBoutonAppuyer1 == 0) {
    EtatBoutonAppuyer1 = 1;
    Milliseconde1 = 0;
    Seconde1 = 0;
    Minute1 = 0;
    Heure1 = 0;
  }
  if (EtatBtStartStop1 == HIGH && EtatBtReset == HIGH) {
    EtatBoutonAppuyer1 = 0;
  }

  currentTime1 = millis();
  TempsEcoule1 = currentTime1 - previousTime1;
  previousTime1 = millis();
  if (EtatChronoOnOFF1 == 1) {
    Milliseconde1 = Milliseconde1 + TempsEcoule1;
    if (Milliseconde1 > 999) {
      Milliseconde1 = Milliseconde1 - 1000;
      Seconde1++;
    }
    if (Seconde1 > 59) {
      Seconde1 = 0;
      Minute1++;
    }
    if (Minute1 > 59) {
      Minute1 = 0;
      Heure1++;
    }
  }

  if (EtatBtStartStop2 == LOW && EtatBoutonAppuyer2 == 0) {
    EtatBoutonAppuyer2 = 1;
    EtatChronoOnOFF2 = !EtatChronoOnOFF2;
  }
  if (EtatBtReset == LOW && EtatChronoOnOFF2 == 0 && EtatBoutonAppuyer2 == 0) {
    EtatBoutonAppuyer2 = 1;
    Milliseconde2 = 0;
    Seconde2 = 0;
    Minute2 = 0;
    Heure2 = 0;
  }
  if (EtatBtStartStop2 == HIGH && EtatBtReset == HIGH) {
    EtatBoutonAppuyer2 = 0;
  }

  currentTime2 = millis();
  TempsEcoule2 = currentTime2 - previousTime2;
  previousTime2 = millis();
  if (EtatChronoOnOFF2 == 1) {
    Milliseconde2 = Milliseconde2 + TempsEcoule2;
    if (Milliseconde2 > 999) {
      Milliseconde2 = Milliseconde2 - 1000;
      Seconde2++;
    }
    if (Seconde2 > 59) {
      Seconde2 = 0;
      Minute2++;
    }
    if (Minute2 > 59) {
      Minute2 = 0;
      Heure2++;
    }
  }

  lcd.setCursor(11, 2);
  lcd.print(".");
  if (Milliseconde1 > 99) {
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  } else if (Milliseconde1 > 9 && Milliseconde1 < 100) {
    lcd.setCursor(16, 2);
    lcd.print("0");
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  } else if (Milliseconde1 > 0 && Milliseconde1 < 10) {
    lcd.setCursor(16, 2);
    lcd.print("00");
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  }
  lcd.setCursor(11, 3);
  lcd.print(".");
  if (Milliseconde2 > 99) {
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else if (Milliseconde2 > 9 && Milliseconde2 < 100) {
    lcd.setCursor(16, 3);
    lcd.print("0");
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else if (Milliseconde2 > 0 && Milliseconde2 < 10) {
    lcd.setCursor(16, 3);
    lcd.print("00");
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else {
    lcd.setCursor(15, 2);
    lcd.print(".000");
    lcd.setCursor(15, 3);
    lcd.print(".000");
    lcd.setCursor(14, 2);
    lcd.print("..");
    lcd.setCursor(14, 3);
    lcd.print("..");
  }
  if (Seconde1 < 10) {
    lcd.setCursor(12, 2);
    lcd.print("0");
    lcd.setCursor(13, 2);
    lcd.print(Seconde1);
  } else {
    lcd.setCursor(12, 2);
    lcd.print(Seconde1);
  }
  if (Seconde2 < 10) {
    lcd.setCursor(12, 3);
    lcd.print("0");
    lcd.setCursor(13, 3);
    lcd.print(Seconde2);
  } else {
    lcd.setCursor(12, 3);
    lcd.print(Seconde2);
  }
  lcd.setCursor(10, 2);
  lcd.print("..");
  lcd.setCursor(10, 3);
  lcd.print("..");
  if (Minute1 < 10) {
    lcd.setCursor(8, 2);
    lcd.print("0");
    lcd.setCursor(9, 2);
    lcd.print(Minute1);
  }
  if (Minute2 < 10) {
    lcd.setCursor(8, 3);
    lcd.print("0");
    lcd.setCursor(9, 3);
    lcd.print(Minute2);
  } else {
    lcd.setCursor(8, 2);
    lcd.print(Minute1);
    lcd.setCursor(8, 3);
    lcd.print(Minute2);
  }
  lcd.setCursor(6, 2);
  lcd.print("..");
  lcd.setCursor(6, 3);
  lcd.print("..");
  if (Heure1 < 10) {
    lcd.setCursor(4, 2);
    lcd.print("0");
    lcd.setCursor(5, 2);
    lcd.print(Heure1);
  }
  if (Heure2 < 10) {
    lcd.setCursor(4, 3);
    lcd.print("0");
    lcd.setCursor(5, 3);
    lcd.print(Heure2);
  } else {
    lcd.setCursor(5, 2);
    lcd.print(Heure1);
    lcd.setCursor(5, 3);
    lcd.print(Heure2);
  }

  matrix1.setCursor(40, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Milliseconde1);
  matrix1.setCursor(35, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.setCursor(25, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Seconde1);
  matrix1.setCursor(20, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.setCursor(10, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Minute1);
  matrix1.setCursor(5, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.show();

  Led2.setCursor(40, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Milliseconde2);
  Led2.setCursor(35, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.setCursor(25, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Seconde2);
  Led2.setCursor(20, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.setCursor(10, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Minute2);
  Led2.setCursor(5, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.show();
}

hello
j'ai commencé par virer tout ce que je n'ai pas (dans ton code).il me reste le comptage .
avec un Serial.print, je visualise les variables et le comptage est correct.
mais comme j'ai viré toute la fin de ton prg, la loop s'effectue rapidement
alors, pour simuler toutes les lignes de code que j'ai supprimées, j'ai rajouté un delai de 500 ms.
et là, je constate queffectivement le chrono du PC affiche environ 40 alors que ton compteur affiche 1mn
conclusion; comme tu ne pourras pas supprimer le code qu concerne les affichages matrices et lcd, il faut que tu revoies le comptage.
mon/ton programme d'essai:

#include <Adafruit_GFX.h>
//#include <Adafruit_NeoMatrix.h>
//#include <Adafruit_NeoPixel.h>
#define DATA_PIN1 9
#define DATA_PIN2 8
//Adafruit_NeoMatrix matrix1 = Adafruit_NeoMatrix(56, 8, DATA_PIN1, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);
//Adafruit_NeoMatrix Led2 = Adafruit_NeoMatrix(56, 8, DATA_PIN2, NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);

//const uint16_t colors1[] = { matrix1.Color(255, 0, 0), matrix1.Color(0, 255, 0), matrix1.Color(0, 0, 255), matrix1.Color(255, 255, 255) };
//const uint16_t colors2[] = { Led2.Color(255, 0, 0), Led2.Color(0, 255, 0), Led2.Color(0, 0, 255), Led2.Color(255, 255, 255) };

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
int BtStartStop1 = 4;
int BtStartStop2 = 3;
int BtReset = 2;
bool EtatBtStartStop1;
bool EtatBtStartStop2;
bool EtatBtReset;

int EtatBoutonAppuyer1;
int EtatChronoOnOFF1;
int TempsEcoule1;
int Milliseconde1;
int Seconde1;
int Minute1;
int Heure1;
unsigned long currentTime1 = 0;
unsigned long previousTime1 = 0;

int EtatBoutonAppuyer2;
int EtatChronoOnOFF2;
int TempsEcoule2;
int Milliseconde2;
int Seconde2;
int Minute2;
int Heure2;
unsigned long currentTime2 = 0;
unsigned long previousTime2 = 0;


void setup() {
  Serial.begin(115200);
  pinMode(BtStartStop1, INPUT_PULLUP);
  pinMode(BtStartStop2, INPUT_PULLUP);
  pinMode(BtReset, INPUT_PULLUP);
  pinMode(DATA_PIN1, OUTPUT);
  pinMode(DATA_PIN2, OUTPUT);
  /*
  lcd.init();
  lcd.setCursor(0, 0);
  lcd.print("Chrono au 1/1000 sec");
  lcd.setCursor(0, 1);
  lcd.print("V");
  lcd.setCursor(0, 2);
  lcd.print("1");
  lcd.setCursor(0, 3);
  lcd.print("2");
  */
  //matrix1.begin();
  //matrix1.setBrightness(10);
  //matrix1.setTextWrap(true);
 //Led2.begin();
 // Led2.setBrightness(10);
 // Led2.setTextWrap(true);
 Serial.println("fin setup");
}
//int x1 = matrix1.width();
//int x2 = Led2.width();
int pass = 1;

void loop() {
  //lcd.backlight();
  //matrix1.fillScreen(0);
 // Led2.fillScreen(0);
  EtatBtStartStop1 = digitalRead(BtStartStop1);//Serial.print("EtatBtStartStop1 ");Serial.println(EtatBtStartStop1);
  EtatBtStartStop2 = digitalRead(BtStartStop2);//Serial.print("fin setup");Serial.println(TempsEcoule1);
  EtatBtReset = digitalRead(BtReset);          //Serial.print("EtatBtReset");Serial.println(EtatBtReset);
//Serial.print("EtatBtStartStop1 ");Serial.println(EtatBtStartStop1);
//Serial.print("EtatBoutonAppuyer1 ");Serial.println( EtatBoutonAppuyer1);
  if (EtatBtStartStop1 == LOW && EtatBoutonAppuyer1 == 0) {
    EtatBoutonAppuyer1 = 1;
    EtatChronoOnOFF1 = !EtatChronoOnOFF1;
  }
  if (EtatBtReset == LOW && EtatChronoOnOFF1 == 0 && EtatBoutonAppuyer1 == 0) {
    EtatBoutonAppuyer1 = 1;
    Milliseconde1 = 0;
    Seconde1 = 0;
    Minute1 = 0;
    Heure1 = 0;
  }
  if (EtatBtStartStop1 == HIGH && EtatBtReset == HIGH) {
    EtatBoutonAppuyer1 = 0;
  }

  currentTime1 = millis();
  TempsEcoule1 = currentTime1 - previousTime1;
 // Serial.println(TempsEcoule1);
  previousTime1 = millis();
  if (EtatChronoOnOFF1 == 1) {
    Milliseconde1 = Milliseconde1 + TempsEcoule1;
   // Serial.print("Milliseconde1 ");Serial.print(Milliseconde1);Serial.print("  ");Serial.print(Seconde1);Serial.print("  ");Serial.print(Minute1);Serial.print("  ");Serial.println(Heure1);
    if (Milliseconde1 > 999) {Serial.print("Milliseconde1 ");Serial.print(Milliseconde1);Serial.print("  ");Serial.print(Seconde1);Serial.print("  ");Serial.print(Minute1);Serial.print("  ");Serial.println(Heure1);
      Milliseconde1 = Milliseconde1 - 1000;
      Seconde1++;
    }
    if (Seconde1 > 59) {
      Seconde1 = 0;
      Minute1++;
    }
    if (Minute1 > 59) {
      Minute1 = 0;
      Heure1++;
    }
  }

  if (EtatBtStartStop2 == LOW && EtatBoutonAppuyer2 == 0) {
    EtatBoutonAppuyer2 = 1;
    EtatChronoOnOFF2 = !EtatChronoOnOFF2;
  }
  if (EtatBtReset == LOW && EtatChronoOnOFF2 == 0 && EtatBoutonAppuyer2 == 0) {
    EtatBoutonAppuyer2 = 1;
    Milliseconde2 = 0;
    Seconde2 = 0;
    Minute2 = 0;
    Heure2 = 0;
  }
  if (EtatBtStartStop2 == HIGH && EtatBtReset == HIGH) {
    EtatBoutonAppuyer2 = 0;
  }

  currentTime2 = millis();
  TempsEcoule2 = currentTime2 - previousTime2;
  previousTime2 = millis();
  if (EtatChronoOnOFF2 == 1) {
    Milliseconde2 = Milliseconde2 + TempsEcoule2;
    if (Milliseconde2 > 999) {
      Milliseconde2 = Milliseconde2 - 1000;
      Seconde2++;
    }
    if (Seconde2 > 59) {
      Seconde2 = 0;
      Minute2++;
    }
    if (Minute2 > 59) {
      Minute2 = 0;
      Heure2++;
    }
  }
Serial.println("delai");
  delay(500);
/*
  lcd.setCursor(11, 2);
  lcd.print(".");
  if (Milliseconde1 > 99) {
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  } else if (Milliseconde1 > 9 && Milliseconde1 < 100) {
    lcd.setCursor(16, 2);
    lcd.print("0");
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  } else if (Milliseconde1 > 0 && Milliseconde1 < 10) {
    lcd.setCursor(16, 2);
    lcd.print("00");
    lcd.setCursor(16, 2);
    lcd.print(Milliseconde1);
  }
  lcd.setCursor(11, 3);
  lcd.print(".");
  if (Milliseconde2 > 99) {
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else if (Milliseconde2 > 9 && Milliseconde2 < 100) {
    lcd.setCursor(16, 3);
    lcd.print("0");
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else if (Milliseconde2 > 0 && Milliseconde2 < 10) {
    lcd.setCursor(16, 3);
    lcd.print("00");
    lcd.setCursor(16, 3);
    lcd.print(Milliseconde2);
  } else {
    lcd.setCursor(15, 2);
    lcd.print(".000");
    lcd.setCursor(15, 3);
    lcd.print(".000");
    lcd.setCursor(14, 2);
    lcd.print("..");
    lcd.setCursor(14, 3);
    lcd.print("..");
  }
  if (Seconde1 < 10) {
    lcd.setCursor(12, 2);
    lcd.print("0");
    lcd.setCursor(13, 2);
    lcd.print(Seconde1);
  } else {
    lcd.setCursor(12, 2);
    lcd.print(Seconde1);
  }
  if (Seconde2 < 10) {
    lcd.setCursor(12, 3);
    lcd.print("0");
    lcd.setCursor(13, 3);
    lcd.print(Seconde2);
  } else {
    lcd.setCursor(12, 3);
    lcd.print(Seconde2);
  }
  lcd.setCursor(10, 2);
  lcd.print("..");
  lcd.setCursor(10, 3);
  lcd.print("..");
  if (Minute1 < 10) {
    lcd.setCursor(8, 2);
    lcd.print("0");
    lcd.setCursor(9, 2);
    lcd.print(Minute1);
  }
  if (Minute2 < 10) {
    lcd.setCursor(8, 3);
    lcd.print("0");
    lcd.setCursor(9, 3);
    lcd.print(Minute2);
  } else {
    lcd.setCursor(8, 2);
    lcd.print(Minute1);
    lcd.setCursor(8, 3);
    lcd.print(Minute2);
  }
  lcd.setCursor(6, 2);
  lcd.print("..");
  lcd.setCursor(6, 3);
  lcd.print("..");
  if (Heure1 < 10) {
    lcd.setCursor(4, 2);
    lcd.print("0");
    lcd.setCursor(5, 2);
    lcd.print(Heure1);
  }
  if (Heure2 < 10) {
    lcd.setCursor(4, 3);
    lcd.print("0");
    lcd.setCursor(5, 3);
    lcd.print(Heure2);
  } else {
    lcd.setCursor(5, 2);
    lcd.print(Heure1);
    lcd.setCursor(5, 3);
    lcd.print(Heure2);
  }

  matrix1.setCursor(40, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Milliseconde1);
  matrix1.setCursor(35, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.setCursor(25, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Seconde1);
  matrix1.setCursor(20, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.setCursor(10, 1);
  matrix1.setTextColor(colors1[1]);
  matrix1.print(Minute1);
  matrix1.setCursor(5, 0);
  matrix1.setTextColor(colors1[0]);
  matrix1.print(".");
  matrix1.show();

  Led2.setCursor(40, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Milliseconde2);
  Led2.setCursor(35, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.setCursor(25, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Seconde2);
  Led2.setCursor(20, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.setCursor(10, 1);
  Led2.setTextColor(colors2[1]);
  Led2.print(Minute2);
  Led2.setCursor(5, 0);
  Led2.setTextColor(colors2[0]);
  Led2.print(".");
  Led2.show();
  */
}

pour démarrer, un BP sur GND et D4
tu commenteras les lignes 151 et 152 pour voir ton prg travailler correctement.
tu ne les commentes pas et tu vois ton prog disfonctionner.

Bonjour dfgh,
J'ai commencé par changer de carte pour une Mega 2560 (mémoire disponible plus importante, ce qui fait fonctionner les 3 affichages normalement).
J'ai essayé les suggestions que vous me proposez pour constater que, sans supprimer les trois affichages, lcd + les 2 matrices, le compteur compte bien 40 secondes pour 1 minute chronométrée. Pour se rapprocher de 60 sec par minute, il faut un délai de environ 460ms. J'en déduit que la base de temps qui gère "millis" n'est pas de 1ms (1000 Hz) mais d'un multiple de 1024 Hz, ce qui fausse, forcement, le temps compté.
Est-il envisageable d'adjoindre un module DS3231pour récupérer la base de temps 32kHz ou celle à 1 sec pour synchroniser mon comptage. Qu'en pensez-vous ?

hello
une horloge n'est pas indispensable,
combien de temps dure une escalade?
en gérant correctement le temps, il n'y a pas de raison d'avoir de telles erreurs.
ou en es tu dans ton programme?
tu parles de 3 affichages? j'ai en mémoire le lcd, les matrices de leds et quel est le 3ème?
je viens de faire la partie chronométrage, controle effectué sur 4 heures pour les deux chronos ensemble,
aucun décalage.

bonjour,
une escalade en vitesse dure moins de 1:00 minute
une escalade en difficulté dure maximum 6:00 minutes
une escalade en blocs on mesure le temps mis pour arriver au sommet

pour le programme, amélioration du fait de la carte Mega;
le temps mesuré de 1000 millisecondes ne correspond pas à 1 seconde; ce qui fait que en utilisant un chronomètre d'athlétisme, il y a, environ, 50 sec comptées pour 60 sec chronométrées.
Mais, au demeurant, le temps peut ne pas être juste, du moment que la base de temps des 2 chronos est la même.

les 3 affichages sont :
1 : le lcd qui regroupe les 2 compteurs ("TempsEcoule1" et "TempsEcoule2");
2 : matrice 64x8 affichage chrono voie 1 (déclenchement indépendant de l'autre voie);
3 : matrice 64x8 affichage chrono voie 2 (déclenchement indépendant de l'autre voie).

Mon problème, maintenant, est la gestion du déclenchement du "Start" par le tapis de sol. J'ai, à disposition sur le tapis, les 2 états NO et NC au repos.
Tant qu'il n'y a personne : ça va (NO connecté en "INPUT_PULLUP").
Le concurrent se présente sur le tapis : le chrono démarre, alors qu'il faudrait qu'il démarre au lâcher du pied. Je n'y arrive pas.

Bonjour castres

La bibliothèque button.h et l'événement .released() te faciliteront la tâche.

Cordialement
jpbbricole

Bonjour jpbbricole, merci pour le tuyau, je regarde ça de suite.

Donc, pas utile d'afficher les heures

non

Bonjour jpbbricole, après plusieurs jours de recherche et d'essais, je n'arrive pas à concrétiser, après que le concurrent soit monté sur le tapis (ce qui le fait changer d'etat (0 vers 1)), le fait de démarrer le chrono au lâcher du pied du tapis sur front descendant (1 vers 0) pour l'arrêter sur front montant dans le style télérupteur avec 2 boutons.
J'ai bien essaye la bibliothèque 'button.h' et l'évènement 'released()' sans véritable succès. j'ai beaucoup de mal à saisir le processus intellectuellement.
Auriez-vous un ou plusieurs prémices de code à me proposer, si ce n'est pas trop demandé ?
Cordialement

Chrono double voies _Synoptique Start-Stop-Reset.pdf (42,0 Ko)

Bonjour castres

Pour résumer,
le concurrent monte sur le tapis = prêt au départ (contact tapis = 1)
le concurrent s'élance = en course (contact tapis de 1 à 0) démarrage chrono
le concurrent arrive (contact bouton d'arrivée de 0 à 1) arrêt chrono.
Juste?

On a 2 boutons, celui du tapis et celui d'arrivée.
Celui d'arrivée est actif à LOW et celui d'arrivée à HIGH, pourquoi?

Le mieux est de mettre tout tes contacts d'un côté à GND, mode PULLUP, ainsi ils sont tous actifs à LOW. Par défaut, button.h fonctionne ainsi.

Que penses tu de tout ça?

A+
Cordialement
jpbbricole

Pas tout a fait.
Le départ = contact au repos à 0, le joueur monte sur le tapis (contact à 1), au lâcher, 'départ chrono' à 0 sur front descendant.
l'arrivée = contact au repos à 1, le concurrent appuie = 0 d'où 'arrêt chrono' sur front descendant.
Le tapis, de construction, a un seul contact NO au repos.
Mon chronographe :
Chrono double voies _Synoptique Start-Stop-Reset.pdf (42,0 Ko)

C'est ce que j'essaye de codifier, mais je n'y arrive pas, ou le comptage démarre à la montée sur le tapis, ou le chrono ne démarre pas, ou il ne s'arrête pas.
Cordialement
CASTRES

Bonjour castres

Ce qui veux dire que tu travailles en PULLDOWN

et que tu as mis une résistance de PULLDOWN?

C'est un NF ou on est en PULLUP?

Mets ton programme en ligne, as-tu un schéma de ton installation?

A+
Cordialement
jpbbricole

Chrono double voies_Schéma.pdf (86,3 Ko)
Chrono double voies _Synoptique Start-Stop-Reset.pdf (44,7 Ko)

Je n'ai pas terminé le câblage de tout ça; ce sera terminé dans environ une semaine. Pour l'instant, je fais des essais avec une MEGA 2560, quelques leds 'feux tricolores' et quatre boutons miniatures NO.
Cordialement
Castres

Bonjour castres

Pourquoi sur ton schéma BtStart1 (tapis) est câblé en mode PULLUP, c'est à dire, quand il est pressé il donne un GND ou LOW alors que c'est noté PULLDOWN (il n'y a d'ailleurs pas de résistance de PULLDOWS sur ton schéma). Pour fonctionner ainsi, il faudrait câbler le tapis au +5V.


Et ton diagramme ne correspond pas à ton câblage.

Le mieux, pour faciliter le programme est de tout mettre en mode PULLUP comme sur ton schéma. Il suffit d'inverser la courbe BtStart1.

Je te fais un exemple dans ce sens.

Cordialement
jpbbricole

Bonsoir castres

Je t'ai fait un exemple avec la bibliothèque Button.h.

Les 2 boutons, soit le tapis et le bouton d'arrivée sont NO et connectés d'un côté à GND et l'autre à la pin de l'Arduino (PULL_UP).
Les pin respectives sont déclarées ici:

const int escTapisPin = 3;     // Contact du tapis de départ
const int escArriveePin = 11;     // Contact bouton arrivée

A toi de mettre ton brochage.

Le déroulement et la gestion des boutons est contrôlé par une liste d'états:

enum etats {etatInitial, etatAuDepart, etatParti, etatTermine}; 

Pendant le parcours, le temps est affiché toutes les escTempsDisplayTempo millisecondes.
Pour le reste je te laisses découvrir.

Si cette "mécanique" est bonne, on pourra toujours multiplier le tout par 2 pour 2 parcours.

Il y a des indications quand au déroulement du programme dans la console de l'IDE à 115200.

Le programe:

/*
    Name:       ARDFR_DeuxVoiesDeChronometrage.ino
    Created:	26.06.2023
    Author:     jpbbricole / castres

	https://forum.arduino.cc/t/deux-voies-de-chronometrage/1137892
*/
#include <Button.h>

enum etats {etatInitial, etatAuDepart, etatParti, etatTermine}; 

//------------------------------------- Escalade (esc)
int escEtat = etatInitial;

unsigned long escChrono = 0;     // Chronométrage escalade
float escTemps = 0.0;     // Chronométrage temps en secondes

unsigned long escTempsDisplayTempo = 500;     // Affichage temps toutes les n millisecondes
unsigned long escTempsDisplayMillis = 0;     // Affichage temps, chrono

const int escTapisPin = 3;     // Contact du tapis de départ
const int escArriveePin = 11;     // Contact bouton arrivée

Button escTapis(escTapisPin);
Button escArrivee(escArriveePin);

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

	pinMode(escTapisPin, INPUT_PULLUP);
	pinMode(escArriveePin, INPUT_PULLUP);

}

void loop()
{
	//--------------------------------- Entrée sur tapis
	if (escTapis.pressed() && escEtat == etatInitial)
	{
		Serial.println("Tapis entree");
		
		escEtat = etatAuDepart;
	}

	//--------------------------------- Quitter sur tapis
	if (escTapis.released() && escEtat == etatAuDepart)
	{
		Serial.println("Tapis quitter");
		Serial.println("\tDemarrage chrono");

		escEtat = etatParti;
		escChrono = millis();
	}

	//--------------------------------- Arrivée
	if (escArrivee.pressed() && escEtat == etatParti)
	{
		Serial.println("Arrivee");
		Serial.println("\tArret chrono");

		escTemps = escTempsCalcul();
		Serial.println("Temps d'escalade : " + String(escTemps) + " sec.");

		escEtat = etatInitial;
	}

	//--------------------------------- Affichage du chrono
	if (escEtat == etatParti)     // Si escalade en cours
	{
		if (millis() - escTempsDisplayMillis >= escTempsDisplayTempo)
		{
			Serial.println("Chrono = " + String(escTempsCalcul()) + " sec.");
			escTempsDisplayMillis = millis();
		}
	}
}

float escTempsCalcul()
{
	return ((float)millis() - (float)escChrono) / 1000.0;     // Calcul du temps
}

A+
Cordialement
jpbbricole

Bonjour jpbbricole, du haut de mes 71 ans et de mes insomnies, je me suis précipité ce matin sur votre exemple. une fois fait les corrections de broches pour mon montage, rien ne fonctionnait. C'est bien de ma faute, je n'utilisais pas la bonne librairie (Cfg : ArduinoGetStarted). Une fois chargé la bonne (Cfg : Michael Adams), tout rentre dans l'ordre avec les fonctions voulues. Merci beaucoup. Il ne reste plus qu'à intégrer et adapter cet exemple dans mon code. Encore une fois, merci de votre bienveillante collaboration.
Le montage en question est prévu pour équiper le club d'escalade que mon fils a monté avec quelques copains depuis quelques années (2017). Le mur municipal est dans un gymnase, haut de 9 mètres avec une trentaines de voies. Je vous tiendrais au courant de l'évolution du projet.
Cordialement
Castres

Bonjour castres

C'est avec grand plaisir, du haut de mes 75 ans, que je te souhaite bonne continuation :wink:

Cordialement
jpbbricole

Rebonjour jpbbricole, le code finalisé :slight_smile:


#include <Button.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define DATA_PIN1 10
#define DATA_PIN2 8
Adafruit_NeoMatrix matrix1 = Adafruit_NeoMatrix(64, 8, DATA_PIN1, NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoMatrix Led2 = Adafruit_NeoMatrix(64, 8, DATA_PIN2, NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);

const uint16_t colors1[] = { matrix1.Color(255, 0, 0), matrix1.Color(0, 255, 0), matrix1.Color(0, 0, 255), matrix1.Color(255, 255, 255) };
const uint16_t colors2[] = { Led2.Color(255, 0, 0), Led2.Color(0, 255, 0), Led2.Color(0, 0, 255), Led2.Color(255, 255, 255) };

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

enum etats1 { etatInitial1, etatAuDepart1, etatParti1, etatTermine1 };
enum etats2 { etatInitial2, etatAuDepart2, etatParti2, etatTermine2 };

//------------------------------------- Escalade (esc)
int escEtat1 = etatInitial1;
int escEtat2 = etatInitial2;

unsigned long escChrono1 = 0;  // Chronométrage escalade 1
unsigned long escChrono2 = 0;  // Chronométrage escalade 2
float escTemps1 = 0.000;         // Chronométrage temps en secondes 1
float escTemps2 = 0.000;         // Chronométrage temps en secondes 2

unsigned long escTempsDisplayTempo1 = 50;  // Affichage temps toutes les n millisecondes1
unsigned long escTempsDisplayMillis1 = 0;   // Affichage temps, chrono1
unsigned long escTempsDisplayTempo2 = 50;  // Affichage temps toutes les n millisecondes2
unsigned long escTempsDisplayMillis2 = 0;   // Affichage temps, chrono2

const int escTapisPin1 = 2;    // Contact du tapis de départ
const int escArriveePin1 = 3;  // Contact bouton arrivée
const int escTapisPin2 = 6;    // Contact du tapis de départ
const int escArriveePin2 = 7;  // Contact bouton arrivée

Button escTapis1(escTapisPin1);
Button escTapis2(escTapisPin2);
Button escArrivee1(escArriveePin1);
Button escArrivee2(escArriveePin2);

void setup() 
{
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  lcd.begin(20, 4);
  lcd.init();
  lcd.setCursor(0, 0);
  lcd.print("Chrono au 1/100 sec");
  lcd.setCursor(0, 1);
  lcd.print("V");
  lcd.setCursor(0, 2);
  lcd.print("1");
  lcd.setCursor(0, 3);
  lcd.print("2");
  matrix1.begin();
  matrix1.setBrightness(10);
  matrix1.setTextWrap(true);
  Led2.begin();
  Led2.setBrightness(10);
  Led2.setTextWrap(true);
}
int x1 = matrix1.width();
int x2 = Led2.width();
int pass = 1;

void loop() 
{
   lcd.backlight();
   matrix1.fillScreen(0);
   Led2.fillScreen(0);
   matrix1.setCursor(1, 1);
   matrix1.setTextColor(colors1[2]);
   matrix1.print("1");
   Led2.setCursor(1, 1);
   Led2.setTextColor(colors2[2]);
   Led2.print("2");

  //--------------------------------- Entrée sur tapis 1
  if (escTapis1.pressed() && escEtat1 == etatInitial1) 
   {
     Serial.println("Tapis entrée 1");
     escEtat1 = etatAuDepart1;
   }

  //--------------------------------- Quitter du tapis 1
  if (escTapis1.released() && escEtat1 == etatAuDepart1) 
   {
     Serial.println("Tapis 1 quitté  Démarrage chrono");
     escEtat1 = etatParti1;
     escChrono1 = millis();
   }

  //--------------------------------- Arrivée 1
  if (escArrivee1.pressed() && escEtat1 == etatParti1) 
   {
     Serial.println("Arrivée 1   Arrêt chrono");
     escTemps1 = escTempsCalcul1();
     Serial.println("Temps d'escalade : " + String(escTemps1, 2) + " sec.");
     escEtat1 = etatInitial1;
   }

  //--------------------------------- Affichage du chrono 1
  if (escEtat1 == etatParti1)  // Si escalade en cours
   {
     if (millis() - escTempsDisplayMillis1 >= escTempsDisplayTempo1) 
     {
       Serial.println("Chrono 1 = " + String(escTempsCalcul1(), 2) + " sec.");
       matrix1.setCursor(22, 1);
       matrix1.setTextColor(colors1[1]);
       matrix1.print(String(escTempsCalcul1(), 2));
       matrix1.show();
       lcd.setCursor(3, 2);
       lcd.print(String(escTempsCalcul1(), 2));
       escTempsDisplayMillis1 = millis();
     }
   }

  //--------------------------------- Entrée sur tapis 2
  if (escTapis2.pressed() && escEtat2 == etatInitial2) 
   {
     Serial.println("Tapis entrée 2");
     escEtat2 = etatAuDepart2;
   }

  //--------------------------------- Quitter du tapis 2
  if (escTapis2.released() && escEtat2 == etatAuDepart2) 
   {
     Serial.println("Tapis 2 quitté   Démarrage chrono");
     escEtat2 = etatParti2;
     escChrono2 = millis();
   }

  //--------------------------------- Arrivée 2
  if (escArrivee2.pressed() && escEtat2 == etatParti2) 
   {
     Serial.println("Arrivée 2  Arrêt chrono");
     escTemps2 = escTempsCalcul2();
     Serial.println("Temps d'escalade : " + String(escTemps2, 2) + " sec.");
     escEtat2 = etatInitial2;
   }

  //--------------------------------- Affichage du chrono 2
  if (escEtat2 == etatParti2)  // Si escalade en cours
   {
     if (millis() - escTempsDisplayMillis2 >= escTempsDisplayTempo2) 
     {
       Serial.println("Chrono 2 = " + String(escTempsCalcul2(), 2) + " sec.");
       Led2.setCursor(22, 1);
       Led2.setTextColor(colors2[1]);
       Led2.print(String(escTempsCalcul2(), 2));
       Led2.show();
       lcd.setCursor(3, 3);
       lcd.print(String(escTempsCalcul2(), 2));
       escTempsDisplayMillis2 = millis();
     }
   }

//-------------------------------------------------Affichages
    lcd.setCursor(13, 2);
    lcd.print(escTemps1, 2);
    lcd.setCursor(13, 3);
    lcd.print(escTemps2, 2);

  if (escEtat1 != etatParti1) 
   {
     matrix1.setCursor(22, 1);
     matrix1.setTextColor(colors1[1]);
     matrix1.print(escTemps1, 2);
     matrix1.show();
   }
  if (escEtat2 != etatParti2) 
   {
     Led2.setCursor(22, 1);
     Led2.setTextColor(colors2[1]);
     Led2.print(escTemps2, 2);
     Led2.show();
   } 

//---------------------------------------Vainqueur 1
   if(escTemps1 < escTemps2) 
    {
     matrix1.setCursor(22, 1);
     matrix1.setTextColor(colors1[3]);
     matrix1.print(escTemps1, 2);
     matrix1.show();
    }
   
//---------------------------------------Vainqueur 2
   if(escTemps2 < escTemps1) 
    {
     Led2.setCursor(22, 1);
     Led2.setTextColor(colors1[3]);
     Led2.print(escTemps2, 2);
     Led2.show();
    }

}

//---------------------------------------------Calcul des Temps
float escTempsCalcul1() 
{ return ((float)millis() - (float)escChrono1) / 600.0;  // Calcul du temps 1
}

float escTempsCalcul2() 
{ return ((float)millis() - (float)escChrono2) / 600.0;  // Calcul du temps 2
}


Un grand merci pour les bons tuyaux.
Cordialement
CASTRES

1 Like

Bonjour Castres,

JE suis sur le même projet pour des cours d'EPS. J'ai un prototype qui fonctionne mais je me demande si tu as résolu le soucis d'affichage. Un écran LCD c'est tout petit et j'aurais aimé que ce le temps soit visible par tout le monde