Interruptions ext

Bonsoir à tous, J'ai besoin de compter les impulsions générées par l'encodeur de mon portail coulissant. Il s'agit d'un capteur à effet hall qui délivre des crénaux de 5vcc.

J'ai donc recopié un scketch classique et je teste en mettant la pin 2 à la masse manuellement. (Pull-up 10k sur pin2) Il va sans dire que ce n'est pas du créneau propre mais des impulsions avec probablement de multiples rebonds.

Le programme fonctionne si je ne renvoie pas sur le moniteur série. Si je veux voir apparaitre le comptage avec : Serial.println(comptImpuls); suivant les cas j'arrive à afficher quatre cinq lignes, parfois plus de cent et régulièrement le programme plante et ne compte plus les interruptions. Quelqu'un pourrait il m'éclaircir les idées à ce sujet, merci

int pin = 13;
volatile int  state = LOW; // déclartion d'une variable volatile
volatile int comptImpuls=0;
void setup()
{
  Serial.begin(115200);
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, CHANGE); // attache l'interruption externe n°0 à la fonction blink
}

void loop()
{
  digitalWrite(pin, state); // la LED reflète l'état de la variable
}

void blink() // la fonction appelée par l'interruption externe n°0
{
  state = !state; // inverse l'état de la variable
  comptImpuls=comptImpuls+1;
 Serial.print("Nbre impulsions = ");
  Serial.println(comptImpuls);
}

Pas de Serial.print dans les fonctions sous interruption. Une fonction de traitement d'interruption doit être courte. Pendant la fonction de traitement d'interruption, certaines interruptions sont masquées. Serial utilise les interruptions. Donc cela peut poser problème.

La solution Faire le comptage dans la fonction de traitement d'interruption Faire le print dans loop Pour ça, déclarer en global deux variables en volatil: la variable de comptage et un drapeau et les initialiser à 0. Dans la fonction de traitement de l'IT on incrémente le compteur et on positionne le drapeau à 1. Dans loop, on teste si le drapeau est à 1. Si c'est le cas faire un Serial.print de la valeur de comptage et remettre à zéro le drapeau. Avec cette solution, à l'affichage on peut manquer des valeurs mais le compteur devrait tourner rond.

Merci fdufnews,
Je me doutais de quelque chose comme ça ; je suis passé aux essais, ça fonctionne au top.
Mais
Est-il possible d’utiliser simultanément une IT interne déclanchée par un registre compteur afin d’alimenter un clignotant par ex. ?

La contrainte de faire des routine de traitement des interruptions courtes c'est justement pour ne pas perturber d'autres fonctionalités. Pour faire un clignotant, tu peux utiliser millis() directement dans loop.

J'ai lu qu'il y avait incompatibilité entre les IT et millis ou delay du fait que durant l'IT et son traitement millis est en standby.

jpjcb66: J'ai lu qu'il y avait incompatibilité entre les IT et millis ou delay du fait que durant l'IT et son traitement millis est en standby.

Il ne faut pas utiliser milis() à l'intérieur de la routine de traitement d'IT car millis() n'incrémente plus. Si la routine de traitement est courte (une incrémentation + le positionnement d'une variable ne prend vraiment pas beaucoup de temps) vu de l'extérieur le fonctionnement de millis() n'est pas perturbé.

Ok fdufnews, Je viens de tester ça en imbriquant du code dans void loop pour faire clignotter la LED de la pin 13 grace à l'instruction millis. Ca fonctionne impeccable. Donc encore merci pour les infos, la réactivité et la gentillesse. Belle communauté. JP