Salut à tous !
Grande nouvelle, le problème d'interruption capricieuse est réglé !
Bilan: ça ne venait pas d'un problème de signal mais bien un problème logiciel.
(Ca ne m'empêchera pas de passer sur un Pull-up externe à l'avenir)
En fait l'ISR n'appréciait l'appel à micros() et le lancement du Timer1 via la librairie Timerone.h.
J'ai contourné le problème en configurant manuellement le Timer.
Au passage de la cible, je calcule directement la période avec le comptage du Timer1, et le remet à zéro.
Le Timer1 peut déclencher des interruptions par comparaison avec une valeur donnée.
Sur le schéma ci desssus, la ligne rouge représente la valeur de comptage du Timer.
Finalement, c'est beaucoup plus simple ainsi et la loop() est désormais totalement indépendante. Ca va me permettre de revoir toute l'architecture du programme.
Voici le bout de code correspondant:
volatile int unsigned long overflow_count = 0;
volatile int unsigned long T = 0;
volatile bool etincelle = 0;
volatile int unsigned long D = 0;
volatile int unsigned long Davant_rech = 0;
/*
Version d'essai pour validation fonctionnement par ISR
Fait fonctionner le moteur avec une avance fixe
Une ISR est déclenchée au passage de la cible:
Le Timer 1 est remis à 0 en début de période.
3 ISR sont configurées sur ce timer:
-la première quand la valeur Timer atteint la valeur A correspondante à D => l'étincelle est déclenchée
-la deuxième quand la valeur Timer atteint la valeur B correspondante à D + Davant_rech => la bobine est mise en charge
- la troisième en cas de débordement du Timer (il peut compter jusqu'à 524ms avant de déborder)
cette troisième ISR sert à compter les périodes T supérieures à 524ms, elle ne sert donc que pour les régimes inférieurs à 115 tr/min
*/
void setup() {
Serial.begin(115200);
pinMode(2, INPUT_PULLUP);
pinMode(3, OUTPUT);
cli(); // désactive les interruptions
EICRA = 0b000000010; // Règle l'interruption broche D2 sur FALLING
EIMSK = 0b000000001; // Autorise les interruptions sur D2
TCCR1A = 0b000000000; // Règle le Timer1
TCCR1B = 0b000000011; // Règle le prediviseur Timer1 à 64 => 1 clock = 4µs
TIMSK1 = 0b000000111; // Autorise les interruptions par comparaison registre OCR1A, OCR1B, et overflow
sei(); // Réactive les interruptions
}
ISR(TIMER1_COMPA_vect){ // ISR qui déclenche l'étincelle
digitalWrite(3, HIGH);
}
ISR(TIMER1_COMPB_vect){ // ISR qui remet en charge la bobine
digitalWrite(3, LOW);
}
ISR(TIMER1_OVF_vect){ // ISR déclenchée par overflow Timer1 (pour calcul période T)
overflow_count++; // Compte le nombre de débordements
TCNT1 = 0; // Remet Timer 1 à 0
}
ISR(INT0_vect){ // ISR déclenchée par le passage de la cible
T = overflow_count*65535 + TCNT1; // Calcul la période en cycles horloges
TCNT1 = 0; // Remet le Timer à 0
overflow_count = 0; // Remet le compteur overflow à 0 pour le prochain calcul
T = T * 4; // Convertit les cycles d'horloge en unité de temps (un cycle = 4µs)
D = T / 180 * 50; // Calcule le délai avant étincelle (pour respect avance allumage)
Davant_rech = T * 3 / 10; // Calcule le délai avant recharge bobine (pour respect Dwell)
OCR1A = (D/4-2); // Fixe le seuil d'interruption
OCR1B = ((D + Davant_rech)/4-2);
}
void loop() {
}
Affaire à suivre !