Bonjour tout le monde,
Je précise tout de suite que je suis débutant en programmation embarquée.
En voulant factoriser le code ci-dessous, je suis tombé sur un os. En effet, comme le code original était une succession de nombreux copié-collé quasiment identiques, j'ai voulu factorisé tout ça pour partir sur de bonnes bases. Mon problème est que attachInterrupt n'accepte pas de fonction avec paramètre (PulseTimer).
Que faire? Est-il possible de faire un tableau ou une structure dont les éléments serait les fonctions dont j'ai besoin?
D'avance merci.
les interruptions pointent vers une fonction qui ne prend ps de paramètre.
A moins de tracker dans l'interruption quelle pin à changé, vous devez conserver des fonctions différentes, une par interruption.
si vous voulez faire une boucle pour les attachInterrupt, il faudra mettre les fonctions PulseTimerXX dans un tableau de pointeurs sur fonction et utiliser le tableau (comme vous le faites pour les pins) dans le attachInterrupt.. c'est gagne petit, conservez donc les attachInterrupt()
pour simplifier le code des fonctions dans les interruptions vous pourriez cependant avoir une fonction générique qui prend le N° de pin changé
void interruptionSur(const byte pinQuiChange) {
••• // ici le code générique en fonction de pinQuiChange
}
void PulseTimer23() {interruptionSur(23);}
void PulseTimer25() {interruptionSur(25);}
void PulseTimer27() {interruptionSur(27);}
void PulseTimer29() {interruptionSur(29);}
void interruptionSur(const byte pinQuiChange) {
••• // ici le code générique en fonction de pinQuiChange
}
void PulseTimer23() {interruptionSur(23);}
void PulseTimer25() {interruptionSur(25);}
void PulseTimer27() {interruptionSur(27);}
void PulseTimer29() {interruptionSur(29);}
void PulseTimer31() {interruptionSur(31);}
void PulseTimer33() {interruptionSur(33);}
// tableau de pointeurs sur fonction dans le même ordre que les pins dans RCPin
void (*tableauPulseTimer[])() = { PulseTimer23, PulseTimer25, PulseTimer27, PulseTimer29 , PulseTimer31, PulseTimer33 };
votre code devient
for (byte i=0; i<nbr_pin; i++){
pinMode(RCPin[i],INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RCPin[i]), tableauPulseTimer[i],CHANGE);
}
En effet, j'avais fait une fonction générale mais elle prenait un paramètre, d'où mon problème.
En tout cas encore merci pour votre aide tout fonctionne correctement et j'ai pu diviser par plus de 2 le nombre de lignes.
Bonne journée.
Pour information, voici le code avant factorisation
#define RCPin23 23
#define RCPin25 25
#define RCPin27 27
#define RCPin29 29
#define RCPin31 31
#define RCPin33 33
volatile long StartTime23=0;
volatile long CurrentTime23=0;
volatile long Pulses23=0;
int PulseWidth23=0;
volatile long StartTime25=0;
volatile long CurrentTime25=0;
volatile long Pulses25=0;
int PulseWidth25=0;
volatile long StartTime27=0;
volatile long CurrentTime27=0;
volatile long Pulses27=0;
int PulseWidth27=0;
volatile long StartTime29=0;
volatile long CurrentTime29=0;
volatile long Pulses29=0;
int PulseWidth29=0;
volatile long StartTime31=0;
volatile long CurrentTime31=0;
volatile long Pulses31=0;
int PulseWidth31=0;
volatile long StartTime33=0;
volatile long CurrentTime33=0;
volatile long Pulses33=0;
int PulseWidth33=0;
int LimiteBruitPWM=2000;
void setup() {
//A commenter si on opère sans ordi
Serial.begin(9600);
pinMode(RCPin23,INPUT_PULLUP);
pinMode(RCPin25,INPUT_PULLUP);
pinMode(RCPin27,INPUT_PULLUP);
pinMode(RCPin29,INPUT_PULLUP);
pinMode(RCPin31,INPUT_PULLUP);
pinMode(RCPin33,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RCPin23), PulseTimer23,CHANGE);
attachInterrupt(digitalPinToInterrupt(RCPin25), PulseTimer25,CHANGE);
attachInterrupt(digitalPinToInterrupt(RCPin27), PulseTimer27,CHANGE);
attachInterrupt(digitalPinToInterrupt(RCPin29), PulseTimer29,CHANGE);
attachInterrupt(digitalPinToInterrupt(RCPin31), PulseTimer31,CHANGE);
attachInterrupt(digitalPinToInterrupt(RCPin33), PulseTimer33,CHANGE);
}
void loop(){
FiltrePWM();
}
//FONCTION ROUTINE
void FiltrePWM(){
if (Pulses23<LimiteBruitPWM) { PulseWidth23=Pulses23; }
if (Pulses25<LimiteBruitPWM) { PulseWidth25=Pulses25; }
if (Pulses27<LimiteBruitPWM) { PulseWidth27=Pulses27; }
if (Pulses29<LimiteBruitPWM) { PulseWidth29=Pulses29; }
if (Pulses31<LimiteBruitPWM) { PulseWidth31=Pulses31; }
if (Pulses33<LimiteBruitPWM) { PulseWidth33=Pulses33; }
Serial.println(PulseWidth23);
// Serial.println(PulseWidth25);
// Serial.println(PulseWidth27);
// Serial.println(PulseWidth29);
// Serial.println(PulseWidth31);
// Serial.println(PulseWidth33);
}
// FONCTION INTERRUPT
void PulseTimer23(){
CurrentTime23=micros();
if (CurrentTime23 > StartTime23){
Pulses23=CurrentTime23-StartTime23;
StartTime23=CurrentTime23;
}}
void PulseTimer25(){
CurrentTime25=micros();
if (CurrentTime25 > StartTime25){
Pulses25=CurrentTime25-StartTime25;
StartTime25=CurrentTime25;
}}
void PulseTimer27(){
CurrentTime27=micros();
if (CurrentTime27 > StartTime27){
Pulses25=CurrentTime27-StartTime27;
StartTime27=CurrentTime27;
}}
void PulseTimer29(){
CurrentTime29=micros();
if (CurrentTime29 > StartTime29){
Pulses29=CurrentTime29-StartTime29;
StartTime29=CurrentTime29;
}}
void PulseTimer31(){
CurrentTime31=micros();
if (CurrentTime31 > StartTime31){
Pulses31=CurrentTime31-StartTime31;
StartTime31=CurrentTime31;
}}
void PulseTimer33(){
CurrentTime33=micros();
if (CurrentTime33 > StartTime33){
Pulses33=CurrentTime33-StartTime33;
StartTime33=CurrentTime33;
}}
Une section critique est une partie du code principal où vous touchez des variables partagées avec les fonctions d’interruption
Ce morceau de code doit être traité de manière atomique, en etant sûr que vous ne serez pas interrompu pendant cette exécution. Sur AVR vous pouvez par exemple suspendre les interruptions temporairement pour faire une copie des variables critiques et éventuellement les modifier puis les réactiver et utiliser la copie pour l’affichage ou les calculs.
Sur plateformes plus complexes comme un ESP32 il faut jouer avec des sémaphores / mutex.