Partage
  • Partager sur Facebook
  • Partager sur Twitter

[arduino] mon code ne marche pas!

return loop() inefficace

Sujet résolu
    12 mars 2012 à 18:18:23

    Bonjour à tous.

    Le code suivant bug. Il est sensé actionner une électrovanne et une sortie son (je l'active juste 100 ms car cela suffit). Or, le programme se déroule toujours comme si le capteur était à l'état HIGH.

    Je ne voit pas du tout d'où peut venir le problème.

    Merci d'avance.

    const int son=5;
    const int vanne=6;
    const int capteur=2;
    
    const int tpsson=100;
    const int tpsvanne=100;
    
    int etat1=0;
    int etat2=0;
    int i=0;
    
    
    
    void setup()
    {
    pinMode(son,OUTPUT);
    pinMode(vanne,OUTPUT);
    pinMode(capteur,INPUT);
    }
    
    
    
    void loop()
    {
    
    etat1=digitalRead(capteur);
    
    if(etat1==LOW) {
    delay(100); // pour éviter de trop consommer
    return loop();}
    
    musique(); //debut
    eau();
    attente(8);
    
    
    eau(); // savonnnage
    
    delay(8000);// savonnage
    eau();
    delay(2000); //on met l'eau 2sec pour que l'enfant remette ses mains
    
    
    attente(12);//rincage
    
    
    //musique finit
    delay(3000);// tempo eau
    
    eau();
    delay(2000);//tempo vide
        
        
        
    }
    
    
    
    void musique()
    {
      digitalWrite(son,HIGH);
      delay(tpsson);
      digitalWrite(son,LOW);
    }
    
    void eau()
    {
      digitalWrite(vanne,HIGH);
      delay(tpsvanne);
      digitalWrite(vanne,LOW);
    }
    
    
    void attente(int secondes)
    {
    i=0;
    
    while(i!=(secondes*5))
    {
    i++;
    
    delay(100);
    etat1=digitalRead(capteur); // deux variable pour avoir + de marge
    delay(100);
    etat2=digitalRead(capteur);
      if (etat1==LOW&&etat2==LOW)
        {
         
          musique();
          eau();
          
          return loop();      
        }
    } 
    }
    
    • Partager sur Facebook
    • Partager sur Twitter
      12 mars 2012 à 19:04:46

      Tu veux faire quoi quand tu fais "return loop()" ? relancer la loop ?

      Sinon tu as vérifié que ton capteur évoluait bien normalement (hors Arduino) ? (je suppose mais on peut toujours demandé ^^ )
      • Partager sur Facebook
      • Partager sur Twitter

      Retrouvez moi sur mon blog et ma chaine Youtube !

        12 mars 2012 à 20:27:41

        Pour le capteur, je branche directement un câble depuis le 5V pour les tests. :p

        Concernant le return loop() , oui je veux redémarrer la boucle (mais ca ne marche pas).
        • Partager sur Facebook
        • Partager sur Twitter
          13 mars 2012 à 0:35:29

          C'est normal.

          lorsque tu fais return loop(à tu fais des imbrications de ta fonction loop().

          En fait tu ne termine jamais de loop() puisque lorsque tu veux terminer attente() tu lance une loop()...

          1.1.loop()
          1.2.j'arrive sur attente()
          1.2.1. je rentre dans le return -> loop()
          1.2.2. j'arrive sur attente()
          1.2.2.1. je rentre dans le return -> loop()
          1.2.2.2. j'arrive sur attente()
          1.2.2.2.1. je rentre dans le return -> loop()
          1.2.2.2.2. j'arrive sur attente()
          etc.

          Ceci dans le cas om l'on arrive sur le return loop(), sinon cela devrait fonctionner puisque tu n'appelle pas de fonction.

          De plus je pense que tu n'a pas trop compris le principe intrinsèque des fonctions et de la stack.

          Mon schéma est horrible est un peu mal foutu mais j'espère que tu réussira à comprendre rapidement :

          Image utilisateur

          Lors de l'exécution de loop, var1 et var2 ont une valeur stockées en mémoire. Lorsque tu fais appel à attente(), le programme va garder l'adresse de l'instruction où il se trouve, va garder en mémoire var1 et var2 et aller à l'adresse de la première instruction de attente(). A partir de là il exécute les instructions qui se trouve dans attente, ici il va mettre rav1 = 42 en mémoire, puis attendre, et vu que la fonction est finie, il va revenir à l'endroit où il était dans loop, ce faisant il dépile la stack et va dégager de la mémoire la variable rav1 puisqu'elle n'est pas transmise en return.
          Comme les variable var1 et var2 étaient dans la stack, on a garder leur valeur. Et le programme va maintenant ajouter la variable blabla = 0 en mémoire.

          Si tu faisais un return loop() dans ce attente(), dans ce cas tu recréé une fonction loop() avec 2 nouvelles variables var1 et var2 mais différentes des 2 premières.



          Quand tu dis que tu veux redémarrer loop() tu peux expliciter ? Tu veux continuer là où tu en était ou refaire tout depuis le début ?
          • Partager sur Facebook
          • Partager sur Twitter
            13 mars 2012 à 9:29:09

            En simple : On ne fait pas de return loop !! (en tout cas dans le sens ou je l'ai compris : repartir à la première instruction de la loop)

            Tu peux faire un "return" tout court, qui te permettera de retourner la ou tu étais rendu lorsque tu as fait appel à ta fonction (à l'instruction juste après donc).

            J'ai relu ton code et je commence à comprendre ce qui ne vas pas...

            Chaque fois que tu as mis un "return loop()" vire le ! ca devrais mieux se passer... (le premier peut etre remplacé par un grand cas "else" par exemple, si tu ne veux pas executer le code lorsque ton capteur n'est pas comme tu veux)
            • Partager sur Facebook
            • Partager sur Twitter

            Retrouvez moi sur mon blog et ma chaine Youtube !

              13 mars 2012 à 9:57:46

              Donc je me sert uniquement d’itérations ( = if) et pas de return c'est ca?
              • Partager sur Facebook
              • Partager sur Twitter
                13 mars 2012 à 10:10:19

                Bah les return ca a un role précis (et ca ne veut pas dire "goto", "aller à" !)

                Un return sera utile pour renvoyer une valeur depuis une fonction par exemple :

                int addition(int a, int b)
                {
                   int resultat = a+b;
                   return resultat;
                }
                


                (va ptet falloir que je reprécise ca dans le tuto)
                • Partager sur Facebook
                • Partager sur Twitter

                Retrouvez moi sur mon blog et ma chaine Youtube !

                  13 mars 2012 à 19:27:23

                  C'est donc une différence avec le C/C++ ?
                  • Partager sur Facebook
                  • Partager sur Twitter
                    13 mars 2012 à 19:34:57

                    Quelle différence ??

                    Je fais du C/C++ et autres langages depuis assez longtemps et je n'utilise pas "return" pour "aller à une fonction" de cette manière...
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Retrouvez moi sur mon blog et ma chaine Youtube !

                      13 mars 2012 à 19:39:12

                      Après une petite discussion avec un collègue, on est arrivé à cette conclusion :

                      - la fonction attente() est de type void elle ne peut donc pas renvoyer de valeur, l'utilisation de return n'est donc pas logique, je dirais même qu'un bon compilateur devrait signaler l'erreur, néanmoins c'est une technologie de virtual machine qui se trouve derrière l'arduino.

                      - la fonction loop() est aussi de type void, ce qui fait que lorsque tu fais un return loop() le programme appelle probablement la fonction loop(), mais il n'y a pas d'erreur signalée car loop() était de type void cela provoque peut-être une sorte de "return void" ou "return null" et donc ne gêne pas le compilateur avec le type void de la fonction attente().

                      -------

                      Je viens de m'apercevoir de ca :

                      if(etat1==LOW) {
                      delay(100); // pour éviter de trop consommer
                      return loop();
                      }
                      


                      J'avais réagit sur le return loop() qui se trouve dans attente(). Mais ce return est complètement faux et je me demande même pourquoi le compilateur arduino peux laisser une erreur aussi grossière (bon le langage c'est du java / C mais quand même).

                      L'autre c'est que tu devrais relire un cours sur le C et regarder un peu du code (c'est difficile de trouver du code correct accessible aux débutants, essaie de faire un tour sur le forum dédié au C) pour voir un peu ce qui se fait.
                      Car là c'est juste faux d'écrire cela et même cela indique que tu n'as pas compris les principes mis en jeu par le C (oui Arduino c'est pas du vrai C mais on va faire comme si ca l'était).
                      • Partager sur Facebook
                      • Partager sur Twitter
                        13 mars 2012 à 19:49:20

                        Citation : Eskimon

                        Quelle différence ??

                        Je fais du C/C++ et autres langages depuis assez longtemps et je n'utilise pas "return" pour "aller à une fonction" de cette manière...



                        Bah moi si. :p
                        Je me doutait que c' était pas génial, mais c'est vachement pratique.

                        @Zeql : hummm, d'acord je comprend mieux :)

                        Je fais comment donc? Je met des else de partout?
                        Et si je met des else de partout et que je modifie la variable de condition, est ce que la condition est brisée?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          13 mars 2012 à 20:11:51

                          Alors...
                          Faire un return dans une fonction void n'est pas faux. "Return" comme vous le savez peut-être signifiera "retour", autrement dit "on retourne la ou on était" lorsqu'on a fait la fonction. On peut en profiter pour y retourner avec une valeur si besoin. Mais faire un return pour quitter une fonction n'est pas faux.

                          Loop() étant elle meme une fonction qui ne retourne rien, il est normal que le "return loop()" compile sans problème. Par contre il faut comprendre ce qui va se passer...

                          Chaque fois que tu va faire "return loop()" tu vas dire au programme "renvoie la valeur renvoyé (s'il y en a une) par la fonction loop". Le programme bête et méchant va donc chercher à executer la fonction loop() qu'il connait... cette derniere va s'executer et tomber tot ou tard (selon ton code) sur un autre return loop() qui donc va de nouveau l'appeler... etc...

                          Donc pour faire propre et fonctionnel, ON NE FAIT PAS RETURN LOOP() ^^

                          Tu fais plutôt des if{}else{} pour encadrer ton code proprement.
                          Par exemple :

                          void loop()
                          {
                              etat1=digitalRead(capteur);
                          
                              if(etat1==LOW) {
                                  delay(100); // pour éviter de trop consommer
                              }
                              else {
                                  musique(); //debut
                                  eau();
                                  attente(8);
                                  [...];// ton code a executer
                              }
                          }
                          
                          • Partager sur Facebook
                          • Partager sur Twitter

                          Retrouvez moi sur mon blog et ma chaine Youtube !

                            13 mars 2012 à 20:18:21

                            Ok, ce serat moche mais fonctionnel alors... tampis :p

                            J'envoie le nouveau code dès que je l'ai validé.

                            Peux tu répondre à ma dernière question : "Et si je met des else de partout et que je modifie la variable de condition, est ce que la condition est brisée? "
                            • Partager sur Facebook
                            • Partager sur Twitter
                              13 mars 2012 à 21:26:03

                              J'ai pas compris ta question... tu peux faire un code d'exemple ?
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Retrouvez moi sur mon blog et ma chaine Youtube !

                              Anonyme
                                14 mars 2012 à 10:58:01

                                pour info, lorsque l'on veux aller quelque part dans le programme sans "le suivre de haut en bas", on peut utiliser la fonction goto : http://arduino.cc/en/Reference/Goto
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  14 mars 2012 à 12:51:24

                                  Les goto sont à éviter absolument. Sinon tu risque de te retrouver avec du "code spaghetti".

                                  J'ai vraiment l'impression que tu n'a pas compris les principes de la programmation.
                                  En assembleur oui on joue avec les adresses pour faire avancer le programme avec certaines construction, mais dans un langage comme le C on n'a pas besoin de dire au programme où aller avec des return et goto sauf cas vraiment exceptionnel et je doute très fortement que tu sois arrivé à un cas où tu ne peux pas faire autrement qu'utiliser un goto.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    14 mars 2012 à 13:39:21

                                    +1 avec zeqL, les goto c'est le mal !
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Retrouvez moi sur mon blog et ma chaine Youtube !

                                      14 mars 2012 à 16:31:04

                                      bah voici un autre code (qui ne marche pas non-plus)

                                      const int son=5;
                                      const int vanne=6;
                                      const int capteur=3;
                                      
                                      const int tpsson=100;
                                      const int tpsvanne=100;
                                      
                                      int etat1=0;
                                      int i=0;
                                      double secondes=0;
                                      
                                      
                                      
                                      void setup()
                                      {
                                      pinMode(son,OUTPUT);
                                      pinMode(vanne,OUTPUT);
                                      pinMode(capteur,INPUT);
                                      }
                                      
                                      
                                      
                                      void loop()
                                      {
                                      
                                      
                                      etat1=digitalRead(capteur);
                                      
                                      if(etat1==HIGH) {
                                      
                                        
                                        musique(); //debut
                                        eau();
                                        
                                        secondes=8;
                                        i=0;
                                        
                                        while(i!=(secondes/10)&&etat1==HIGH)
                                        {
                                        i++;
                                        delay(100);
                                        etat1=digitalRead(capteur);
                                        } 
                                        
                                        if(etat1==LOW)
                                        {
                                        musique();
                                        eau();
                                        }
                                        
                                        if(etat1==HIGH)
                                        {
                                        eau(); // savonnnage
                                        delay(8000);// savonnage
                                        eau();
                                        delay(2000); //on met l'eau 2sec pour que l'enfant remette ses mains
                                        etat1=digitalRead(capteur);
                                        }
                                        
                                        
                                        
                                        i=0;
                                        secondes =12;
                                        
                                         // rincage des mains
                                        while(i!=(secondes/10)&&etat1==HIGH)
                                        {  
                                        delay(100);
                                        etat1=digitalRead(capteur); 
                                        i++;
                                         }
                                         
                                         if(etat1==LOW)
                                        {
                                          eau();
                                        }
                                        
                                        if(etat1==HIGH)
                                        {
                                        //musique finit
                                        delay(3000);// tempo eau
                                        
                                        eau();
                                        delay(2000);//tempo vide
                                        }
                                            
                                      }// fin du 1er if
                                      
                                      
                                      }// fin loop
                                      
                                      
                                      
                                      void musique()
                                      {
                                        digitalWrite(son,HIGH);
                                        delay(tpsson);
                                        digitalWrite(son,LOW);
                                      }
                                      
                                      void eau()
                                      {
                                        digitalWrite(vanne,HIGH);
                                        delay(tpsvanne);
                                        digitalWrite(vanne,LOW);
                                      }
                                      


                                      Pourquoi ca marche pas ???? J'ai l'impression qu'il ne prend plus la valeur du capteur après la 1er itération. En pratique, la boucle ne s'arrete jamais. :'(

                                      EDIT : nv code, toujours bugant (mais moins).
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        14 mars 2012 à 17:38:43

                                        Ca veut dire quoi "bugguant mais moins" :D décris nous les symptomes, ce a quoi tu t'attends et ce que tu obtiens vraiment.

                                        Il y a des incohérences.
                                        Par exemple (premier while) :
                                        secondes=8;
                                        i=0;
                                        while(i!=(secondes/10)&&etat1==HIGH)
                                        {
                                           i++;
                                           delay(100);
                                           etat1=digitalRead(capteur);
                                        }
                                        

                                        Tu vas essayer de comparer i (un int) avec secondes (un double qui vaut 0.8). Qu'est ce que tu attends comme réaction ? ta condition ne marchera jamais car i sera TOUJOURS différent de secondes (quelques soit sa valeur). Il faut que tu fasses ta comparaison avec des '<=' ou '>=' (ou juste '<' et '>')
                                        Essaie d'aérer tes conditions, ce sera plus simple à débugguer :
                                        while( i!=(secondes/10) && etat1==HIGH )
                                        



                                        Au lieu d'essayer le comportement "tout d'un coup", essai de faire juste morceau par morceau. Écris un peu du code, envoie le sur Arduino et test le. Une fois que ca marche, rajoute en un peu etc...
                                        Ne te presse pas sinon ca ne marchera pas car tu ne verras pas ou ca bug...
                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Retrouvez moi sur mon blog et ma chaine Youtube !

                                          16 mars 2012 à 20:37:37

                                          Voici un code déjà plus opérationnel.

                                          const int son=5;
                                          const int vanne=6;
                                          const int capteur=3;
                                          
                                          const int tpsson=100;
                                          const int tpsvanne=100;
                                          
                                          int etat1=0;
                                          double i=0;
                                          double secondes=0;
                                          
                                          
                                          
                                          void setup()
                                          {
                                          pinMode(son,OUTPUT);
                                          pinMode(vanne,OUTPUT);
                                          pinMode(capteur,INPUT);
                                          }
                                          
                                          
                                          
                                          void loop()
                                          {
                                          
                                          
                                          etat1=digitalRead(capteur);
                                          
                                          if(etat1==HIGH) {
                                          
                                            
                                            musique(); //debut
                                            eau();
                                            
                                            secondes=0.8;
                                            i=0;
                                            delay(100);
                                            etat1=digitalRead(capteur);
                                            
                                            while(i<secondes&&etat1==HIGH)// mouillage
                                            {
                                            i=i+0.01;
                                            delay(100);
                                            etat1=digitalRead(capteur);
                                            } 
                                            
                                            if(etat1==LOW)
                                            {
                                            musique();
                                            eau();
                                            }
                                            
                                            if(etat1==HIGH)
                                            {
                                            eau(); // savonnnage
                                            delay(8000);// savonnage
                                            eau();
                                            delay(2000); //on met l'eau 2sec pour que l'enfant remette ses mains
                                            etat1=digitalRead(capteur);
                                            }
                                            
                                            
                                            
                                            i=0;
                                            secondes =1.2;
                                            
                                             // rincage des mains
                                            while(i<(secondes/10)&&etat1==HIGH)
                                            {  
                                            delay(100);
                                            etat1=digitalRead(capteur); 
                                            i=i+0.01;
                                             }
                                             
                                             if(etat1==LOW)
                                            {
                                              eau();
                                            }
                                            
                                            if(etat1==HIGH)
                                            {
                                            //musique finit
                                            delay(3000);// tempo eau
                                            
                                            eau();
                                            delay(2000);//tempo vide
                                            }
                                            
                                            
                                            
                                                
                                          }// fin du 1er if
                                          
                                          
                                          }// fin loop
                                          
                                          
                                          
                                          void musique()
                                          {
                                            digitalWrite(son,HIGH);
                                            delay(tpsson);
                                            digitalWrite(son,LOW);
                                          }
                                          
                                          void eau()
                                          {
                                            digitalWrite(vanne,HIGH);
                                            delay(tpsvanne);
                                            digitalWrite(vanne,LOW);
                                          }
                                          


                                          Le seul problème que j'ai détecter et celui de la latence : l'arduino met environ 1.5 seconde à sortit d'une boucle while !Le problème vient-il de mon programme? Est-il évitable?
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            16 mars 2012 à 21:04:39

                                            Pour la première boucle while, en admettant que etat1 reste à HIGH, ta boucle va s'executer à peu près 80 fois, ce qui fait donc 80 fois delay(100) donc... 8 secondes !
                                            Pareil pour ta deuxième boucle while, ou tu devras la faire à peu près 12 fois, donc 1.2 secondes (d'ailleurs pourquoi écrire "secondes = 1.2" puis le diviser par 10 alors que tu pourrais directement écrire "secondes = 0.12" ?
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Retrouvez moi sur mon blog et ma chaine Youtube !

                                              16 mars 2012 à 21:32:31

                                              Sauf que la condition est :

                                              while(i<secondes&&etat1==HIGH)
                                              



                                              Donc théoriquement, si le capteur n'est plus à l'état HIGH, la boucle doit s’arrêter non?
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                16 mars 2012 à 21:55:11

                                                c'est pour ca que j'ai mis "en admettant que" ;)
                                                du coup je sais pas vu que j'ai pas les détails du montage/capteur/simulation...
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Retrouvez moi sur mon blog et ma chaine Youtube !

                                                  16 mars 2012 à 22:06:30

                                                  Le problème est donc matériel?
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    16 mars 2012 à 22:33:07

                                                    Je sais pas, je ne sais pas comment tu fais tes tests !
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    Retrouvez moi sur mon blog et ma chaine Youtube !

                                                      17 mars 2012 à 10:10:00

                                                      Bah avec des leds et un fil 5V vers l’entrée utilisée comme INPUT.

                                                      Quand je parle de matériel, je parle de l'arduino, pas du reste.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        17 mars 2012 à 12:01:55

                                                        Et comment tu t'y prend pour faire tes tests ? tu branches/débranches un fil ? tu utilises un interrupteur ? Tu as observé que tu amenais les bonnes tensions sans rebond ou autre ?

                                                        Sinon autre question. Pour tes secondes tu codes tout sur des floats. Ici la performance n'est pas un facteur clé mais il est plus judicieux de travailler avec des entiers (int) et donc tu pourrais tout multiplier par 100 et faire comme si tu travaillais en centième de secondes. C'est toujours mieux de bosser avec des entiers au lieu de float quand tu peux (typiquement des unités de temps se représente bien en entier...)
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter

                                                        Retrouvez moi sur mon blog et ma chaine Youtube !

                                                          17 mars 2012 à 19:19:46

                                                          Je branche et debranche un fil depuis le 5V pour simuler le capteur. Ca fait des rebonds?

                                                          Merci pour les conseils.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            17 mars 2012 à 19:24:36

                                                            Oui ca doit surement faire des rebonds... essaie de mettre un condensateur pour filtrer... (à une époque je faisais des tests avec une breadboard pas terrible et j'avais des rebonds très rapidement du à la "pauvreté" des connexions)
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Retrouvez moi sur mon blog et ma chaine Youtube !

                                                            [arduino] mon code ne marche pas!

                                                            × 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