Partage
  • Partager sur Facebook
  • Partager sur Twitter

Arduino - attachinterrupt et variables multiples

    14 septembre 2017 à 19:38:04

    Salut à tous,

    je debute et je parcours les cours et les forums pour trouver la reponse à ma solution, en vain, je ne trouve pas mon exemple dans les differentes realisations

    j'ai un petit programme qui utilise l'attachinterrupt, jusque là tout va presque bien

    j'ai un arbre tournant qui à chaque tour complet donne 4 impulsions HIGH et 4 LOW pour un tour complet de l'arbre.

    Ces 8 impulsions doivent etres separées car elles ont des valeurs differentes.

    et je souhaite que le temps de chaque HIGH et chaque LOW soit stocké dans des variables differentes.

    c'est là que je peche .... l'attachinterrupt est à peu pres clair pour moi, mais il me manque la façon de coder pour prendre à la suite chaque CHANGE

    Attachinterrupt(pin, val, CHANGE)

    void loop(){

    serial.println(var 1);

    serial.println(var 2);

    etc

    }

    void val()

    var 1 = temps HIGH

    var 2 = temps LOW

    var 3 = temps HIGH

    ....

    var 8 = temps LOW

    }

    puis on repart pour un tour

    ce qui est milli() et le reste ça va pour stocker un HIGH ou un LOW, mais les 8 à la suite c'est plus compliqué :(

    vous pourriez m'aider à coder les 8 variables qui stockeront le temps des 8 CHANGE sur un tour?

    merci d'avance !

    -
    Edité par OilgustBora 14 septembre 2017 à 19:43:33

    • Partager sur Facebook
    • Partager sur Twitter
      14 septembre 2017 à 21:03:16

      La première chose à faire serait de calculer le temps qui s'est écoulé depuis le dernier appel à attachInterrupt.

      Pour ça, tu as millis avec une petite soustraction qui fait ça très bien.

      unsigned long lastTime = 0;
      
      void myIRQ(void) {
      
          unsigned long currentTime, elaspsedTime;
          
          currentTime = millis();
          elaspsedTime = ( currentTime - lastTime );
          lastTime = currentTime;
      
      }

      Il te faudra aussi gérer un compteur, qui compte le nombre de fois ou ton interruption a été appelé.

      Ce compteur ira de 0 à 7 soit 8 valeurs distinct, une pour chaque pulse.

      unsigned long lastTime = 0;
      unsigned char counterIdx = 0;
      
      void myIRQ(void) {
      
          unsigned long currentTime, elaspsedTime;
          
          currentTime = millis();
          elaspsedTime = ( currentTime - lastTime );
          lastTime = currentTime;
      
          counterIdx++;
          if ( counterIdx >= 8 ) {
              counterIdx = 0;
          }
      
      }

      ET pour finir, tu peux parfaitement te servir de cet index compteur pour remplir un tableau contenant les 8 temps.

      unsigned long lastTime = 0;
      unsigned char counterIdx = 0;
      unsigned long elapsedTimeArray[8];
      
      void myIRQ(void) {
      
          unsigned long currentTime, elaspsedTime;
          
          currentTime = millis();
          elaspsedTime = ( currentTime - lastTime );
          lastTime = currentTime;
      
          elapsedTimeArray[counterIdx] = elaspsedTime;
      
          counterIdx++;
          if ( counterIdx >= 8 ) {
              counterIdx = 0;
          }
      
      }



      -
      Edité par lorrio 14 septembre 2017 à 21:05:18

      • Partager sur Facebook
      • Partager sur Twitter
        14 septembre 2017 à 21:31:52

        punaise, super

        et j'etais certain qu'un tableau pouvait remplir cette fonction

        j'etais pas loin, suis content ;)

        je vais donc continuer d'etudier les tableaux, et egalement revenir sur le millis() car ta formule n'est finalement pas si clair pour moi :/

        ça parait super simple comme ça mais je ne comprend pas encore tout, je vais relire ton post plusieurs fois, merci d'avoir decomposé

        mon programme d'origine (que j'ai fait tout seul) utilisait des pulsIn, il semble fonctionner mais à priori pourrait poser des problemes => toutes les impulsions pourraient ne pas être prise en compte contrairement à l'attachinterrupt

        donc je tente de l'adapter

        je suis très très débutant, j'ai un besoin qui "m'oblige" à apprendre le langage arduino, mais j'adore ça

        merci !!!

        • Partager sur Facebook
        • Partager sur Twitter
          15 septembre 2017 à 8:29:58

          La fonction millis te donne le nombre de millis seconde écoulé (depuis le lancement du programme) au moment où tu l'appel.

          Dans la fonction interrupt, je finis par sauvegarder cette valeur dans la variable lastTime.

          Ainsi, la variable lastTime contient le nombre de millis seconde qui s'était écoulé lorsque la fonction interrupt a été appelé.

          Puis lorsque celle-ci est à nouveau appelée, je fais un appel à millis qui sauvegarde la valeur dans variable currentTime.

          Du coup, je me retrouve avec :

          • La variable lastTime qui contient le nombre de ms écoulé au précédant appelé de interrupt
          • La variable currentTime qui contient le nombre de ms écoulé pour l'appel actuel de interrupt

          Pour connaitre le temps écoulé entre ces 2 appels, il suffit simplement de faire la soustraction entre ces 2 variables.

          C'est d'ailleurs ce que je fais avec elaspsedTime = ( currentTime - lastTime );

          • Partager sur Facebook
          • Partager sur Twitter
            15 septembre 2017 à 19:51:01

            ah genial ! meme pas eu le temps de m'y pencher que j'ai deja l'explication !

            c'est sympas, en fait je ne serais pas parti dans la bonne direction pour la comprehension .... allé, je continue de gratter ce sujet ;)

            -
            Edité par OilgustBora 16 septembre 2017 à 20:50:20

            • Partager sur Facebook
            • Partager sur Twitter
              16 septembre 2017 à 19:55:18

              ok, donc si je comprend bien :

              la fonction milli() est stoppée par les interruptions.

              à chaque interruption la fonction milli() renvoie le temps écoulé entre le début du programme et l'interruption

              pour la 1ere interruption lastTime = 0 et currentTime = 10s (admettons)

              donc elapsedTime = 10s et lastTime =10s  (car repris de currentTime)

              pour la 2eme interruption lastTime =10s et currentTime = 13s

              donc elapsedTime = 3s et lastTime =13s

              pour la 3eme interruption lastTime =13s et currentTime = 16s

              donc elapsedTime = 3s et lastTime =16s

              c'est bien ça ? suis obligé de decomposer ainsi pour tenter de comprendre correctement ;)

              la 1ere interruption n'est pas exoploitablecar tout depend quand elle à eu lieu apres le demarrage du programme, c'est correct ?

              si oui les x milliers interruptions suivantes seront regulieres, donc exploitables

              • Partager sur Facebook
              • Partager sur Twitter
                17 septembre 2017 à 18:00:46

                La fonction millis renvoie le nombre de ms écoulé entre le moment où tu l'appel et le dépend du programme.

                Du coup, ta décomposition est correct ;)

                La première interruption donnera effectivement quelque chose de difficilement exploitable mais ce n'est pas bien dérangeant ;)

                Si tu tiens absolument à avoir quelque chose d'exploitable pour chaque appel, alors tu pourrais ajouter un boucle dans le setup qui attend le premier changement d'état avant d'activer l'interruption.

                • Partager sur Facebook
                • Partager sur Twitter
                  17 septembre 2017 à 19:11:48

                  un grand merci, j'ai enfin compris le role de cette fonction, c'est tout simple au final, mais sans la bonne explication c'est toujours plus laborieux

                  j'ai commandé un starter kit pour faire tous les exercices sur l'arduino, ça ma bloque un peu car je souhaite voir l'histoire du tableau en détail, et le cours sur les led semble pas mal et surtout apprendre comment nommer et rappeler les variables stockées dans un tableau, d'ailleur voici mon programme original

                  Il fonctionne, je l'ai testé, il donne de bons resultats, mais il pourrait ne pas "capter" tous les pulseIn d'apres ce que l'on m'a dit

                  d'ailleur, tu en penses quoi ?

                  Preuve ci-dessous que je dois conserver chaque variable de temps et le rappeler car je convertis 4 impulsions en angle après mes 8 impulsions

                  d'ailleurs je viens de m'apercevoir (à force d'apprendre) que le if (buttonState != lastButtonState) ne sert à rien dans mon programme ....

                  merci

                  const byte PIN_SIGNAL = 2;
                  int buttonState = 0;
                  int lastButtonState = 0;
                  long temps_total = 0;
                  int angle2 = 0;
                  int angle4 = 0;
                  int angle6 = 0;
                  int angle8 = 0;
                  const int angle_total = 360;
                  long p1 = 0;
                  long p2 = 0;
                  long p3 = 0;
                  long p4 = 0;
                  long p5 = 0;
                  long p6 = 0;
                  long p7 = 0;
                  long p8 = 0;
                  
                  /** Fonction setup() */
                  void setup() {
                      /* Initialise le port série */
                    Serial.begin(115200);
                      /* Met la broche en sortie */  
                    pinMode(PIN_SIGNAL, OUTPUT);
                  }
                  
                  
                  /** Fonction loop() */
                  void loop() {
                   // lit l'état actuel du bouton poussoir et le mémorise dans la variable
                    buttonState = digitalRead(PIN_SIGNAL);
                    // compare l'état actuel du bouton poussoir à l'état précédent mémorisé
                    if (buttonState != lastButtonState) {  
                    /* Mesure la durée de la période */
                  p1 = pulseIn(PIN_SIGNAL, LOW);
                  //  Serial.print("p1: ");
                       //  Serial.println(p1);
                         
                      if (buttonState != lastButtonState){
                  p2 = pulseIn(PIN_SIGNAL, HIGH);
                     //  Serial.print("p2: ");
                    // Serial.println(p2);
                    }
                      
                         if (buttonState != lastButtonState){
                      p3 = pulseIn(PIN_SIGNAL, LOW);
                    //   Serial.print("p3: ");
                    //  Serial.println(p3);
                    }
                      
                         if (buttonState != lastButtonState){
                      p4 = pulseIn(PIN_SIGNAL, HIGH);
                    //   Serial.print("p4: ");
                    //  Serial.println(p4);
                    }
                      
                       if (buttonState != lastButtonState){
                    p5 = pulseIn(PIN_SIGNAL, LOW);
                     //  Serial.print("p5: ");
                    //  Serial.println(p5);
                    }
                      
                       if (buttonState != lastButtonState){
                    p6 = pulseIn(PIN_SIGNAL, HIGH);
                      // Serial.print("p6: ");
                    //  Serial.println(p6);
                    }
                      
                       if (buttonState != lastButtonState){
                    p7 = pulseIn(PIN_SIGNAL, LOW);
                      // Serial.print("p7: ");
                      //Serial.println(p7);
                      }
                      
                       if (buttonState != lastButtonState){
                     p8 = pulseIn(PIN_SIGNAL, HIGH);
                      // Serial.print("p8: ");
                     // Serial.println(p8);
                     }
                      
                      // affiche le temps total
                     temps_total = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8;
                    // Serial.print("temps total: ");
                         // Serial.println(temps_total);
                          
                      // affiche l'angle inter fermé
                        angle2 = (p2 * angle_total) / (temps_total) ;
                        Serial.print("angle 2: ");
                          Serial.println(angle2);
                  
                           // affiche l'angle inter fermé
                        angle4 = (p4 * angle_total) / (temps_total) ;
                        Serial.print("angle 4: ");
                          Serial.println(angle4);
                  
                           // affiche l'angle inter fermé
                        angle6 = (p6 * angle_total) / (temps_total) ;
                        Serial.print("angle 6: ");
                          Serial.println(angle6);
                  
                           // affiche l'angle inter fermé
                        angle8 = (p8 * angle_total) / (temps_total) ;
                        Serial.print("angle 8: ");
                          Serial.println(angle8);
                        }
                       }
                     
                     
                   
                  
                  
                  



                  -
                  Edité par OilgustBora 17 septembre 2017 à 19:13:11

                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 septembre 2017 à 19:22:25

                    Oui, je confirme, ta variable lastState ne sert à rien puisque tu l'initialise à 0 au début puis tu ne changes plus jamais son état.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 septembre 2017 à 14:09:14

                      et tu penses quoi des pulsIn ? et de mon petit programme ? :)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        18 septembre 2017 à 14:42:57

                        C'est fonctionnel à condition que tu n'ai rien d'autre à faire...

                        En effet, la fonction pulseIn est bloquante de façon à ce que l'arduino attende le pulse avant de noter le temps écoulé.

                        Pendant que ton arduino est en train de faire ses appels à pulseIn, il ne fait rien d'autre.

                        Du coup, si tu veux ajouter des boutons, des LEDs ou un petit écran à ton projet, ça risque d'être compliqué parce que l'arduino ne pourra les gérer que pendant qu'il n'est pas en train de faire des appels à pulseIn.

                        Au final, si ton arbre tourne en permanence, ton arduino ne pourra jamais gérer les autres éléments du projet.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 septembre 2017 à 14:54:00

                          ah, enfin une reponse claire !

                          ailleurs (sans dénigrer aucunement) on ne m'a pas expliqué pourquoi

                          • Partager sur Facebook
                          • Partager sur Twitter
                            29 janvier 2018 à 11:22:46

                            Salut à tous,
                            me revoici après une longue pause afin de terminer d'autres projets.
                            je me suis fait un montage complet avec un moteur d’essuie glace, une carte de puissance sabertooth 2x12 et le filtre donné sur un autre forum posts.
                            Rappel, une came tournante, 4 impulsions montantes, 4 descendantes, je ne veux compter que l'une d'entre elle afin de créer (dans un premier temps) un compte tour.
                            Mon programme fonctionne sur le principe MAIS quand tout ça est en rotation le compteur n'est pas stable du tout, le RPM affiche beaucoup de variations, il a parfois les bonnes valeurs mais ça varie ....
                            pourtant ce systeme fonctionne tres bien quand on se sert du rupteur (interrupteur actionné par la came) pour allumer une led, mais si je souhaite recuperer ce signal et le traiter il apparait des variations ....
                            pourriez vous m'aider ?
                            merci d'avance
                            voici le programme :
                            #include <SoftwareSerial.h>
                            #include <SabertoothSimplified.h>
                            #define NOT_AN_INTERRUPT -1
                            #include "LiquidCrystal.h" //ajout de la librairie
                            SoftwareSerial SWSerial(NOT_A_PIN, 8); //Pin 8 utilisé pour communiquer avec la Sabertooth
                            SabertoothSimplified ST(SWSerial); //librairie sabertooth
                            int buttonState = 0;
                            int lastButtonState = 0;
                            const int potar = A0;  //la broche pour régler la vitesse
                            int compteur =0;
                            /* constantes pour la broche de mesure */
                            const byte PIN_SIGNAL = 2; /* const met la variable en lecture seule / byte = 8 bytes 0 à 255 */
                            /* Variables pour la mesure */
                            volatile unsigned long periode = 0; /*volatile souvent associé à une interrupt  / unsigned = non negatif / long = 4 294 967 295 */
                            void tick() {
                            if(digitalRead(PIN_SIGNAL)== LOW) /*lit le type de signal*/
                                  {
                                     compteur++; /*incremente à chaque signal LOW*/
                                     if(compteur % 4 ==0){ /*si le resultat est divisible par 4 on passe à la suite*/
                              static unsigned long previousMicros = 0; /*static  variable conservée entre 2 appels à la fonction / initialisation qu'une seule fois */
                              unsigned long currentMicros = micros(); /*le nombre de microSecondes depuis le début du programme */
                              /* Calcul le temps écoulé depuis le précédent front */
                              periode = currentMicros - previousMicros; /*le nombre de microSecondes depuis la dernière interruption*/
                              /* Met à jour la variable pour la prochaine interruption */
                              previousMicros = currentMicros; /*on se souvient du nombre de microSecondes depuis le début du programme*/}}
                            }
                            /** Fonction setup() */
                            void setup () {
                                 Serial.begin(9600);
                                 SWSerial.begin(38400);
                                 /* Met la broche en sortie */  
                              pinMode(PIN_SIGNAL, INPUT);
                              attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), tick, FALLING);  
                            }
                            void loop() {
                              int vitesse = analogRead(potar);
                            ST.motor(1,vitesse / 16);
                                 Serial.println("potar");
                              Serial.println(vitesse / 8);
                                Serial.println("");
                                Serial.println("RPM");
                                Serial.println(1000000 / periode * 60);
                                Serial.println("");
                               delay(100);
                              }

                            -
                            Edité par OilgustBora 29 janvier 2018 à 11:24:42

                            • Partager sur Facebook
                            • Partager sur Twitter
                              29 janvier 2018 à 12:47:39

                              Problème #1 :

                              Je ne comprends pas ta ligne 16 : if(digitalRead(PIN_SIGNAL)== LOW)

                              Pourquoi vérifier que la pin est LOW alors que la fonction tick est appelée sous interruption à chaque front descendant (FALLING) ?

                              Vérifier l'état LOW n'est pas nécessaire voir peut-être même dérangeant si la pin à eu le temps de revenir à l'état HIGH avant que l'interruption FALLING ne soit exécutée.

                              ==========

                              Problème #2 :

                              Tu utilises ta variable periode sans verrouiller son accès en désactivant les interruptions.

                              Du coup, pendant que l'arduino fait le calcul 1000000 / periode * 60, une interruption FALLING peut se produire et changer la valeur en plein milieux du calcul, ce qui donnera un résultat obérant.

                              Il te faudrait désactiver et réactiver les interruptions avec cli et sei ;)

                              ==========

                              Problème #3 :

                              Tu fais une division sur des nombres entiers avec 1000000 / periode donc le résultat sera forcément un nombre entier : 1, 2, 3, 4, 5, 6...

                              Vient ensuite la multiplication * 60 qui donnera donc forcément un multiple de 60 : 60, 120, 180, 240, 300, 360...

                              Avec cette formule, impossible d'avoir un autre chiffre qu'un multiple de 60, ce qui limite grandement les possibilités et génère des sauts dans l'affichage.

                              Il te faudrait faire 60000000 / periode pour plus de précision.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                29 janvier 2018 à 14:27:01

                                ah cool !!

                                ce que tu me cites là sont des choses que je ne peux pas encore voir, par contre apres modif je pense pouvoir apprecier la difference !!

                                merci, je regarde ça

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  2 février 2018 à 19:24:21

                                  pleins d'essais réalisés aujourd'hui, quoi qu'il se passe j'ai un mauvais signal généré par l'interrupteur, je m'explique.

                                  j'ai mis une led en parallèle du signal récupéré par l'interrupteur, j'ai en même temps la led TX qui s'allume sur l'arduino quand je commande l'interrupteur.

                                  Je m'aperçois que la led TX s'allume parfois une fois de plus que la led placée en // du montage quand j'actionne l'interrupteur plusieurs fois.

                                  c'est ce qui me plombe le signal je pense ....

                                  il y a donc un truc que je ne comprend pas :

                                  si je pilote une led par l'interrupteur => le signal semble net et franc (pas de programme, simple boucle entre le +5v et le gnd en passant par l'interrupteur et la led)

                                  si je recupere ce meme signal pour le traiter via l'arduino j'ai des sauts et le signal de la led TX n'est pas aussi regulier que celui de la led

                                  comment est-ce possible ?

                                  j'ai modifié le programme mais pas encore ré-injecté

                                  j'ai ajouté cli et sei avec les recherches que j'ai pu faire, ça me depasse un peu mais d'apres ce que j'ai pu lire ça doit pouvoir s'integrer ici, c'est correct ?

                                  void loop() {
                                    int vitesse = analogRead(potar);
                                  
                                   //ST.motor(1,vitesse / 8);
                                  ST.motor(1,vitesse / 16);
                                  cli();
                                      //Serial.println(vitesse);
                                       Serial.println("potar");
                                    Serial.println(vitesse / 8);
                                      Serial.println("");
                                      Serial.println("RPM");
                                      Serial.println(1000000 / periode);
                                         delay(100);
                                         sei();
                                    }

                                  -
                                  Edité par OilgustBora 3 février 2018 à 17:12:11

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    5 février 2018 à 6:40:34

                                    Problème en partie résolu, il me fallait 2 choses

                                    J'ai trouvé un anti rebond software tout simple et efficace e il me manquait une pièce sur mon assemblage, le condensateur ...

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      29 août 2018 à 13:59:18

                                      Salut Lorrio,

                                      j'ai essayé le bout de programme que tu m'as donné il y a quelques temps, je n'ai rien change hormis le fait que mon besoin est un CHANGE dans l'interrupt, seulement je m'aperçois que les valeurs sont dupliquées

                                      le resultat 1 est equivalement au resultat 3, le 2 au  4 bref .... tu saurais pourquoi ?

                                      peut etre que le change est trop rapide et qu'il ne peut enchainer ?

                                      sur un tour d'arbre je dois mesurer 4 LOW et 4 HIGH, je suis donc passé par le change, mais je n'ai pas l'impression que ça fonctionne tres bien

                                      merci d'avance !

                                      #include <SoftwareSerial.h>
                                      #include <SabertoothSimplified.h>
                                      #define NOT_AN_INTERRUPT -1
                                      
                                      SoftwareSerial SWSerial(NOT_A_PIN, 8); //Pin 8 utilisé pour communiquer avec la Sabertooth
                                      SabertoothSimplified ST(SWSerial); //librairie sabertooth
                                      
                                      //rupteur
                                      const byte PIN_SIGNAL = 2; 
                                      volatile unsigned long last_micros;
                                      
                                      //optique
                                      const byte PIN_SIGNAL1 = 3;
                                      unsigned long periode2 = 0;
                                      unsigned long periode3 = 0;
                                      volatile unsigned long last_micros1;
                                      
                                      //dephasage
                                      float dephasage = 0;
                                      
                                      
                                      //COMMUN DEBOUNCING TIME
                                      long debouncing_time = 15; //Debouncing Time in Milliseconds
                                      
                                      //angle came
                                      int buttonState = 0;
                                      int lastButtonState = 0;
                                      float temps_total = 0;
                                      float angle1 = 0;
                                      float angle2 = 0;
                                      float angle3 = 0;
                                      float angle4 = 0;
                                      float angle5 = 0;
                                      float angle6 = 0;
                                      float angle7 = 0;
                                      float angle8 = 0;
                                      int angle_total = 360;
                                      float p1 = 0;
                                      float p2 = 0;
                                      float p3 = 0;
                                      float p4 = 0;
                                      float p5 = 0;
                                      float p6 = 0;
                                      float p7 = 0;
                                      float p8 = 0;
                                      int compteur =0;
                                      
                                      volatile byte compteur_ticks   = 0;
                                      volatile byte compteur_optique = 0;
                                      //unsigned long  previousMicros  = 0;
                                      //unsigned long  previousMicros1 = 0;
                                      float periode=0;
                                      float periode1=0;
                                      float  vitesse1=0;
                                      float  delta2=0;
                                      float  delta3=0;
                                      float  delta4=0;
                                      void debounceInterrupt1() {compteur_optique++;}
                                      //void debounceInterrupt()  {compteur  ++;}
                                      unsigned long  previousMicros  = micros();
                                      unsigned long  previousMicros1 = micros();
                                      unsigned long  fin_rupteur     = 0;
                                      unsigned long  fin_opto        = 0;
                                      float  delta           = 0;
                                      float vitesse = 0;
                                      unsigned long lastTime = 0;
                                      unsigned char counterIdx = 0;
                                      volatile float elapsedTimeArray[8];
                                      /** Fonction setup() */
                                      
                                      
                                      
                                      /*void debounceInterrupt() {
                                        if((long)(micros() - last_micros) >= debouncing_time*1000) {
                                          tick();
                                          last_micros = micros();
                                        }
                                      }*/
                                      
                                      void tick() {
                                       
                                          volatile unsigned long currentTime, elaspsedTime;
                                           
                                          currentTime = millis();
                                          elaspsedTime = ( currentTime - lastTime );
                                          lastTime = currentTime;
                                       
                                          elapsedTimeArray[counterIdx] = elaspsedTime;
                                       
                                          counterIdx++;
                                          if ( counterIdx >= 8 ) {
                                              counterIdx = 0;
                                          }
                                       
                                      }
                                      
                                      void debounceInterrupt() {
                                        if((long)(micros() - last_micros) >= debouncing_time*10) {
                                          tick();
                                          last_micros = micros();
                                        }
                                      }
                                      
                                      void setup () {
                                      
                                           Serial.begin(115200);
                                           SWSerial.begin(38400);
                                            pinMode(PIN_SIGNAL, OUTPUT);
                                      attachInterrupt(digitalPinToInterrupt(PIN_SIGNAL), debounceInterrupt, CHANGE);  
                                      
                                      
                                      }
                                      
                                      void loop() {
                                        vitesse = 50;
                                          ST.motor(1,vitesse);
                                       Serial.println(60000000 / elapsedTimeArray[0]);
                                       Serial.println(60000000 / elapsedTimeArray[1]);
                                       Serial.println(60000000 / elapsedTimeArray[2]);
                                      Serial.println(60000000 / elapsedTimeArray[3]);
                                      Serial.println(60000000 / elapsedTimeArray[4]);
                                      Serial.println(60000000 / elapsedTimeArray[5]);
                                      Serial.println(60000000 / elapsedTimeArray[6]);
                                      Serial.println(60000000 / elapsedTimeArray[7]);
                                      
                                      
                                       temps_total = elapsedTimeArray[0]+elapsedTimeArray[1]+elapsedTimeArray[2]+elapsedTimeArray[3]+elapsedTimeArray[4]+elapsedTimeArray[5]+elapsedTimeArray[6]+elapsedTimeArray[7];
                                      angle1 = (elapsedTimeArray[0]* angle_total) / temps_total;
                                      angle2 = (elapsedTimeArray[1]* angle_total) / temps_total;
                                      angle3 = (elapsedTimeArray[2]* angle_total) / temps_total;
                                      angle4 = (elapsedTimeArray[3]* angle_total) / temps_total;
                                      angle5 = (elapsedTimeArray[4]* angle_total) / temps_total;
                                      angle6 = (elapsedTimeArray[5]* angle_total) / temps_total;
                                      angle7 = (elapsedTimeArray[6]* angle_total) / temps_total;
                                      angle8 = (elapsedTimeArray[7]* angle_total) / temps_total;
                                      
                                      Serial.print("angle 1: ");
                                           Serial.println(angle1);
                                           Serial.print("angle 2: ");
                                           Serial.println(angle2);
                                           Serial.print("angle 3: ");
                                           Serial.println(angle3);
                                           Serial.print("angle 4: ");
                                           Serial.println(angle4);
                                           Serial.print("angle 5: ");
                                           Serial.println(angle5);
                                           Serial.print("angle 6: ");
                                           Serial.println(angle6);
                                           Serial.print("angle 7: ");
                                           Serial.println(angle7);
                                           Serial.print("angle 8: ");
                                           Serial.println(angle8);
                                          
                                            }



                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        29 août 2018 à 14:55:23

                                        Pourquoi avoir déclaré elapsedTimeArray comme un tableau de float ???

                                        La gestion des float est extrêmement lente, c'est donc une très mauvaise idée que d'utiliser des float dans une interruption.

                                        Vu que ton tableau contient uniquement des nombre entier (nombre de millis secondes), tu ferais mieux de le déclarer comme étant un tableau de unsigned long.

                                        Le calcul pourra ensuite se faire sur des float dans le main.

                                        * * *

                                        Autre problème, si une interruption se produit lors du calcul réalisé par le main, alors la valeur change en plein milieu du calcul, on va donc se retrouver avec n'importe quoi.

                                        Il est impératif de désactiver les interruptions le temps de faire une copie puis de travailler sur la copie.

                                        Exemple:

                                        unsigned long elapsCopy[8];
                                        
                                        // Désactivation interruptions le temps de faire une copie !
                                        cli();
                                        
                                        // Copie...
                                        for ( int i = 0 ; i < 8 ; i++ ) {
                                        	elapsCopy[i] = elapsedTimeArray[i];
                                        }
                                        
                                        // Réactivation des interruptions
                                        sei();
                                        
                                        // Et maintenant on fait les calculs en utilisant les copies
                                        
                                        vitesse = 50;
                                        ST.motor(1,vitesse);
                                        
                                        temps_total = 0;
                                        for ( int i = 0 ; i < 8 ; i++ ) {
                                        	temps_total += elapsCopy[i];
                                        }
                                        
                                        for ( int i = 0 ; i < 8 ; i++ ) {
                                        	angle[i] = ( (float)(elapsCopy[i]) * (float)(angle_total) ) / (float)(temps_total);
                                        }
                                        
                                        for ( int i = 0 ; i < 8 ; i++ ) {
                                        	Serial.print("nb");
                                        	Serial.print(i+1);
                                        	Serial.print("=");
                                        	Serial.println( (float)(60000000) / (float)(elapsCopy[i]) );
                                        }
                                        
                                        for ( int i = 0 ; i < 8 ; i++ ) {
                                        	Serial.print("angle");
                                        	Serial.print(i+1);
                                        	Serial.print("=");
                                        	Serial.println( angle[i] );
                                        }

                                        * * *

                                        Les rebonds sont aussi à étudier.

                                        Pour le moment, tu fais un système anti rebond de 150us avec la ligne if((long)(micros() - last_micros) >= debouncing_time*10) {

                                        Donc si tu as des changements plus rapide que 150us, ils seront forcément ignoré.

                                        * * *

                                        Et dernier problème et pas des moindres... (car aucune solution à proposer...)

                                        La lib SoftwareSerial désactive les interruptions durant la réception et l'émission de données !

                                        Donc pendant ce temps, ton interruption CHANGE est temporairement désactivée.

                                        -
                                        Edité par lorrio 29 août 2018 à 14:58:02

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          29 août 2018 à 15:10:22

                                          rhooo la vache j'ai encore beaucoup à apprendre ;)

                                          merci, je regarde tout ça !!!

                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Arduino - attachinterrupt et variables multiples

                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                          • Editeur
                                          • Markdown