[non réglé] Allumage électronique programmable Arduino Uno

Bonjour à tous,

Débutant en Arduino et assez peu familier du code, après quelques programmes très simples, j'essaye d'élaborer un programme d'allumage pour moto ancienne en remplacement d'allumage à vis platinées ou d'ancien allumage électronique analogique.

Je suis parti (heureusement !) d'un allumage fonctionnel AEPL de Ph. Loutrel avec qui je suis en contact mais il est très occupé avec d'autres développements...
http://a110a.free.fr/SPIP172/article.php3?id_article=142

Son fonctionnement est basé sur la mesure de la vitesse (N) de rotation du moteur (capteur à effet Hall et une cible en métal en bout de vilebrequin ou d'arbre à cames).

Le temps mesuré (T) à chaque tour permet de calculer un temps d'avance à l'allumage (D).
L'allumage (Etincelle) se produit avant le point mort haut du moteur (le PMH) afin de laisser le temps au mélange air + essence de s'enflammer.

Une courbe (régime Na, avance Anga) est à renseigner en début de programme.

Différents paramètres sont à renseigner, nombre de cylindres, angle du capteur avant le PMH, temps de charge de la bobine d'allumage, etc.

L'avance à bas régime est imposée et calculée à 0° (PMH) afin d'éviter un retour de gaz au démarrage (notamment au kick pour une moto, gros risque de blessure si trop d'avance !!)

Ensuite elle est calculée à partir des points de la courbe, c'est une partie assez compliquée pour moi.

Il est aussi nécessaire de calculer le moment où la bobine sera alimentée (Bob = 1) avant l'allumage (Etincelle, Bob = 0), c'est élaboré avec le Timer1.

Une sécurité bobine est prévue (Dsecu), si le moteur est arrêté on coupe l'alimentation de la bobine au bout de cette temporisation, ex 1 sec ce qui d'ailleurs limite le régime minimum de fonctionnement de l'allumage.

Ça fonctionne bien mais :
L'AEPL ne respecte pas bien le temps de charge bobine, différence entre calcul de l'avance et calcul du moment d'alimentation avec Timer1, surtout pendant les phases transitoires de changement de régime.

L'AEPL ne respecte pas bien l'avance à 0° en cas de rotation moteur non régulière ou incomplète à très bas régime (démarrage au kick).

Je voudrais utiliser une bobine très basse résistance dont le temps de charge doit parfaitement être maîtrisé, ex 5 ms et pas plus sinon la bobine peut cramer !

Et je voudrais déclencher l'allumage à très bas régime à 0° sans calcul d'avance car il peut être faussé, car la rotation du moteur peut être à vitesse non constante, voire incomplète.

J'ai donc fait une version un peu différente (MM), le temps de charge bobine est fixe et intégré au temps d'avance, ça fonctionne bien,

mais là le capteur est à 0° ou 360° pour déclencher avec une grande sûreté l'allumage à bas régime à 0°, ça fonctionne bien aussi,

ensuite à partir d'un seuil (Ndem) l'avance est calculée avec le capteur que je considère à 360° pour laisser le temps à TchargeBob + avance (à 60 ou 90° comme l'AEPL ça ne fonctionne pas, c'est trop court, idem à 180°),
et là c'est irrégulier, aléatoire, des allumages par moment, l'avance totalement fausse etc.

J'ai essayé plusieurs modifications, essayé de faire une interruption pour le capteur au lieu de la boucle while existante, j'ai essayé séparément la mesure de T seule, c'est ok, mais je bute sur le fonctionnement du calcul d'avance.

Le code est trop long malheureusement je mets un lien pour le fichier texte :

http://a110a.free.fr/SPIP172/IMG/txt/Aepl-duino_11-11-16.txt

Ma version simplifiée mais problématique partie 1/3 :

//Michel essai allumage au changement d'état (front montant) fin de la cible (capteur Hall) à 0° (ou 360° c'est identique)

//**************************************************************
                                                  // Aepl-Aecp Arduino Nano. Allumage électronique programmable, version simplifiée
char ver[] = "version MM du 28_01_2017";          // MM avance à 0° au démarrage en fin de cible, Temps d'avance non calculé
                                                  // MM avance calculée depuis top capteur à 0° au lieu de 60° par exemple pour une meilleure stabilité du temps de charge bobine
                                                  // MM version sans isr gestionIbob, ni desecu
                                                  // LED de calage statique de l'allumage,
                                                
//******************************************************************************


//**************  Ces lignes sont à renseigner obligatoirement.****************
          // Ce sont : Na[],Anga[],  Ncyl, AngleCapteur, CaptOn, 
          // Les tableau Na[] et Anga[] doivent obligatoirement débuter puis se terminer par  0
          // et  contenir des valeurs  entières >= 1
          // Le nombre de points est libre. L'avance est imposée à 0° entre 0 et Nplancher t/mn
          // Le dernier N fixe la ligne rouge, c'est à dire la coupure de l'allumage
          
//***************  Courbe Avance régime à renseigner 
          // Au régime moteur de (obligatoirement croissant):
int Na[] = {0, 500, 600, 700,  800,  900, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 6800, 7000, 0}; // Courbe a  (16 valeurs)         MM ajout unsigned ? pas de différence
          // degrés d'avance vilebrequin correspondant:
int Anga[] = {0, 1,  8,  12,   12,    8,   12,   20,   22,   24,   28,   28,   28,   28,    5,  0}; //                    MM ajout unsigned                
          
int Ncyl = 2;                     // Nombre de cylindres (modifiable)
const int AngleCapteur = 360;     // Angle entre la position du capteur Hall et le Point Mort Haut du moteur (MM angle vilebrequin) 45° minimum, avec 360° l'avance + le temps de charge bobine est calculé 1 tour avant

const int CaptOn = 0;             // CapteurOn = 0 déclenche sur front descendant (capteur non saturé). le capteur Hall conduit (donc 0 V) quand le disque aimanté passe devant Voir explications en fin du listing
                                  // CapteurOn = 1 déclenche sur front montant (capteur saturé)

boolean Autorisation_Etincelle = 0;  // MM essai autorisation étincelle avec avance calculée, elle est à 0 au début puis à 1 dès la première étincelle au démarrage   
                                     // MM cela évite une étincelle perdue à l'alimentation du circuit
                                                                   
           //************Ces valeurs sont eventuellement modifiables*****************
                                             // Ce sont TchargeBob , Ndem
const int Ndem = 150;                        // Régime estimée du moteur entrainé par le demarreur en t/m   MM : const int constante non modifiable                                          
const int TchargeBob = 5000;                 // temps de recharge bobine, ex 7 ms pour bobines Lucas de 3 ohms, 5 ms pour bobine moderne (ex Clio 16S bobine crayon Bosch )

          //***********************Variables du sketch************************************
          
const int Bob = 4;                  // Sortie D4 vers bobine
const int Cible = 2;                // Entrée sur D2 du capteur, R PullUp et interrupt
const int Led = 13;                 // Sortie D13 avec la led built-in (interne sur l'Arduino Nano) pour caller le disque par rapport au capteur

float modC1 = 0;                    // MM Correctif pour C1[]

int unsigned long D = 0;            // Délai en µs à attendre après la cible pour l'étincelle // MM pas de int ? pas de changement     
int unsigned long Dsum = 0;         // Délai en µs avec les corrections (temps de calcul, temps de charge bobine) pour l'avance totale  // MM pas de int 

int milli_delay = 0;
int micro_delay = 0;

const int tcor = 240;               // Temps de correction en µs du temps de calcul pour D 120 µs  + 120 µs de traitement , 
int unsigned long Tprec  = 0;       // Période précédant la T en cours, pour calcul de TchargeBob  // MM pas de int  
int unsigned long prec_H  = 0;      // Heure du front précédent en µs    // MM pas de int                        
int unsigned long T  = 0;           // Période en cours    // MM pas de int  
int unsigned long Tdem  = 0;        // Période correspondante à Ndem, forcée pour le régime de démarrage (au démarreur électrique)  // MM pas de int 

int N1  = 0;                       // Couple N,A de début d'un segment
int Ang1  = 0;                     // Car A1 réservé pour entrée analogique!
int N2  = 0;                       // Couple N,A de fin de segment
int Ang2  = 0;
int*  pN = &Na[0];                 // pointeur au tableau des régimes. Na sera la courbe par défaut    // MM unsigned ? pas de changement
int*  pA = &Anga[0];               // pointeur au tableau des avances. Anga sera la courbe par défaut  // MM unsigned 
float k = 0;                       // Constante pour calcul de l'avance courante
float C1[20];                      // Tableaux des constantes de calcul de l'avance courante 20 cases prévues
float C2[20];                      // Tableaux des constantes de calcul de l'avance courante 20 cases prévues
float Tc[20];                      // Tableau des Ti correspondants au Ni 20 cases prévues
                                   // Si nécessaire, augmenter ces 3 valeurs: Ex C1[30],C2[30],Tc[30]
int Tlim  = 0;                     // Période minimale, limite, pour la ligne rouge
int j_lim = 0;                     // index maxi des N, donc aussi Ang
int unsigned long NT  = 0;         // Facteur de conversion entre N et T à Ncyl donné       // MM int unsigned utile ?              
int AngleCibles = 0;               // Angle entre 2 cibles, 180° pour 4 cyl, 120° pour 6 cyl, est calculé dans le code avec 720 / N cylindres                                   
                                   // Permet d'identifier le premier front et forcer T=Tdem, ainsi que Ibob=1, pour démarrer au premier front
float uspardegre = 0;

int unsigned long Vitesse = 0;     // vitesse en cours              // MM pas de int ? pas de changement                                      
int unsigned long Delaideg = 0;    // µs/deg pour calcul avance     // MM pas de int                                
                                   // Tableau pour sauver des données temporelles
                                    
unsigned long Stop_temps_Etincelle = 0;          // MM ajout de = 0  (pas utile !)           
unsigned long Tempsecoule = 0;                   // MM temps écoulé entre étincelle et top capteur                    
long AvanceMoteur = 0;                           // MM calcul avance moteur pour sortie série, initialisation à 0, nombre signé l'avance peut-être négative

2/3

                  //********************LES FONCTIONS*************************

void  CalcD ()    //  Calcul délai avant étincelle, avance totale
{                                            // Noter que T1>T2>T3...  
 for (byte j = 1; j <= j_lim; j++)           // On commence par T la plus longue et on remonte, tant que j < limite on augmente j + 1  MM origine en byte
// for (int j = 1; j <= j_lim; j++)           // On commence par T la plus longue et on remonte, tant que j < limite on augmente j + 1  MM essai en int comme AEPL pas de différence
  {                                             
    if  (T >=  Tc[j]) {                      // Si T période en cours supérieure ou égal à j tableau des Ti et Ni
                                             // on a trouvé le bon segment de la courbe d'avance                                                                                         
    D =  float(T * ( C1[j] - modC1 ) + C2[j]);   // MM calcul de D  temps de l'avance à l'allumage (brut sans corrections etc.) 
   
  Serial.print(" ; D = ");         // MM mesure de la période T entre chaque tour moteur  
  Serial.println(D);               // MM T    
                              
    Dsum = D - tcor - TchargeBob;           // MM Dsum total de D  - temps de calcul - (MM) Temps de charge des bobines, (tcor appliqué ici donne de meilleurs résultats niveau précision)
 
   if (Dsum < 6500) {  
    delayMicroseconds(Dsum);                 // Attendre Dsum, MM si Dsum (avance totale) est inférieure à 6500 µs (il y a de la marge avec maxi 16383 µs) le délai Dsum est directement en µs
  }
  
  else {                                     // MM sinon si Dsum est égal ou supérieur à 6500 µs, convertir Dsum en ms et us avec milli delay et micro delay 
  milli_delay = ((Dsum/1000)-2);             // car problèmes avec delayMicroseconds si Dsum > 14 ms! Currently, the largest value that will produce an accurate delay is 16383 µs  
  micro_delay = (Dsum-(milli_delay*1000));   // MM milli delay c'est Dsum en us / 1000 (-2) et micro delay c'est le reste en us de Dsum - milli delay
  
  delay(milli_delay);                        // MM délai en ms à attendre avant alimenation bobine et étincelle pour avoir l'avance à l'allumage programmée
  delayMicroseconds(micro_delay);            // MM délai en us à attendre avant alimenation bobine et étincelle pour avoir l'avance à l'allumage programmée 
     
      break;
    }
  }
 }
}


void  Etincelle ()           // Charger la bobine en l'alimentant pendant T recharge Bobine et la couper pour avoir l'étincelle d'allumage
{                                                              
  digitalWrite(Bob, 1);                     // MM établir le courant
  delayMicroseconds(TchargeBob);            // MM charger (alimenter) les bobines pendant le temps de charge déterminé : "TchargeBob" en µs (ex 5 ms)   
  digitalWrite(Bob, 0);                     // Couper le courant, donc étincelle
  
  Stop_temps_Etincelle = micros();          // Pour calcul des temps
}


void  Init ()              // Elaboration du point d'avance dans la cartographie
                                                 // Calcul de 3 tableaux,C1,C2 et Tc qui serviront à calculer D, temps d'attente
                                                 // entre la détection d'une cible par le capteur  et la génération de l'étincelle.
                                                 // Le couple C1,C2 est determiné par la période T entre deux cibles, correspondant au
                                                 // bon segment de la courbe d'avance entrée par l'utilisateur: T est comparée à Tc
{ 
  AngleCibles = 720 / Ncyl;                      // Ex : 720° pour 1 ou 2 cylindres (à étincelle perdue), 180° pour 4 cylindres, et 120° pour 6 cylindres
  NT = 120000000 / Ncyl;                         // Facteur de conversion Nt/mn en T µs

                                                 // T temps entre 2 étincelles soit 720°  1°=1/6N
  Tdem = NT / Ndem;                              // Période pour le régime de démarrage

  N1  = 0; Ang1 = 0;                             // Toute courbe part de  0
  int i = 0;                                     // locale mais valable hors du FOR
  pN++; pA++;                                    // sauter le premier élément de tableau, toujours = 0
  for (i  = 1; *pN != 0; i++)                    // i pour les C1,C2 et Tc. Arrêt quand régime = 0.
                                                 // pN est une adresse (pointeur) qui pointe au tableau N. Le contenu pointé est *pN
  { N2 = *pN; Ang2 = *pA;                        // recopier les valeurs pointées dans N2 et Ang2
    k = float(Ang2 - Ang1) / float(N2  - N1);    // K = Angle 2 - Angle 1 / N2 - N1 (régime N2 - N1)
    
    C1[i] = float(AngleCapteur - Ang1 + k * N1) / float(AngleCibles);  // C1 = Angle Capteur - Angle 1 + k x N1 / Angle cible  
    C2[i] = -  float(NT * k) / float(AngleCibles);        
    Tc[i] = float(NT / N2);     
    N1 = N2; Ang1 = Ang2;                        // fin de ce segment, début du suivant    
    pN++; pA++;                                  // Pointer à l'élément suivant de chaque tableau
  }
  j_lim = i - 1;                                 // Revenir au dernier couple entré 
  Tlim  = Tc[j_lim];                             // Ligne rouge, limite du régime moteur maxi autorisé
}


void setup()                ///////////while (1); delay(1000);////////////////
{
  Serial.begin(115200);         // Ligne suivante, 3 Macros du langage C
  Serial.println(__FILE__); Serial.println(__DATE__); Serial.println(__TIME__);
  Serial.println(ver);
  
  if (Ncyl < 2)Ncyl = 2;           // On assimile le mono cylindre au bi, avec une étincelle perdue
  
  pinMode(Cible, INPUT_PULLUP);    // Entrée capteur essai interruption sur D2, front montant (résistance pullup)
  pinMode(Bob, OUTPUT);           // Sortie sur D4 controle du courant dans la bobine1
  pinMode(Led, OUTPUT);            // pour signaler le calage du capteur lors de la mise au point

  Autorisation_Etincelle = 0;      // MM autorisation étincelle à 0 au début de programme (évite une étincelle perdue à l'alimentation du circuit), passe à 1 dès les premières étincelles
                                 
  Init();                          // Executée une fois au démarrage et à chaque changement de courbe (option multi-courbes d'avance)
}

Fin du programme (ouf !)

void loop()                   //////////////// Attendre la présence de la cible avec capteur pour si besoin calculer l'avance et créer l'allumage
{                              
  while (digitalRead(Cible) == CaptOn);          // MM boucle tant que : capteur actif de la cible
  digitalWrite(Led,HIGH);                        // MM Allumage Led de calage statique tant que la cible est présente, et extinction en fin de cible donc à 0° Point Mort Haut moteur 
  
  T = micros() - prec_H;                         // MM on quitte le front actif calculer T = temps en microsecondes depuis le début - heure précédente
  prec_H = micros();                             // heure précédente = heure actuelle en microseconde  

  Serial.print(" ; T = ");       // MM mesure de la période T entre chaque tour moteur  
  Serial.print(T);               // MM T 

  if (T >= Tdem){Etincelle();(Autorisation_Etincelle = 1);}         // MM étincelle immédiate (sans calcul d'avance) si sous le régime de démarrage (au démarreur électrique) et à la fin de la cible aimantée à 0° au PMH du moteur, fin de la cible active
                                                                    // Autorisation Etincelle passe à 1 suite à ce premier allumage                                                 
  if (T > Tlim && T < Tdem && Autorisation_Etincelle == 1)          // MM Si sous la ligne rouge (régime maxi) ET au-dessus du régime de démarrage (au démarreur électrique) ET autorisation étincelle à 1

  {  
  CalcD();                                       // Calcul de l'avance à l'allumage avec le temps de charge Bobine   
  Etincelle();                                   // fonction Etincelle donc allumage moteur
  }

  Vitesse = NT / T;                              // MM calcul de la vitesse (régime moteur)
  Delaideg = NT / Vitesse / float(AngleCibles);  // MM calcul du délai en degrés
  Tempsecoule = Stop_temps_Etincelle - prec_H;             // MM calcul du temps entre étincelle et le top capteur
  AvanceMoteur = AngleCapteur - (Tempsecoule / Delaideg);  // MM calcul avance totale à l'allumage du moteur
  if (AvanceMoteur < 0) {AvanceMoteur = 0;}                // MM si l'avance est négative ou pas d'allumage, afficher 0 


  while (digitalRead(Cible) ==! CaptOn);         // boucle tant que capteur non actif
  digitalWrite(Led,LOW);                         // MM extinction LED de calage statique quand la cible est absente


        /////////// MM Informations envoyées vers le port série pour lecture du régime moteur, du temps entre allumage et PMH et de l'avance à l'allumage etc.
  
  Serial.print(" ; N = ");       // MM régime moteur N  
  Serial.print(Vitesse);         // MM régime moteur N
  Serial.print(" tr/mn, Tall = ");
  Serial.print(Tempsecoule);     // MM temps entre allumage (étincelle) et top capteur à 0°
  Serial.print(" us, Av = ");    // MM (espace devant µs sinon problème de lecture)
  Serial.print(AvanceMoteur);    // MM avance totale de l'allumage du moteur
  Serial.println(" deg");      
}

J'aimerais donc avoir quelques conseils sur mon programme par rapport au calcul d'avance perturbé,
je n'ai pas encore bien compris l'utilisation du Degug (voir l'AEPL), j'utilise des serial.print mais ça peut perturber le fonctionnement, j'en ai conscience.

Merci de m'avoir lu et ce n'est pas aisé à comprendre !

En complément avec un autre Arduino (enfin un clone de Nano) j'ai fait un générateur de créneaux 0/5V à fréquence variable avec un potentiomètre pour simuler le capteur Hall du moteur.
Ça permet de faire des tests plus facilement qu'avec un générateur BF plus précis mais beaucoup plus encombrant...

// MM générateur de créneaux à fréquence variable pour tester l'allumage électronique Arduino (simulation du capteur à effet Hall du moteur)

const int Gene = 13;             // Sortie générateur BF en D13
float F = 0;                     // Entrée analogique tension variable pour variation de fréquence
float N = 0;                     // N régime moteur simulé en tr/mn
float ValeurF = 0;

float  Etat1 = 0;    // Délai en ms à l'état 0 variable en fonction de la fréquence
float  Etat0 = 0;    // Délai en ms à l'état 1 variable en fonction de la fréquence

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

   pinMode(F, INPUT);       // Entrée tension du potentiomètre pour faire varier la fréquence
   pinMode(Gene, OUTPUT);   // Sortie créneaux sur D4  

}

void loop() {

  ValeurF = analogRead (A0);       // Lire la valeur de tension en sortie du potentiomètre

  F = map(ValeurF,0,1023,1,1220);  // La fréquence en 1/10 Hz,ou le régime moteur simulé est fonction de la tension de sortie du potentiomètre d'environ 6 à 7100 tr/mn
  N = F * 6;                       // N régime moteur simulé : F x 6 = N en tr/mn

  Serial.print("N = ");      // Lecture régime moteur simulé vers le port série
  Serial.println(N);      

  Etat1 = (8000 / F);        // Etat à 1 dure 1/F en ms 80%
  Etat0 = (2000 / F);        // Etat à 0 dure 1/F en ms 20% 
   
  digitalWrite(Gene,1);
  delay(Etat1);
  digitalWrite(Gene,0);   
  delay(Etat0);  
  
}

Bonjour à tous,

Peut-être une question simple pour m'aider à avancer :
Pour la mesure du temps et du régime moteur à chaque tour (capteur Hall), quelle est la meilleure méthode : une boucle while (qui me pose des problèmes avec le reste du programme car par moment la détection du top ne fonctionne pas par dépassement du temps T avec le reste)

ou une interruption ? Ce qui me parait mieux (plus sûr) mais là aussi j'ai quelques soucis avec le reste mais au moins la détection du Top est fiable.

Et dans l'interruption peut-on calculer le temps directement ou le faire dans Loop, et aussi est-ce utile de mettre les variables en volatile (avantages / risques ?).
Merci.

Exemple avec while :

void setup()
{
  Serial.begin(115200);
  
  pinMode(Cible, INPUT_PULLUP);    // Entrée capteur sur D2, front montant (résistance pullup)
  pinMode(Bob, OUTPUT);            // Sortie sur D4 controle du courant dans la bobine  
  Autorisation_Etincelle = 0;        // MM autorisation étincelle à 0 au début de programme (évite une étincelle perdue à l'alimentation du circuit)


void loop()                   //////////////// Attendre la présence de la cible avec capteur pour si besoin calculer l'avance et créer l'allumage
{ 
                               
  while (digitalRead(Cible) == CaptOn);          // MM boucle tant que : capteur actif de la cible
  
  T = micros() - prec_H;                         // MM on quitte le front actif calculer T = temps en microsecondes depuis le début - heure précédente
  prec_H = micros();                             // heure précédente = heure actuelle en microseconde  

  if (T >= Tdem)          // MM étincelle immédiate si t < 150 tr/mn (N démarrage) soit T > 400 ms
  {
  Etincelle();
  Autorisation_Etincelle = 1;

ou avec interruption
Exemple 1

void setup()
{
  Serial.begin(115200);
  
  pinMode(Cible, INPUT_PULLUP);    // Entrée capteur essai interruption sur D2, front montant (résistance pullup)
  pinMode(Bob, OUTPUT);            // Sortie sur D4 controle du courant dans la bobine  
  Autorisation_Etincelle = 0;        // MM autorisation étincelle à 0 au début de programme (évite une étincelle perdue à l'alimentation du circuit)

attachInterrupt(0, Pmh, RISING); // MM essai interruption front montant à la fin de la cible à 0° PMH

}


void  Pmh ()    ////////////////// Essai interruption pour Calcul temps T entre chaque top du capteur moteur
{  
    T = micros() - prec_H;                           // MM calculer T = temps en microsecondes depuis le début - heure précédente
    prec_H = micros();                               // heure précédente = heure actuelle en microseconde
}


void loop() 
{
  if (T >= Tdem)          // MM étincelle immédiate si t < 150 tr/mn (N démarrage) soit T > 400 ms
  {
  Etincelle();
  Autorisation_Etincelle = 1;
  }

Exemple 2

void setup()
{
  Serial.begin(115200);
  
  pinMode(Cible, INPUT_PULLUP);    // Entrée capteur essai interruption sur D2, front montant (résistance pullup)
  pinMode(Bob, OUTPUT);            // Sortie sur D4 controle du courant dans la bobine  
  Autorisation_Etincelle = 0;       // MM autorisation étincelle à 0 au début de programme (évite une étincelle perdue à l'alimentation du circuit)

attachInterrupt(0, Pmh, RISING); // MM essai interruption front montant à la fin de la cible à 0° PMH

}


void  Pmh ()    ////////////////// Essai interruption pour Calcul temps T entre chaque top du capteur moteur
{  
  MesureT = 1;                                      // MM essai mesure de T lors du passage au PMH
}


void loop() 
{
 if (MesureT == 1)  {                                 // MM essai interruption mesure de T
    T = micros() - prec_H;                           // MM calculer T = temps en microsecondes depuis le début - heure précédente
    prec_H = micros();                               // heure précédente = heure actuelle en microseconde
    MesureT = 0;
  }

  if (T >= Tdem)          // MM étincelle immédiate si t < 150 tr/mn (N démarrage) soit T > 400 ms
  {
  Etincelle();
  Autorisation_Etincelle = 1;
  }

Salut,
As-tu avancé sur ton projet ?
Je pense que je vais tester ça sur esp8266 avec pour cible un esp32 et sa connexion bluetooth pour debug comme vu sur certain projet.
Tout ça pour monter sur une BM R100.
A+