Partage
  • Partager sur Facebook
  • Partager sur Twitter

Fonction millis arduino

Sujet résolu
    10 avril 2017 à 19:49:46

    Bonsoir, 

    Je souhaite remplacer les delay par des millis pour éviter que le programme ce stop à chaque fois, cependant je n'y arrive pas du tout.

    Je contrôle un moteur pas à pas en I2C et j'ai un amis qui lui contrôle un moteur CC aussi en I2C seulement une fois nos programme respectif fini ont va rassembler les deux et il ne faut pas que mes delay() stop sont moteur à chaque fois ^^.

    Donc voila mon code avec delay :

    #include <Wire.h>
    
    #define MotorSpeedSet             0x82
    #define DirectionSet              0xaa
    #define Nothing                   0x01
    #define Stepernu                  0x1c
    #define I2CMotorDriverAdd         0x0f   // Set the address of the I2CMotorDriver
    
    byte Direction1 [2][8]={{B1000,B1010,B0010,B0110,B0100,B0101,B0001,B1001},    // mode demi- pas
                            {B1001,B0001,B0101,B0100,B0110,B0010,B1010,B1000}};
    
    void  autorisation(byte ena,byte enb)
    {
      Wire.beginTransmission(I2CMotorDriverAdd);     // transmit to device I2CMotorDriverAdd
      Wire.write(MotorSpeedSet);                     // Direction control header
      Wire.write(ena);                               // send direction control information
      Wire.write(enb);                               // need to send this byte as the third byte(no meaning)  
      Wire.endTransmission();   
      
    }
    void MotorDirectionSet(byte sens)                // Adjust the direction of the motors 0b0000 I4 I3 I2 I1
    {                 
      Serial.println(sens);
      Wire.beginTransmission(I2CMotorDriverAdd);           // transmit to device I2CMotorDriverAdd
      Wire.write(DirectionSet);                            // Direction control header
      Wire.write(sens);                                    // send direction control information
      Wire.write(Nothing);                                 // need to send this byte as the third byte(no meaning)  
      Wire.endTransmission();                              // stop transmitting 
    }
      
    void setup() {
      Wire.begin(); // join i2c bus (address optional for master)
      Serial.begin(9600);
      delay(1000);
    
    
    }
    
    void loop()
    {
    
      for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
        {
           autorisation(255,255);    // activer les autorisations
           for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
           {
             delay(53);
             MotorDirectionSet(Direction1[0][j]);
             Serial.println((Direction1[0][j]));
             delay(53);
           };
      };
    
    for(int i=0 ; i<32 ; i++)  // faire 125 pas pour chaque entrées du tableau
    {
          autorisation(255,255);
          for(int j=0 ; j<8 ; j++)  // sens inverse des aiguilles d'une montre 
          {
            delay(53);
            MotorDirectionSet(Direction1[1][j]);
            delay(53);
          };
    };
      for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
        {
           autorisation(255,255);    // activer les autorisations
           for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
           {
             delay(53);
             MotorDirectionSet(Direction1[0][j]);
             Serial.println((Direction1[0][j]));
             delay(53);
           };
      };
    }


    Et voici celui avec millis :

    #include <Wire.h>
    
    #define MotorSpeedSet             0x82
    #define DirectionSet              0xaa
    #define Nothing                   0x01
    #define Stepernu                  0x1c
    #define I2CMotorDriverAdd         0x0f   // Set the address of the I2CMotorDriver
    
    long temps;  // variable qui stocke la mesure du temps
    
    
    byte Direction1 [2][8]={{B1000,B1010,B0010,B0110,B0100,B0101,B0001,B1001},    // mode demi- pas
                            {B1001,B0001,B0101,B0100,B0110,B0010,B1010,B1000}};
    
    void  autorisation(byte ena,byte enb)
    {
      Wire.beginTransmission(I2CMotorDriverAdd);     // transmit to device I2CMotorDriverAdd
      Wire.write(MotorSpeedSet);                     // Direction control header
      Wire.write(ena);                               // send direction control information
      Wire.write(enb);                               // need to send this byte as the third byte(no meaning)  
      Wire.endTransmission();   
      
    }
    void MotorDirectionSet(byte sens)                // Adjust the direction of the motors 0b0000 I4 I3 I2 I1
    {                 
      Serial.println(sens);
      Wire.beginTransmission(I2CMotorDriverAdd);           // transmit to device I2CMotorDriverAdd
      Wire.write(DirectionSet);                            // Direction control header
      Wire.write(sens);                                    // send direction control information
      Wire.write(Nothing);                                 // need to send this byte as the third byte(no meaning)  
      Wire.endTransmission();                              // stop transmitting 
    }
      
    void setup() {
      Wire.begin(); // join i2c bus (address optional for master)
      Serial.begin(9600);
      delay(1000); 
      temps = millis(); //on initialise le temps
    
    }
    
    void loop()
    {
    
      for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
        {
           autorisation(255,255);    // activer les autorisations
           for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
           {
             if((millis() - temps) > 106)
             {
                 MotorDirectionSet(Direction1[0][j]);
                 Serial.println((Direction1[0][j]));
                 temps = millis(); //on stocke la nouvelle heure
             };
           };
      };
    
    for(int i=0 ; i<32 ; i++)  // faire 125 pas pour chaque entrées du tableau
    {
          autorisation(255,255);
          for(int j=0 ; j<8 ; j++)  // sens inverse des aiguilles d'une montre 
          {
            if((millis() - temps) > 106)
            {
                MotorDirectionSet(Direction1[1][j]);
                temps = millis(); //on stocke la nouvelle heure
            };
          };
    };
      for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
        {
           autorisation(255,255);    // activer les autorisations
           for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
           {
             if((millis() - temps) > 106);
             {
             MotorDirectionSet(Direction1[0][j]);
             Serial.println((Direction1[0][j]));
             temps = millis(); //on stocke la nouvelle heure
             };
           };
      };
    }

    Merci de votre aide :)

    • Partager sur Facebook
    • Partager sur Twitter
      10 avril 2017 à 23:43:56

      Tu ne peux pas laisser tes boucles for si tu n'utilisent pas de delay.

      Par exemple, imaginons que tu ai ce programme :

      void loop() {
      
          Serial.println("debut");
      
          for ( int i = 0 ; i < 5 ; i++ ) {
      
              Serial.println(i);
      
              delay(100);
      
          }
      
          Serial.println("fin");
      
      }

      Celui-ci va afficher :

      debut
      1
      2
      3
      4
      5
      fin
      debut
      1
      2
      ...
      

      Mais si tu le remplaces par celui-ci :

      long temps;
      
      void loop() {
      
          Serial.println("debut");
      
          for ( int i = 0 ; i < 5 ; i++ ) {
      
              if ( millis() - temps > 100 ) {
                  Serial.println(i);
                  temps = millis();
              }
      
          }
      
          Serial.println("fin");
      
      }

      Alors tu vas voir afficher :

      debut
      fin
      debut
      fin
      debut
      fin
      debut
      ...

      Ce qui n'est pas le résultat attendu.

      Tu obtiens ça car ton programme rentre dans la bouble for avec i=0 puis il test le if.

      Comme très peu de temps c'est écoulé, il n'entre pas dans le if et continue la boucle for avec i=1.

      Il test à nouveau le if mais là encore, il ne s'est pas écoulé 100ms donc il n'entre pas dans le if et il continue la boucle avec i=2.

      Au final, le programme va très rapidement faire la boucle avec i=1,2,3,4,5 sans jamais entré dans le if.

      Au bout d'un moment, il se sera effectivement écoulé 100ms donc on a voir apparaitre un nombre au hasard dans la console (ça dépendra de où on en est dans le code) puis ce sera à nouveau reparti sur l'affichage debut/fin/debut/fin...

      Bref, tout ça pour dire qu'il te faut complètement revoir l'architecture de ton code pour retirer les boucles for.

      Dans mon exemple, il faudra plutôt avoir :

      int i = 0;
      long temps;
      
      void loop() {
      
          if ( i == 0 ) {
              Serial.println("debut");
              i++;
          }
      
          if ( millis() - temps > 100 ) {
      
              Serial.println(i);
      
              i++;
      
              temps = millis();
      
          }
      
          if ( i >= 5 ) {
              Serial.println("fin");
              i = 0;
          }
      
      }

      Bref, pas de boucle for mais uniquement des if pour jouer avec la variable i.




      -
      Edité par lorrio 10 avril 2017 à 23:47:16

      • Partager sur Facebook
      • Partager sur Twitter
        11 avril 2017 à 0:52:28

        Merci beaucoup lorrio pour ton explication, je vais refaire mon code demain et mettrais le résultat ici :)
        • Partager sur Facebook
        • Partager sur Twitter
          22 avril 2017 à 3:17:55

          Bonsoir,

          Bien que j'ai avancé dans mon programme, je n'ai pas réussis à remplacer les for par des if :/

          Mais j'ai une autre question, peut-on mettre des boucle for dans des boucle if ?

          Exemple :

            if (ValeurBP2 != 1) 
            {
              for()// tourner à droite à l'"infinie"
            }
            else if (ValeurBP1 != 1)
            {
              for()// tourner à gauche à l'"infinie"
            }
            else
            {
              for()// lancer le "scanner"
            }

          Merci des vos réponses :)

          -
          Edité par RafaelDAIGNEAU1 22 avril 2017 à 3:18:57

          • Partager sur Facebook
          • Partager sur Twitter
            22 avril 2017 à 20:58:25

             Tu es libre de faire le programme que tu veux.

            Si tu veux mettre des boucles for à l'intérieur d'un if, tu as tout à fait le droit ;)

            • Partager sur Facebook
            • Partager sur Twitter
              23 avril 2017 à 13:11:25

              D'accord,

              Merci, j'étais pas sur que l'on pouvais le faire de ton aide ;)

              • Partager sur Facebook
              • Partager sur Twitter
                24 avril 2017 à 12:19:14

                Bonjour,

                J'ai donc essayé de rajouter 2 boutons poussoir à mon programme d'origine pour pouvoir mettre le moteur en position initial.

                Le problème est que lorsque j'appuis sur le bouton, le programme ne passe pas à la boucle suivante et tourne toujours dans cette même boucle.

                #include <Wire.h>
                
                #define MotorSpeedSet             0x82
                #define DirectionSet              0xaa
                #define Nothing                   0x01
                #define Stepernu                  0x1c
                #define I2CMotorDriverAdd         0x0f   // Set the address of the I2CMotorDriver
                
                
                byte Direction1 [2][8]={{B1000,B1010,B0010,B0110,B0100,B0101,B0001,B1001},    // mode demi- pas
                                        {B1001,B0001,B0101,B0100,B0110,B0010,B1010,B1000}};
                
                int BP1=1;
                int BP2=2;
                
                int ValeurBP1=LOW;
                int ValeurBP2=0;
                
                
                void  autorisation(byte ena,byte enb)
                {
                  Wire.beginTransmission(I2CMotorDriverAdd);           // transmit to device I2CMotorDriverAdd
                  Wire.write(MotorSpeedSet);                                    // Direction control header
                  Wire.write(ena);                               // send direction control information
                  Wire.write(enb);                                 // need to send this byte as the third byte(no meaning)  
                  Wire.endTransmission();   
                  
                }
                
                
                void MotorDirectionSet(byte sens)    // Adjust the direction of the motors 0b0000 I4 I3 I2 I1
                {                 
                  Wire.beginTransmission(I2CMotorDriverAdd);           // transmit to device I2CMotorDriverAdd
                  Wire.write(DirectionSet);                                    // Direction control header
                  Wire.write(sens);                               // send direction control information
                  Wire.write(Nothing);                                 // need to send this byte as the third byte(no meaning)  
                  Wire.endTransmission();                              // stop transmitting 
                }
                
                
                void SequenceComplete()
                {
                    for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
                    {
                       autorisation(255,255);    // activer les autorisations
                       for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
                       {
                         delay(30);
                         MotorDirectionSet(Direction1[0][j]);
                         delay(30);
                       };
                    };
                
                    for(int i=0 ; i<32 ; i++)  // faire 125 pas pour chaque entrées du tableau
                    {
                       autorisation(255,255);
                       for(int j=0 ; j<8 ; j++)  // sens inverse des aiguilles d'une montre 
                       {
                         delay(30);
                         MotorDirectionSet(Direction1[1][j]);
                         delay(30);
                       };
                    };
                    for(int i=0 ; i<16 ; i++)  // faire 125 pas pour chaque entrées du tableau
                    {
                       autorisation(255,255);    // activer les autorisations
                       for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
                       {
                         delay(30);
                         MotorDirectionSet(Direction1[0][j]);
                         delay(30);
                       };
                   };
                }
                
                void SensHoraire()
                {
                  autorisation(255,255);    // activer les autorisations
                  for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre 
                  {
                     delay(30);
                     MotorDirectionSet(Direction1[0][j]);
                     ValeurBP2=digitalRead(BP2);
                     Serial.println(ValeurBP2);
                     delay(30);
                  };
                    
                }
                
                void SensAntiHoraire()
                {
                  autorisation(255,255);
                  for(int j=0 ; j<8 ; j++)  // sens inverse des aiguilles d'une montre 
                  {
                      delay(30);
                      MotorDirectionSet(Direction1[1][j]);
                      ValeurBP1=digitalRead(BP1);
                      Serial.println(ValeurBP1);
                      delay(30);
                  };
                }
                  
                void setup() {
                  Wire.begin(); // join i2c bus (address optional for master)
                  Serial.begin(9600);
                  delay(1000);
                  pinMode(BP1, INPUT);
                  pinMode(BP2, INPUT);
                }
                
                void loop()
                {
                  do
                  {
                     SensHoraire();
                  }while (ValeurBP2 == LOW);
                  
                  do
                  {
                     SensAntiHoraire();
                  }while (ValeurBP1 == LOW);
                  
                SequenceComplete();
                
                }

                Le programme reste bloqué dans la première boucle do/while or je voudrais qu'une fois le BP soit appuyé il passe directement à la seconde boucle while et ainsi de suite.

                Merci de vos aides ^^ 

                • Partager sur Facebook
                • Partager sur Twitter
                  24 avril 2017 à 13:17:59

                  Sur arduino, l'état Low est un define sur la valeur 0.

                  Donc quand tu écris ceci :

                  int ValeurBP1=LOW;
                  int ValeurBP2=0;

                  Cela, revient à à avoir tes 2 état à LOW lors de l'initialisation.

                  Est-ce vraiment ce que tu veux ?

                  ----------

                  Dans ton programme principal, tu fais

                    do
                    {
                       SensHoraire();
                    }while (ValeurBP2 == LOW);
                     
                    do
                    {
                       SensAntiHoraire();
                    }while (ValeurBP1 == LOW);

                  Sur un do/while, le contenu est exécuté au moins une fois puis la condition est testée.

                  Donc dans tous les cas, tu programme va faire au moins un appel à SensHoraire et un appel à SensAntiHoraire, même si les 2 boutons sont à High.

                  Est-ce vraiment ce que tu veux ?

                  Ne serait-ce pas plus logique d'avoir une boucle while ?

                  ----------

                  Dans tes fonctions SensHoraire et sens SensAntiHoraire, tu as une bouble for avec lecture de l'état du bouton :

                  void SensHoraire()
                  {
                    autorisation(255,255);    // activer les autorisations
                    for(int j=0 ; j<8 ; j++)  // sens des aiguilles d'une montre
                    {
                       delay(30);
                       MotorDirectionSet(Direction1[0][j]);
                       ValeurBP2=digitalRead(BP2);
                       Serial.println(ValeurBP2);
                       delay(30);
                    };
                       
                  }

                  Sauf qu'à aucun endroit de ces fonctions tu ne prends en compte l'état du bouton.

                  Du coup, peu importe l'état du bouton, le programme va faire la boucle for en entier, ce qui prend environ 0.5 secondes.

                  Une fois la boucle for terminée, la fonction s'arrête et l'on revient à ton do/while qui va prendre en compte l'état lu.

                  Est-ce vraiment ce que tu veux ?

                  Ne serait-ce pas plus logique d’arrêter la boucle for avec un break si le bouton est enfoncé ?

                  ----------

                  Et puis dernière question : es-tu certain du bon câblage de tes boutons ?

                  Vu que tu fais un Serial.println de la valeur, vois tu cette valeur changé quand tu appuie sur le bouton ?



                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 avril 2017 à 16:49:33

                    Oui, j'aimerais qu'ils soient au début à 0.

                    ---------

                    Non, je veux que la conditions soit d'abord testé et si elle est non vérifié que le moteur continue à avancer dans le sens donné jusqu'à ce que la condition soit vérifié.

                    ---------

                    Oui, justement le problème est la. Lorsque le bouton est enfoncé il faudrait que la boucle for se termine ainsi que la boucle while et passe à la seconde boucle while faire la même chose.

                    ---------

                    Concernant le câblage, j'ai utilisé celui-ci pour les boutons.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      26 avril 2017 à 17:19:30

                      Quand ton bouton est enfoncé, celui-ci fait contact entre la pin et 5V.

                      Du coup, c'est comme si la pin était reliée au 5V.

                      De ce fait, la lecture de l'état de la pin va donner la valeur HIGH.

                      Jusque là, tout va bien :)

                      Quand ton bouton n'est pas enfoncé, celui-ci ne fait aucun contact.

                      Du coup, c'est comme si la pin était reliée à rien du tout, elle est dans le vide.

                      De ce fait, la lecture de l'état de la pin va donner plus ou moins n'importe quoi (soit HIGH, soit LOW) puisqu'il n'y a rien pour imposer un état logique.

                      En effet, ce n'est pas parce que tu ne connectes rien à ta pin qu'elle va forcément lire LOW.

                      D'ailleurs, celle-ci aura plutôt tendance à lire un HIGH qu'un LOW compte tenu de la physique du cœur du processeur.

                      Bref, ça ne va pas du tout...

                      Il te faut impérativement ajouter une résistance de pull-dow entre la pin (fil gris sur ton schéma) et le GND (fil bleu sur ton schéma).

                      Une résistance comprise entre 1k et 10k fera l'affaire ;)

                      ----------

                      Quand au code, si tu veux que celui-ci n'exécute la boucle que si le bouton est relâché et qu'il la quitte dès qu'on appuie dessus, tu devras avoir :

                      ValeurBP2 = digitalRead(BP2);
                      while (ValeurBP2 == LOW) {
                          SensHoraire();
                      };
                      void SensHoraire()
                      {
                          autorisation(255,255);
                          for(int j=0 ; j<8 ; j++) {
                              delay(30);
                              MotorDirectionSet(Direction1[0][j]);
                              ValeurBP2=digitalRead(BP2);
                              Serial.println(ValeurBP2);
                              delay(30);
                              if ( ValeurBP2 != LOW ) {
                                  break;
                              }
                          }
                      }




                      -
                      Edité par lorrio 26 avril 2017 à 19:48:19

                      • Partager sur Facebook
                      • Partager sur Twitter
                        26 avril 2017 à 18:13:33

                        Oh excuse moi je n'ai pas fais attention au schéma, dans mon câblage, j'ai bien mis une résistance de 10k à l'endroit que tu m'a indiqué.

                        Je vais donc tester ce câblage avec le nouveau code voir si cela fonctionne, encore merci et bonne soirée ;)

                        -
                        Edité par RafaelDAIGNEAU1 26 avril 2017 à 18:20:01

                        • Partager sur Facebook
                        • Partager sur Twitter
                          27 avril 2017 à 18:28:47

                          Comment peut-on prouver qu'il faut une résistance de 1k à 10k ?

                          Avec U = R*I ? 

                          Merci :)

                          • Partager sur Facebook
                          • Partager sur Twitter
                            27 avril 2017 à 19:12:10

                            Quand le bouton est enfoncé, la résistance est en direct entre GND et VCC donc un courant circule dans la résistance.

                            Plus la résistance est faible, plus le courant est important car I = U / R.

                            Mieux vaut donc prendre une valeur assez élevée pour ne pas consommer trop de courant inutilement.

                            Cependant, plus la valeur est élevée, moins celle-ci est efficace pour polariser l'entrée de l'arduino.

                            Il faut donc trouver le bon compromis entre consommation et polarisation.

                            Au final, une valeur entre 1k et 10k donne un bon compromis.

                            Mais ça marchera quand même si tu prends une 0.5k ou un 20k.

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Fonction millis arduino

                            × 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