Commande automatique de groupe électrogène - machine à états et autres questions

Bon alors voila, pour détecter la rotation du moteur, j'ai rajouté un capteur de proximité qui compte les dents du ventilateur du moteur.

le nouveau scema de la carte V3.0 est le suivant :

J'ai connecté ce capteur sur l'entrée INT1 (pin D03), ma fonction associée à l'interruption mesure la période entre plusieurs tops et compte ces tops. Ensuite j'ai une fonction qui est appelée dans la boucle principale, qui calcule la vitesse de rotation du moteur à partir de cette période et du nombre de tops comptés.

unsigned int rpm_moteur; 	//vitesse de rotation moteur.

//variables utilisees en interruption (volatile = stockees en RAM)
volatile unsigned int rpm_cpt;                     //compteur de passage en interruption. Pour savoir cb de périodes sont utilisées pour le calcul de F
volatile unsigned long rpm_periode;                //periode des implulsion du capteur de rotation
volatile unsigned long rpm_tprecedent,rpm_tcourant;//temps utilisés pour calculer la période

void setup()
{
(...)
attachInterrupt(1, comptetour, RISING);	//entree rotation moteur sur INT1
(...)
}

void calcule_rpm() {
  //calcul de la vitesse de rotation du moteur.
  
  //on calcule la fréquence avec 1*60*1000/période car la période est en ms (*1000), et que l'on veut la fréquence en tr/min et non en Hz ou tr/s (*60)
  //on divise ensuite le total par le nombre de dents comptées par le capteur sur 1 tour moteur
  //la periode est une moyenne des rpm_cpt periodes mesurees en interruption avant passage par ici
  
  //Serial.print(rpm_cpt);
  //Serial.println(" ");  
  if (rpm_cpt) {
    rpm_moteur = (unsigned int)(60000/(rpm_periode/rpm_cpt))/nbr_dents_capteur_rota;
    rpm_cpt = 0; 			//remise à zero du compteur pour les prochaines mesures
    rpm_periode = 0;			//idem pour la periode
  }
  else if (rpm_tcourant<(temps_courant-300))
	rpm_moteur = 0;			//si pas de nouvelle mesure pdt plus de 300ms, alors le moteur est à l'arret ou le capteur est HS
					//300ms de période correspond à 22trs minutes si nbr_dents_capteur_rota=9
  //Serial.print(rpm_moteur);
  //Serial.print(" ");
  
}	

void comptetour(void) {
  //passage ici en interruption à chaque top capteur de vitesse. 
  //On stocke juste la somme des période des impulsions, et un compteur du nombre de périodes additionnées  
  rpm_tprecedent = rpm_tcourant;
  rpm_tcourant = millis();
  rpm_cpt++;
  rpm_periode += (rpm_tcourant-rpm_tprecedent);  
}

le code complet est ici : http://sourceforge.net/p/groupe/code/ci/31e71b1ae87b4828ae862ed18880018b4c217bed/tree/groupe.ino

Tout ça fonctionne très bien, du moins tant que le système est en veille (machine à état en état et_attente).

En revanche, dès que je demande un démarrage du moteur, on dirais que le passage en interruption ne se fait plus. Je passe bien dans la fonction de calcul de vitesse à chaque boucle, comme en attestent les serial.print que j'ai collé dedans, mais le nombre de tops comptés est toujours 0, quelle que soit la fréquence des impulsions en entrée, ce qui semble vouloir dire que je ne passe pas dans l'interruption.

Le pire, c'est que une fois la séquence de démarrage (ratée !) finie, quand la machine à état repasse en attente, ben ça remarche.... arghhhh !

Qu'est-ce qui peut me bloquer l'interruption ? J'avoue que je m'arrache les cheveux, je sent bien que ça doit être une connerie énorme, mais j'y suis depuis 3h et je trouve pas...