IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Interruption déclenchée à chaque lancement de l'interrupt sur Nano


Sujet :

Arduino

  1. #1
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut Interruption déclenchée à chaque lancement de l'interrupt sur Nano
    Bonjour à tous

    je me suis rendu compte que dès le setup lorsque j'appelle attachInterrupt(0,switchOFDetected,FALLING);, une interruption est déclenchée.
    Puis dans mon programme j'utilise detachInterrupt(0);.
    Alors, dès que je réactive l'interruption, une interruption est à nouveau détectée.
    Je ne pense pas que ce phénomène soit normal.

  2. #2
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonjour mormic

    As-tu bien initialisé l'entrée en , INPUT_PULLUP?
    Une entrée "en l'air" peut déclencher l'interrupt à tout moments.

    Cordialement
    jpbbricole

  3. #3
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Bonjour jpbbricole

    Oui voilà mon setup:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void setup() {
      //Serial.begin(9600);
      pinMode(LEDPIN,OUTPUT);
      pinMode(OPIN,OUTPUT);             //commande de relais d'ouverture
      pinMode(FPIN,OUTPUT);             //commande le relais de fermeture
      pinMode(OFSWPIN, INPUT_PULLUP);    //poussoir ouverture manuelle
     
     attachInterrupt(0,switchOFDetected,FALLING);
    }

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour à tous

    C'est un problème classique et expliqué dans la docs des AVR.
    En programmation AVR, il faut effacer un flag (par sécurité) avant d'autoriser à nouveau les interruptions. Ne pas effacer le flag permet d'avoir un comportement, souhaité selon les cas, d'une suspension de l'interruption (si une est arrivée pendant la désactivation, elle s'exécute à l'autorisation).

    En programmation Arduino, je m'attendrais à ce que cela soit fait d'office, mais je n'en sais pas plus.

    PS: La suspension des interruptions c'est pratique quand on veut qu'une partie critique du code ne soit pas coupée par une interruption. Cela ne fait sens que lorsque cette partie critique est courte.

    Delias

  5. #5
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonjour mormic

    Sur quelle pin est ton interrupt (OFSWPIN)?
    Utilises cette syntaxe pour attacher ton interrupt:
    attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) (recommended)

    Cordialement
    jpbbricole

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour

    Avant le message de jpbbricole, je n'avais pas fait attention que Arduino utilise directement la syntaxe AVR pour la gestion des interruptions.

    Si tu veux supprimer le problème il faut ajouter cette ligne de code avant de réactiver l'interruption. Il est possible d'avoir cette ligne de code aussi avant la première activation, il y a moins de coût en temps d'exécution et en mémoire de la laisser que de faire un test.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EIFR &= ~(_bv(x)); // supprime interruption en attente sur INT0 (patte Arduino 2) ou INT1 (patte Arduino 3)
    Avec x qui vaut 0 pour l'interruption de la patte Arduino 2 et x qui vaut 1 pour l'interruption de la patte Arduino 3.

    Si on veut faire le reset sur les deux interruptions on peut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EIFR = $00; // supprime interruption en attente sur INT0 (patte Arduino 2) et INT1 (patte Arduino 3)
    J'utilise la variante d'écriture en hexadecimal car je travail sur des bits (petite convention de codage personnelle)

    Delias

  7. #7
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Merci Delias pour cette info.
    S'agit-il du bit6 (INTF0 dans mon cas) du registre GIFR que je doit remettre à zéro dès que la routine d'interruption est entrée?
    Que font les routines cli() et sei()?
    EIFR &= ~(_bv(0)); Que veut dire _bv ?

    Ok j'ai trouvé _bv c'est l'acronyme de BitValue. Mais traduit en langage Arduino, qu'est-ce que ça donne?

  8. #8
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour Mormic

    Pour paramétrer et gérer une interruption, il y a 5 étapes. Par simplification, je vais indiquer les registres utilisés par INT0.

    La première c'est d'activer les aiguillages (multiplexeurs) qui détectent une interruption. C'est EICRA bits ISC00 et ISC01.
    Dès que cela est fait, lorsque la condition pour activer une interruption est présente, il y a un set (passage à 1) du Flag de l'interruption correspondante, le flag est le registre EIFR bit INTF0.
    C'est bien le INTF0 du registre EIFR (tu as écrit GIFR que je ne trouve pas dans la doc du ATMEGA328) Ce flag est remis à 0 matériellement lors du lancement de l'interruption. Pas besoin de le faire à l'entrée dans la fonction d'interruption. C'est à faire uniquement avant la réactivation d'un masque (étape suivante) pour ignorer les interruptions arrivées pendant que le masque était désactivé. Cela peut aussi être fait en fin d'interruption pour ignorer une deuxième activation de l'interruption si la condition d'activation peut se présenter plusieurs fois dans un délai inférieur à celui du traitement. On peut par exemple l'utiliser comme anti-rebond sur l'interruption de changement de niveau si la durée du traitement de l'interruption correspond à la pause nécessaire au fonctionnement de l'anti-rebond.

    Il y a ensuite deux niveaux de masque, un bit par interruption permettant de bloquer l'interruption correspondante, c'est EIMSK bit INT0. Mais cela n'empêche pas au flag de passer à 1 si la condition d'interruption est remplie.
    Le deuxième niveau est général, c'est le Flag I de l'ALU que l'on peut activer et désactiver par sei() et cli(). Ce n'est qu'un masque qui empêche le démarrage des interruptions, mais, à nouveau, cela n'empêche pas aux flags des interruptions de passer à 1.

    Le dernier point c'est le vecteur d'interruption qui est la définition de la fonction qui doit être appelée lors d'une interruption.


    _BV est juste une macro qui fait 1<<x et donc _BV(0) équivaut à 0b00000001 et _BV(1) équivaut à 0b00000010. En Arduino ce serait bit();. Dommage d'utiliser une fonction quand une macro fait l'affaire, l'optimisation de compilation est moins bonne.

    Pour être encore plus strict j'aurais dû écrire EIFR &= ~(_BV(INTF0));, mais j'ai toujours de la peine à utiliser les noms des bits (et les macros en majuscules).

    Delias

  9. #9
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Citation Envoyé par mormic Voir le message
    S'agit-il du bit6 (INTF0 dans mon cas) du registre GIFR
    Ça c'est pour les ATTiny85 (et probablement d'autres petits ATTiny) qui sont rependus chez les utilisateurs d'Arduino comme puce minimaliste.
    Mais ce n'est pas valable pour les ATMega qui équipent les vrai Arduino (Uno, Nano, Mega, Leonardo, etc.)

    Delias

  10. #10
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Bonjour
    J'ai bien un Arduino Uno équipé d'un ATMega
    Je n'arrive pas à m'en sortir malgré les bons conseils de Delias
    Je viens de faire un petit prog d'essai que j'indique ci-après. ****Désolé je n'ai plus les balises d'affichées****
    Le résultat est : chaque fois que je lance l'interruption, soit au début, soit après avoir appuyé sur sw le compteur s'incrémente !
    0 au départ puis 1 à la première boucle, puis chaque fois que j'appuie sur sw incrémentation de 2.
    Est-ce mon prog qui est stupide ou y-a-t'il vraiment un bug?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    #define swPin 2
    uint8_t i=0;
    bool interruptOn=false;
     
    void gestionInterrupt(){
      detachInterrupt(0);
      delay(400);
      i++;
      interruptOn=false;
    }
     
    void setup(){
      Serial.begin(9600);
      Serial.print("SetUp "); Serial.println(i); 
      pinMode(swPin,INPUT_PULLUP);  
    }
     
    void loop(){
      Serial.println(i);   
      delay(1000);
      if(!interruptOn){
        EIFR &= ~(bit(INTF0)); // supprime interruptions en attente sur INT0 
        attachInterrupt(0,gestionInterrupt,FALLING);
        interruptOn=true;
      }
    }

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour mormic

    Il manque à minimum cela:
    Citation Envoyé par jpbbricole Voir le message
    As-tu bien initialisé l'entrée en , INPUT_PULLUP?
    Une entrée "en l'air" peut déclencher l'interrupt à tout moments.
    Dans le setup()(honneur à celui qui l'a indiqué en premier)

    Ensuite les variables utilisées dans l'interruption doivent être déclarée avec le mot clé volatile pour éviter les problèmes suite aux optimisations du compilateur.

    Delai(); ne fonctionne pas dans les interruptions (mais c'est bizarre tu devrais avoir un freeze de l'AVR pas un comptage)

    Je ne suis pas certain que le detachInterrupt() utilisé dans l'interruption ne provoque pas de comportement non souhaité voir aléatoire. J'ai été voir le code Arduino, à priori pas.

    Delias

  12. #12
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Je vais devenir fou. Je suis passé sur un Arduino Uno pour lever le doute. j'ai recompilé un petit prog en apportant quelques modifs mais c'est toujours bizarre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    #define swPin 2
    volatile uint8_t i=0;
    volatile bool interruptOn=false;
     
    void delai(unsigned long t){
      unsigned long deb = millis();
      while(1){
        if(millis() - deb >= t) break;
      }
    }
     
    void gestionInterrupt(){
      interruptOn=true;
    }
     
    void action(){ 
      delai(500);
      i++;
      Serial.print("Inter "); Serial.println(i);
      interruptOn=false;
      delai(1000); 
      EIFR &= ~(bit(INTF0)); // supprime interruptions en attente sur INT0 
      attachInterrupt(0,gestionInterrupt,FALLING); 
    }
     
    void setup(){
      Serial.begin(9600);
      pinMode(swPin,INPUT_PULLUP);
      attachInterrupt(0,gestionInterrupt,FALLING); 
      Serial.print("SetUp "); Serial.println(i); 
    }
     
    void loop(){
      do{
      }while(!interruptOn);
      detachInterrupt(0);
      action();
    }
    Affichage: "SetUp 0" puis attente appui sur sw "Inter 1" attente 1 seconde "Inter 2" puis attente..
    Et systématiquement lorsque j'appui sur sw 2 interrupt semblent se déclencher ???

    Je ne sais plus par quel bout solutionner ce pb.

    Le fait de supprimer EIFR &= ~(bit(INTF0)); ne change rien

  13. #13
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour

    J'aimerais voir s'il n'y a pas une erreur dans la lib Arduino.
    Est-ce que tu peux essayer de remplacer les lignes 23 et 24 par les trois variantes suivantes (sans autre modification de ton code):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    EIFR &= ~(1<<INTF0);
    EIMSK |= 1<<INT0;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    EICRA = (1<<ISC01);
    EIFR &= ~(1<<INTF0);
    EIMSK |= 1<<INT0;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    EIFR &= ~(1<<INTF0);
    EICRA = (1<<ISC01);
    EIMSK |= 1<<INT0;
    Si cela fonctionne dans le deux premiers cas mais pas dans le 3ème, c'est la lib Arduino qui ne respecte pas une recommandation de codage de la doc AVR (qui était présente pour les anciennes puces)
    Mélanger les fonctions Arduino et l'accès aux registres ce n'est pas top. C'est plus pour chercher la raison du problème.

    Attention également: Registre &= ~(_BV(numbit)); et Registre &= ~(1<<numbit); fonctionnent, mais Registre &= ~(bit(numbit)); peut ne pas fonctionner, c'est lié à ce que l'on cherche à utiliser une optimisation bien précise du compilateur qui n'est possible que si la partie de droite est sur 8 bits, constante et avec un seul 0. En utilisant une fonction, ce contrôle par le compilateur peut ne pas fonctionner (la partie de droite est détectée comme variable) et provoquer un résultat inattendu.
    C'est pareil pour l'instruction inverse Registre |= _BV(numbit); et Registre |= 1<<numbit;.

    Delias

    [Edit] Petite erreur de ma part, je réactivais l’interruption sur le flan montant, j'avais lu la doc trop vite. Corrigé ici

  14. #14
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Bonsoir Delias
    les trois solutions ne fonctionne qu'une fois, c'est à dire que: j'appui sur sw , je passe par action() puis les appuis suivants ne sont pas détectés.

    J'ai corrigé la ligne 23 d'origine par EIFR &= ~(1<<0); Je retrouve le même fonctionnement précédent, c'est à dire pour un appui j'ai 2 détections mais parfois j'en ai qu'une. Là c'est peut-être l'anti-rebond qui n'est pas bon ?

  15. #15
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour

    Il faudrait partir d'un programme simple, modifier une seule chose à la fois pour voir où cela merde.

    De base ce serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    #define swPin 2
    #define LedPin 13
    volatile uint8_t i=0;
     
    void gestionInterrupt(){
      i++;
    }
     
    void setup(){
      Serial.begin(9600);
      pinMode(swPin, INPUT_PULLUP);
      pinMode(LedPin, OUTPUT);
      Serial.print("SetUp "); Serial.println(i); 
    }
     
    void loop(){
      attachInterrupt(0,gestionInterrupt,FALLING); 
      digitalWrite(LedPin, HIGH);
      Serial.print("interrupt ON "); Serial.println(i);
      delay(1000);
      detachInterrupt(0);
      digitalWrite(LedPin, LOW);
      Serial.print("interrupt OFF "); Serial.println(i);
      delay(1000);
    }
    Avec ce code i ne doit progresser que lors que la led est alumée et que tu presses le bouton.
    Il sera intéressant de voir la progression de i sans action de ta part pour faire la suite.

    pour l'étape suivante, il est possible de définir la pin 2 en sortie et de commander sa commutation par le code, cela permet de générer un signal très propre pour déclencher l'interruption. Et de vérifier que l'on a une progression propre. Attention pas d'action sur le bouton poussoir dans ce cas !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    void setup(){
      Serial.begin(9600);
      pinMode(swPin, OUTPUT);
      pinMode(LedPin, OUTPUT);
      Serial.print("SetUp "); Serial.println(i); 
    }
     
    void loop(){
      attachInterrupt(0,gestionInterrupt,FALLING); 
      digitalWrite(LedPin, HIGH);
      Serial.print("interrupt ON "); Serial.println(i);
      delay(400);
      digitalWrite(swPin, HIGH);
      delay(100);
      digitalWrite(swPin, LOW);
      delay(500);
      detachInterrupt(0);
      digitalWrite(LedPin, LOW);
      Serial.print("interrupt OFF "); Serial.println(i);
      delay(400);
      digitalWrite(swPin, HIGH);
      delay(100);
      digitalWrite(swPin, LOW);
      delay(500);
    }
    Avec ce code la sortie devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    interrupt ON 0
    interrupt OFF 1 
    interrupt ON 1
    interrupt OFF 2
    ...

    Après ajout d'un délai dans l'interruption, anti-rebond, le detachInterrupt dans le code de l'interruption etc.
    A chaque fois, faire un minimum de changement et valider que cela fonctionne.

    Pour la suite on peut mettre des digitalWrite(swPin, HIGH); digitalWrite(swPin, LOW); un peu partout dans le code, pour simuler les différents moments. Y compris en entrée, milieu et juste avant la sortie du code de l'interruption. Pas forcement besoin de mettre un délai entre les deux, les deux fonctions prennent déjà assez de temps pour être exécutées.

    delay() ne fonctionne pas et millis() ne progresse pas dans le code d'une interruption. Ce n'est pas utilisable pour mettre un délai dans le code d'une interruption.
    Il y a la fonction _delay_ms() de la bibliothèque AVR <util/delay.h> qui permet de le faire. Je ne sais pas dans quelle mesure c'est intégrable dans un programme Arduino (cela devrait être le cas car Arduino s'appuie sur AVR).

    Delias

    PS: comme d'habitude pour ma part, code fait à la volée, sans garantie d'une petite erreur ici ou là.

  16. #16
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Le premier sketch fonctionne correctement sauf bien sûr qu'il n'y a pas d'anti-rebonds.
    Le deuxième est intéressant car on obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SetUp 0
    interrupt ON 1
    interrupt OFF 2
    interrupt ON 3
    interrupt OFF 4
    interrupt ON 5
    interrupt OFF 6
    interrupt ON 7
    interrupt OFF 8
    interrupt ON 9
    interrupt OFF 10
    interrupt ON 11
    interrupt OFF 12
    sachant qu'au premier ON le compteur i devrait toujours être à 0. J'ai l'impression que le fait de faire attachInterrupt déclenche une interruption!
    J'ai essayé de prépositionner sw HIGH dans le setup mais rien n'a changé.

  17. #17
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 277
    Par défaut
    Bonjour

    Le premier Sketch, oui et? est-ce que les nombres après un interrupt OFF et l'interrupt ON qui suit sont identiques quand tu n'appuies pas sur le bouton? Si tu appuies au moment où la Led s'allume c'est possible qu'il y aie une incrémentation (car il faut quelques cycles entre l'activation de l'interruption et l'envoi de i).
    Pour le deuxième Sketch, c'est donc à simplifier pour isoler le problème: plus de digitalWrite(swPin, xxx); dans le loop(), uniquement un digitalWrite(swPin, LOW); dans le setup() après le choix en mode sortie.

    Delias

  18. #18
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Pour le premier sketch oui le nombre reste le même entre OFF et ON.

    Pour le deuxième sketch sans les swPin HIGH/LOW dans la loop voilà le résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    SetUp 0
    interrupt ON 0
    interrupt OFF 0
    interrupt ON 0
    interrupt OFF 0
    interrupt ON 0
    interrupt OFF 0    //appui pendant led OFF
    interrupt ON 1
    interrupt OFF 1
    interrupt ON 1
    interrupt OFF 1
    interrupt ON 1
    interrupt OFF 1
    interrupt ON 2
    interrupt OFF 2
    interrupt ON 2
    interrupt OFF 15          //appui pendant led ON
    interrupt ON 15
    interrupt OFF 15
    interrupt ON 15
    interrupt OFF 20
    interrupt ON 20
    interrupt OFF 20
    interrupt ON 20
    interrupt OFF 20
    interrupt ON 20
    interrupt OFF 20
    interrupt ON 20
    Donc si j'appui entre detachInterrupt(0) et attachInterrupt(0,gestionInterrupt, FALLING) il y a une seule interruption détectée; dans le cas contraire, sans anti-rebonds, il y a une salve de détections.

    *****je rectifie ma réponse car ce qui précède correspondait à un swPin HIGH dans le setup
    Si je mets swPin LOW dans le setup plus aucune interruption n'est détectée.

  19. #19
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    J'ai refait un nouvel essai ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include <util/delay.h>
    #define swPin 2
    #define LedPin 13
    volatile uint8_t i=0;
    volatile bool interOn=false;
     
    void gestionInterrupt(){
      detachInterrupt(0);
      i++;
      interOn=true;
    }
     
    void setup(){
      Serial.begin(9600);
      pinMode(swPin,INPUT_PULLUP);
      attachInterrupt(0,gestionInterrupt,FALLING); 
      pinMode(LedPin, OUTPUT);
      Serial.print("SetUp "); Serial.println(i); 
    }
     
    void loop(){
      if(interOn) {
        _delay_ms(500);   
        digitalWrite(LedPin, HIGH);
        Serial.print("interrupt ON "); Serial.println(i);
        interOn=false;
        attachInterrupt(0,gestionInterrupt,FALLING);              //sera supprimé au deuxième essai
        _delay_ms(500);
      }
      digitalWrite(LedPin, LOW);
      Serial.print("interrupt OFF "); Serial.println(i);
      _delay_ms(500);
    }
    résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    SetUp 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt ON 1
    interrupt OFF 2
    interrupt ON 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt ON 3
    interrupt OFF 4
    interrupt ON 4
    interrupt OFF 4
    interrupt OFF 4
    interrupt OFF 4
    interrupt OFF 4
    interrupt OFF 4
    interrupt OFF 4
    interrupt OFF 4
    Chaque appui est bien détecté mais une interruption supplémentaire est comptabilisée en sortie du 'if'

    J'ai fait un nouvel essai en supprimant attachInterrupt dans le if, c'est à dire que je ne relance pas l'interruption après une 1ère détection.
    Résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    SetUp 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt ON 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    Bien sûr il n'y a qu'une détection mais en sortie du 1er if il n'y a pas de deuxième détection!
    Je ne sais plus comment m'y prendre.

  20. #20
    Membre éclairé
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 406
    Par défaut
    Cher Delias je viens de faire une petite modif:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     void loop(){
      if(interOn) {
        _delay_ms(500);   
        digitalWrite(LedPin, HIGH);
        Serial.print("interrupt ON "); Serial.println(i);
        interOn=false;
        EIMSK |= 1<<INT0;
        attachInterrupt(0,gestionInterrupt,FALLING); 
        _delay_ms(500);
      }
      digitalWrite(LedPin, LOW);
      Serial.print("interrupt OFF "); Serial.println(i);
      _delay_ms(500);
    }
    Résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    SetUp 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt OFF 0
    interrupt ON 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt OFF 1
    interrupt ON 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt OFF 2
    interrupt ON 3
    interrupt OFF 3
    interrupt OFF 3
    interrupt OFF 3
    interrupt OFF 3
    interrupt OFF 3
    Et là ça a l'air de fonctionner parfaitement. Que penses-tu de cette solution ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Utilisation du mode Wait For Interrupt sur STM8L151G6
    Par wiloui dans le forum Embarqué
    Réponses: 2
    Dernier message: 27/06/2014, 20h02
  2. [16f84] Aide pour une interruption sur port B
    Par spedy dans le forum Autres architectures
    Réponses: 3
    Dernier message: 12/09/2011, 18h08
  3. Problème d'interruption sur PIC16F877
    Par fidchell456 dans le forum C
    Réponses: 3
    Dernier message: 22/06/2010, 10h08
  4. Interruption sur RB0 [langage C]
    Par jorg1n dans le forum C
    Réponses: 11
    Dernier message: 28/02/2008, 16h57
  5. Interruption sur port série
    Par psl dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 15/06/2007, 20h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo