HELP : asservissement de bobines d'allumage => problème de synchro

Hello,

Je suis débutant en code et en arduino depuis qques mois.
J'ai parcourus longuement divers forum et blog et particulièrement celui ci.

Pour commencer sur un arduino uno et me familiariser avec le language (et les subtilités) :confused:

Bref, j'ai créé un programme et pas à pas j'ai débuggué à l'aide de l'écran LCD

Je bute sur un problème de synchronisation du pilotage des bobines.
Pour donner un ordre de grandeur la précision de l'allumage est du degré (soit 1/360 tour moteur)
A un régime moteur de 6000 trs/min il s'écoule 28microsecondes entre 2 degrés.

J'espère trouver de l'aide dans le forum pour comprendre ce que je ne vois pas.

Le but:
Faire un système d'allumage pour une voiture en utilisant :

-> En entrée un capteur Hall qui donne le top pour un tour moteur et un capteur de pression (pour la pression de l'admission du moteur).
-> En sortie deux Mosfet de type IGBT (spécifique allumage) pour piloter deux bobines.

Le principe :
S'affranchir d'un allumage mécanique (y compris du distributeur d'étincelle) en utilisant des bobines jumo-statiques.

L'arduino doit capter le top tour du moteur (et donc la position angulaire du capteur qui servira de référence)
Il devra calculer l'avance en fonction du régime moteur et de la pression de l'admission
Il devra enfin piloter précisément les bobines d'allumage.

Pour la partie Hard :
J'ai simuler mon moteur avec un ventilateur sur lequel j'ai greffé un capteur à effet HALL.
Ensuite tout installé provisoirement sur une platine avec qques fiches BNC.
Actuellement, j'utilise un GBF pour le signal régime moteur (le ventilo est bruyant) et un oscillo pour valider la synchronisation entre le signal du régime moteur et le signal de pilotage des bobines d'allumage.

Voici un aperçu du code (incomplet puisque je ne trouve pas solution pour la synchro allumage)

// DECLARATIONS 
// include the library code:

// Declaration Entree/Sortie
int broche10 = 10;                 // Sortie Allumage bobine pour cylindre 1 et 4
int broche11 = 11;                 // Sortie Allumage bobine pour cylindre 2 et 3
int capteurP = A1;                 // Entree capteur pression


// variables régime moteur

unsigned long rpm;
volatile unsigned long tmpActuel = 0;
volatile unsigned long tmpPreced = 0;
volatile unsigned long tmpTour = 0;

// variables pression collecteur
unsigned long sensorPcol = 0;
unsigned long rawPcol = 0;
unsigned long rawPcolFilt = 0;
int filtrePcol =0;


// variables calcul avance allumage

unsigned long stopsecu = 0;
volatile unsigned long tmpdegr = 0;
unsigned long PositCapteur = 90;
volatile unsigned long ALL = 0;
unsigned long Avance = 10;
unsigned long degreRpm = 0;
unsigned long degrePcol = 0;

   
   
// XXXXXXXXXXXXXXXXXXX SETUP XXXXXXXXXXXXXXXXXXXXXXX
void setup() {

  
  // Initialisation Sorties / Entrees
  pinMode(broche10, OUTPUT);      // met la borche 10 en mode OUT
  pinMode(broche11, OUTPUT);      // met la borche 11 en mode OUT
  
 // déclaration de l'interruption pour le capteur regime
  attachInterrupt(0, capteurHall, RISING);  
  

}


// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX LOOP xxxxxxxxxxxxxxxxxxxxx

void loop() {
 

// FONCTION Pression collecteur

  sensorPcol = analogRead(capteurP); // Mesure pression brute
  
  if (filtrePcol > 20) {    // filtrage pression sur 2000 mesure => A ajuster en fonction de temps de récurrence de mesure 
    rawPcolFilt = rawPcol/20;
    filtrePcol =0; 
    rawPcol = 0;}
    else {
      rawPcol = rawPcol + sensorPcol; // Mesure de la sortie du capteur
      filtrePcol = filtrePcol+1;}
      

// FONCTION de cartographie des avances fonction du regime et pression admisssion
 

 if (rawPcolFilt<40) { degrePcol = 0; } 
   else if  (rawPcolFilt>540) { degrePcol = 9;  }
     else {
   degrePcol =  0.024 * rawPcolFilt - 0.96; // vecteur d'avance pression : 0.15bar a 0.6bar soit 40dec a 540dec
          }

if  (tmpTour > 120000) { Avance = 20; } // AVANCE de la plage de regime de 0 a 500 trs => tmpTour > 119880 microsecondes
     else if (tmpTour > 75000) { Avance = 10; }  // AVANCE de la plage de regime de 500 a 800 trs
       else if (tmpTour >= 17143) { // AVANCE de la plage de regime de 800 a 3500 trs
           degreRpm = (-0.0004321 * tmpTour + 42.4);
           Avance = degreRpm + degrePcol; }
             else  {   // AVANCE de la plage de regime a superieur a 3500 trs         
               Avance = 35 + degrePcol;}  
 
 ALL = PositCapteur-Avance;


} 

// xxxxxxxxxxxxxxxxxxxxxxxx ISR xxxxxxxxxxxxxxxxxxxxxxxxx

// Fonction interruption sur detection capteur hall 

void capteurHall()
{
 
  tmpPreced = tmpActuel; // mémorise la valeur de temps du tour précédent
  tmpActuel = micros(); // mémorise la valeur du temps actuel
  tmpTour = tmpActuel-tmpPreced; // calcul le temps entre chaque tour moteur
  
   tmpdegr = tmpTour/360; // calcul du temps entre chaque degre vilebrequin


 }

Un petit Up ...

Je cherche de l'aide pour finaliser mon code.

En effet la partie que je n'arrive pas à réaliser c'est le pilotage des deux sorties digital (qui piloteront deux IGBT)
avec une bonne synchro.

Dans le détail du code :

-> A l'interruption externe (déclenché par la détection d'un front montant de tension sur mon capteur Hall à chaque tour de moteur).
=> stockage de la valeur de micros() et comparaison avec la valeur stocké à l'interruption précédente

-> Dans la LOOP
=> calcul d'un angle d'avance à l'allumage en fonction du régime moteur (exprimé dans le code en temps par tour moteur et comparée à la valeur figée pendant l'interruption
=> acquisition de la valeur du capteur de pression (avec une moyenne pour lisser les bruits de signal)
=> calcul d'un angle d'avance à partir de la pression mesurée
=> soustraction de l'avance calculée à la position du capteur Hall (90° avant le point mort haut)

1ere tentative de pilotage des IGBT:
J'avais fait une interruption à partir du timer.one à 50microsecondes, pour comparer à la fonction micros() mon avance (convertie en temps).
Mais le résultat donnait n'importe quoi en terme de synchro.

// DECLARATIONS 


// Include timer1 library
#include <TimerOne.h> 
#define TIMER_US (50) 

// Declaration Entree/Sortie
int broche10 = 10;                 // Sortie Allumage bobine pour cylindre 1 et 4
int broche11 = 11;                 // Sortie Allumage bobine pour cylindre 2 et 3
int capteurP = A0;                 // Entree capteur pression

unsigned long CompteurTemps = 0; //recopie du compteur micros

// variables régime moteur
unsigned long rpm;
unsigned long rpm1;
volatile unsigned long tmpActuel = 0;
volatile unsigned long tmpPreced = 0;
volatile unsigned long tmpTour = 0;
unsigned long DetectRpm = 0;

// variables pression collecteur
unsigned long sensorPcol = 0;
unsigned long rawPcol = 0;
unsigned long rawPcolFilt = 0;
int filtrePcol =0;

float Pcol = 0;

// variables calcul avance allumage
unsigned long tmpFutur = 0;
unsigned long tmpCharge = 0;
unsigned long tmpAll = 0;
unsigned long stopsecu = 0;
unsigned long tmpdegr = 0;
unsigned long DebutAll14 = 0;
unsigned long FinAll14 = 0;
unsigned long DebutAll23 = 0;
unsigned long FinAll23 = 0;
unsigned long PMH14 = 45;
unsigned long PMH23 = 180;
float Qdwell = 0.63;  // Pourcentage de Dwell
unsigned long PCentDwell = 0.30;   // Pourcentage du temps d'etincellage par rapport au temps d'un tour
unsigned long Rmin = 300;  // regime min
unsigned long Rmax = 4500;    // regime max
unsigned long Avance = 10;
unsigned long degreRpm = 0;
unsigned long degrePcol = 0;
int diode14 = 0;

   
   
// XXXXXXXXXXXXXXXXXXX SETUP XXXXXXXXXXXXXXXXXXXXXXX
void setup() {

  // Initialisation du Timer One
  Timer1.initialize(TIMER_US);
  Timer1.attachInterrupt( MyISR );

  
  // Initialisation Sorties / Entrees
  pinMode(broche10, OUTPUT);      // met la borche 10 en mode OUT
  pinMode(broche11, OUTPUT);      // met la borche 11 en mode OUT
  
 // déclaration de l'interruption pour le capteur regime
  attachInterrupt(0, capteurHall, RISING);  

}

// xxxxxxxxxxxxxxxxxxxxxxxxxxx TIMER ONE xxxxxxxxxxxxxxxxxxxxxxxxxx

void MyISR(){

// FONCTION application avance allumage

 if ((DebutAll14 > micros())&& (micros() < FinAll14)) {
   digitalWrite (broche10,LOW);  }
 else {
   digitalWrite (broche10,HIGH);  }

 
// Cylindre 2 et 3
 if (DebutAll23 > micros() && micros() < FinAll23) {
   digitalWrite (broche11,LOW);  }
 else   {
   digitalWrite (broche11,HIGH);  }
  
   }   

// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX LOOP xxxxxxxxxxxxxxxxxxxxx

void loop() {

  
  // FONCTION Regime moteur

  tmpTour = tmpActuel-tmpPreced; // calcul le temps entre chaque tour moteur
  rpm = (60 / (tmpTour/1000000.0)); // Calcul de la vitesse en tours/min

// FONCTION Pression collecteur

  sensorPcol = analogRead(capteurP); // Mesure pression brute
  
  if (filtrePcol > 20) {    // filtrage pression sur 2000 mesure => A ajuster en fonction de temps de récurrence de mesure 
    rawPcolFilt = rawPcol/20;
    filtrePcol =0; 
    rawPcol = 0;}
    else {
      rawPcol = rawPcol + sensorPcol; // Mesure de la sortie du capteur
      filtrePcol = filtrePcol+1;}
      
Pcol = ((rawPcolFilt*0.00093)+0.105) ;   // Calcul de la pression réel *par la pleine echelle et /par 1024dec

// FONCTION de cartographie des avances fonction du regime et pression admisssion
 

 if (Pcol<0.130) { degrePcol = 0; } 
//   else if  (Pcol>1) { degrePcol = 12;  }
   else if  (Pcol>0.530) { degrePcol = 9;  }
     else {
   degrePcol =  30 * Pcol - 3.9; // vecteur d'avance pression : 130mm/hg a 530mm/hg
          }

//if  (tmpTour > 119880) { Avance = 20; } // AVANCE de la plage de regime de 0 a 500 trs
if  (rpm < 500) { Avance = 20; } // AVANCE de la plage de regime de 0 a 500 trs
     else if (rpm < 800) { Avance = 10; }  // AVANCE de la plage de regime de 500 a 800 trs
       else if (rpm <= 3500) { // AVANCE de la plage de regime de 800 a 3500 trs
           degreRpm = (0.0093 * rpm + 2.593);
           Avance = degreRpm + degrePcol; }
             else  {   // VANCE de la plage de regime a superieur a 3500 trs         
               Avance = 35 + degrePcol;}  
               

// FONCTION coupure allumage

  if (rpm <= Rmin||rpm > Rmax||((micros() - tmpActuel)>250000)) {
    stopsecu = 1;    } 
    else {
      stopsecu = 0;    } 

// FONCTION calcul DWELL
  tmpFutur = tmpActuel+tmpTour;
  tmpCharge = max((tmpFutur*Qdwell),4000); //calcul le temps de charge de la bobine avec une borne mini a 4ms
  //tmpAll = tmpTour - tmpCharge; // calcul le temps d'etincellage
   
// FONCTION de calcul du point d'avance a l allumage

  tmpdegr = tmpTour/360;
 
  DebutAll14 = tmpFutur+((PMH14-Avance)*tmpdegr);
  FinAll14 = DebutAll14+tmpCharge;
  DebutAll23 = DebutAll14+(tmpdegr*180);
  FinAll23 = DebutAll23+tmpCharge;

} 

// xxxxxxxxxxxxxxxxxxxxxxxx ISR xxxxxxxxxxxxxxxxxxxxxxxxx

// Fonction interruption sur detection capteur hall 

void capteurHall()
{
  tmpPreced = tmpActuel; // mémorise la valeur de temps du tour précédent
  tmpActuel = micros(); // mémorise la valeur du temps actuel
 }

J'ai tenté de baisser la fréquence de l'interruption à moins de 50 uS sur Timer.one, mais je pense que mes quelques calculs avec cette fréquence font ramer le UNO. Et donc résultats négatifs...

2nd tentative de pilotage des IGBT:
J'ai tenté d'utiliser des delay dont les valeurs étaient calculées à partir de mon avance converti en temps. Ceci appliqué dans l'interruption du capteur Hall.
=> j'ai obtenu qques résultats positifs à régime fixe mais ça ne fonctionne plus dès que je monte en fréquence, et à l'inverse delaymicroseconds est limité à 16000 et des brouettes ce qui rend impossible le fonctionnement à fréquence faible.

// DECLARATIONS 

// Declaration Entree/Sortie
int broche10 = 10;                 // Sortie Allumage bobine pour cylindre 1 et 4
int broche11 = 11;                 // Sortie Allumage bobine pour cylindre 2 et 3
int capteurP = A1;                 // Entree capteur pression


// variables régime moteur

unsigned long rpm;
volatile unsigned long tmpActuel = 0;
volatile unsigned long tmpPreced = 0;
volatile unsigned long tmpTour = 0;

// variables pression collecteur
unsigned long sensorPcol = 0;
unsigned long rawPcol = 0;
unsigned long rawPcolFilt = 0;
int filtrePcol =0;

float Pcol = 0;

// variables calcul avance allumage
volatile int interruptionOUT = 0;
unsigned long stopsecu = 0;
volatile unsigned long tmpdegr = 0;
volatile unsigned long DebutA = 0;
volatile unsigned long DebutB = 0;
unsigned long PositCapteur = 90;
volatile unsigned long ALL = 0;
unsigned long Avance = 10;
unsigned long degreRpm = 0;
unsigned long degrePcol = 0;

   
   
// XXXXXXXXXXXXXXXXXXX SETUP XXXXXXXXXXXXXXXXXXXXXXX
void setup() {

  
  // Initialisation Sorties / Entrees
  pinMode(broche10, OUTPUT);      // met la borche 10 en mode OUT
  pinMode(broche11, OUTPUT);      // met la borche 11 en mode OUT
  
 // déclaration de l'interruption pour le capteur regime
  attachInterrupt(0, capteurHall, RISING);  
  
}


// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX LOOP xxxxxxxxxxxxxxxxxxxxx

void loop() {
  

  DebutA = (ALL*tmpdegr) ; // debut de coupure alimentation bobine 1 pour creer etincelle sur cylindres 1 et 4
  DebutB=(tmpdegr*180)-2000; // debut de coupure alimentation bobine 1 pour creer etincelle sur cylindres 2 et 3
  
 // FONCTION de calcul du moment d'avance a l allumage
if (DebutA>16000){

  delay (DebutA/1000);
   digitalWrite (broche10,HIGH); // mise à 5 volts de la borche 10 pour pilotage bobine = avance allumage
  
  delay (2); // delai de 2ms pour faire l etincelle
  digitalWrite (broche10,LOW);
  
      delay (DebutB/1000);
  digitalWrite (broche11,HIGH); // mise à 5 volts de la borche 11 pour pilotage bobine = avance allumage
  
  delay (2); // delai de 2ms pour faire l etincelle
  digitalWrite (broche11,LOW);

 }
 
  // FONCTION Regime moteur

//  rpm = (60 / (tmpTour/1000000.0)); // Calcul de la vitesse en tours/min
  


// FONCTION Pression collecteur

  sensorPcol = analogRead(capteurP); // Mesure pression brute
  
  if (filtrePcol > 20) {    // filtrage pression sur 2000 mesure => A ajuster en fonction de temps de récurrence de mesure 
    rawPcolFilt = rawPcol/20;
    filtrePcol =0; 
    rawPcol = 0;}
    else {
      rawPcol = rawPcol + sensorPcol; // Mesure de la sortie du capteur
      filtrePcol = filtrePcol+1;}
      

// FONCTION de cartographie des avances fonction du regime et pression admisssion
 

 if (rawPcolFilt<40) { degrePcol = 0; } 
   else if  (rawPcolFilt>540) { degrePcol = 9;  }
     else {
   degrePcol =  0.024 * rawPcolFilt - 0.96; // vecteur d'avance pression : 0.15bar a 0.6bar soit 40dec a 540dec
          }

if  (tmpTour > 120000) { Avance = 20; } // AVANCE de la plage de regime de 0 a 500 trs => tmpTour > 119880 microsecondes
     else if (tmpTour > 75000) { Avance = 10; }  // AVANCE de la plage de regime de 500 a 800 trs
       else if (tmpTour >= 17143) { // AVANCE de la plage de regime de 800 a 3500 trs
           degreRpm = (-0.0004321 * tmpTour + 42.4);
           Avance = degreRpm + degrePcol; }
             else  {   // AVANCE de la plage de regime a superieur a 3500 trs         
               Avance = 35 + degrePcol;}  
 
 ALL = PositCapteur-Avance;
    

// FONCTION coupure allumage
  if (tmpTour <= 6000||tmpTour > 230000||((micros() - tmpActuel)>250000)) {
    stopsecu = 1; 
    digitalWrite (broche10,HIGH); // mise à 5 volts de la borche 10 pour pilotage bobine = avance allumage
    digitalWrite (broche11,HIGH); // mise à 5 volts de la borche 11 pour pilotage bobine = avance allumage
   } 
    else {
      stopsecu = 0;    } 

} 

// xxxxxxxxxxxxxxxxxxxxxxxx ISR xxxxxxxxxxxxxxxxxxxxxxxxx

// Fonction interruption sur detection capteur hall 

void capteurHall()
{
 
  tmpPreced = tmpActuel; // mémorise la valeur de temps du tour précédent
  tmpActuel = micros(); // mémorise la valeur du temps actuel
  tmpTour = tmpActuel-tmpPreced; // calcul le temps entre chaque tour moteur
  
   tmpdegr = tmpTour/360; // calcul du temps entre chaque degre vilebrequin

      delayMicroseconds (DebutA);
   digitalWrite (broche10,HIGH); // mise à 5 volts de la borche 10 pour pilotage bobine = avance allumage
  
  delayMicroseconds (2000); // delai de 2ms pour faire l etincelle
  digitalWrite (broche10,LOW);
  
      delayMicroseconds (DebutB);
  digitalWrite (broche11,HIGH); // mise à 5 volts de la borche 11 pour pilotage bobine = avance allumage
  
  delayMicroseconds (2000); // delai de 2ms pour faire l etincelle
  digitalWrite (broche11,LOW);

 }