Partage
  • Partager sur Facebook
  • Partager sur Twitter

Arduino : Accéléromètre et moteur

    29 novembre 2018 à 8:19:29

    Bonjour, je suis actuellement en Terminale S SI, et je dois réaliser un projet de fin d'année.

    Je suis vraiment débutant en Arduino, l'ayant abordé depuis peu en cours d'électronique. Je souhaite réaliser un programme qui aurait pour but de récupérer la valeur de l'inclinaison de la pente sur lequel se trouve le véhicule (ici un fauteuil roulant) et ensuite démarrer le fauteuil en fonction de ladite inclinaison. J'ai déjà une esquisse de programme, mais malheureusement nous n'avons pas encore le matériel pour le tester, le magasinier du lycée étant particulièrement lent.

    Je souhaiterais donc savoir si ce programme risque de ne pas fonctionner, ou si certaines choses demanderaient a être améliorées.

    Merci d'avance et bonne journée

    • Partager sur Facebook
    • Partager sur Twitter
      Staff 30 novembre 2018 à 11:30:06

      Plutôt que de poster une image, ce serait bien d'utiliser la balise code (le petit bouton </> juste à coté du bouton servant à insérer une image).

      Sinon, quelques remarque :

      - pour des numéro de pin, ce serait mieux d'utiliser int plutôt que float

      - attention aux divisions par 0 :si AY=0, alors ton programme va très mal se comporter en faisant AX/AY, un petit if/else s'impose

      - j'ai un doute sur la fonction map, si elle prend des entiers en paramètre, ça risque d'être saccadé...

      - si I est négatif, tu vas envoyer un PWM négatif, ce n'est pas une bonne idée

      -
      Edité par lorrio 30 novembre 2018 à 11:30:56

      • Partager sur Facebook
      • Partager sur Twitter
        13 décembre 2018 à 8:51:10

        D'accord, merci beaucoup.

        Je vais rajouter ce que tu m'as dit.

        A la place de la fonction map, que me conseille tu ? Pour la conversion d'une plage de valeurs sur une autre ?

        Merci d'avance

        • Partager sur Facebook
        • Partager sur Twitter
          Staff 13 décembre 2018 à 10:03:22

          La fonction map fait une simple mise à l'échelle, le code n'est pas compliqué.

          Tu peux très bien la recréer toi même sur des floats :

          float mapF(float x, float in_min, float in_max, float out_min, float out_max) {
              return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
          }

          Si tu veux que x se situe forcément entre le min et le max, tu peux aussi rajouter une protection :

          float constrainF(float x, float in_min, float in_max, float out_min, float out_max) {
              float res = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
              if ( res < out_min ) { res = out_min };
              if ( res > out_max ) { res = out_max };
              return res;
          }




          -
          Edité par lorrio 13 décembre 2018 à 10:05:51

          • Partager sur Facebook
          • Partager sur Twitter
            20 décembre 2018 à 8:21:30

            Merci pour ton aide, je vais encore abuser, mais le floatF,tu le met avant le void setup ?

            Et sinon, par rapport au premier map que j'avais fait, qu'elle est la différence ?

            Encore merci, et désolé pour mon amateurisme :-)

            PS : Et je t'avoue ne pas comprendre le "return" que tu as mis après le float mapF

            Mon code ressemble à ça maintenant :

            int pot1 = 3; // c'est ici qu'on branche l'axe X de l'accelerometre
            int pot2 = 4; // c'est ici qu'on branche l'axe Y de l'accelerometre
            int pinMoteur = 11; // le moteur est branché sur la branche 11
            float I ;// I sera la valeur d'inclinaison de la pente plus tard dans le programme
            
            void setup() {
              pinMode (pot1, INPUT); //on définit l'axe X comme une entrée
              pinMode (pot2, INPUT);//on définit l'axe Y comme une entrée
              //pinMode (moteur, OUTPUT);//le moteur est définit comme une sortie
            }
            void accelerometre(){//on crée une fonction correspondant au calcul du degré de pente
               float Ax = analogRead(pot1); // la valeur Ax prend la valeur de l'accelération en X
               float Ay = analogRead(pot2); // la valeur Ay prend la valeur de l'accelération en Y
               float mapAX(float Ax, float 268.0, float 404.0, float -1000.0, float 1000.0){ //la fonction map convertit par un produit en croix la valeur de Ax comprise entre 268 et 404 en une valeur comprise entre -1000 et 1000 que l'on appelle AX, faire attention à AX différent de Ax
                return (Ax - 268.0) * (1000.0 + 1000.0) / (404.0 - 268.0) - 1000.0;
               }
               float mapAY (float Ay, float 271.0, float 406.0, float -1000.0, float 1000.0); // la fonction map convertit par un produit en croix la valeur de Ay comprise entre 270 et 406 en une valeur comprise entre -1000 et 1000 que l'on appelle AY, faire attention à AY différent de Ay
                return (Ax - 271.0) * (1000.0 + 1000.0) / (406.0 - 271.0) - 1000.0;
               if (AY>0){
               I=atan(AX/AY)*180/PI; // I prend la valeur de l'inclinaison de la pente en degrés
               } 
               else {}
               }
            
            void loop() {
              accelerometre();
            



            -
            Edité par AntoineGros2 20 décembre 2018 à 9:38:03

            • Partager sur Facebook
            • Partager sur Twitter
              Staff 20 décembre 2018 à 12:24:24

              Là, il faut revoir un peu les bases de la programmation en C.

              Une petite relecture du cours sur les fonctions s'impose ;)

              Le floatF que je te propose est une fonction, que tu dois théoriquement déclarer avant de l'utiliser, puis l'implémenter où tu le souhaites dans l'espace global (en dehors de setup et loop).

              Le code doit alors ressemblé à ceci :

              // Création des variables
              int pot1 = 3;
              int pot2 = 4;
              int pinMoteur = 11;
              float I;
              
              
              // Déclaration des fonctions :
              void setup(void);
              void loop(void);
              void accelerometre(void);
              float mapF(float x, float in_min, float in_max, float out_min, float out_max);
              
              
              // Implémentation de setup
              void setup() {
              	pinMode (pot1, INPUT);
              	pinMode (pot2, INPUT);
              }
              
              
              // Implémentation de loop
              void loop() {
              	accelerometre();
              }
              
              
              // Implémentation de accelerometre
              void accelerometre(void){
                 float Ax = analogRead(pot1);
                 float Ay = analogRead(pot2);
                 Ax = mapF(Ax, 268.0, 404.0, -1000.0, +1000.0);
                 Ax = mapF(Ax, 271.0, 406.0, -1000.0, +1000.0);
                 I=atan(AX/AY)*180/PI;
              }
              
              
              // Implémentation de mapF
              float mapF(float x, float in_min, float in_max, float out_min, float out_max) {
                  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
              }

              Pour ce qui est de ta question, il faut savoir que la fonction map fait ses calculs sur long, ce qui correspond à des nombres entiers.

              Dans ton cas, tu fais un map sur l'interval -1000/+1000 donc l'arrondissement du résultat à un nombre entier donnera une erreur assez faible.

              Mais si tu avais fais ton map sur un interval -1/+1 comme c'est le cas en trigonométrie, tu aurais eu une sacrée surprise car il n'y a que 3 résultats possibles : soit -1, soit 0, soit 1.

              J'en profite aussi pour insister sur le fait que map et mapF ne font aucune contrainte sur l'interval d'arrivée et de départ.

              Imaginons que analogRead te retourne la valeur 103 (qui est en dehors de l'interval 268/404), le résultat de sortie correspondra à la valeur -3426 (qui est en dehors de l'interval -1000/+1000).

              Si tu veux que le résultat de sortie soit bridé sur l'interval de sorti, il te faut utiliser constrain ou constrainF.



              -
              Edité par lorrio 20 décembre 2018 à 12:28:18

              • Partager sur Facebook
              • Partager sur Twitter
                10 janvier 2019 à 8:34:41

                Bonjour, et merci pour ta réponse.

                La fonction map ne met pas de contraintes sur l'intervalle, mais l'intervalle que j'ai donnée comme borne de l'intervalle sont les valeurs de tension de sortie minimale et maximale, respectivement en x et en y. Est-ce donc possible d'avoir une valeur se situant à l'extérieur de l'intervalle ?

                En je n'ai pas compris ce que fait la fonction mapF...:D

                Voila mon code, si nécessaire :

                int pot1 = 3; // c'est ici qu'on branche l'axe X de l'accelerometre
                int pot2 = 4; // c'est ici qu'on branche l'axe Y de l'accelerometre
                int pinMoteur = 11; // le moteur est branché sur la branche 11
                float I; // I sera la valeur d'inclinaison de la pente plus tard dans le programme
                 
                 
                // Déclaration des fonctions :
                void setup(void);
                void loop(void);
                void accelerometre(void);
                float mapF(float x, float in_min, float in_max, float out_min, float out_max);
                 
                 
                // Implémentation de setup
                void setup() {
                    pinMode (pot1, INPUT); //on définit l'axe X comme une entrée
                    pinMode (pot2, INPUT); //on définit l'axe Y comme une entrée
                }
                 
                  
                // Implémentation de accelerometre
                void accelerometre(void){ //on crée une fonction correspondant au calcul du degré de pente
                   float Ax = analogRead(pot1); // la valeur Ax prend la valeur de l'accelération en X
                   float Ay = analogRead(pot2); // la valeur Ay prend la valeur de l'accelération en Y
                   AX = mapF(Ax, 268.0, 404.0, -1000.0, +1000.0); //la fonction map convertit par un produit en croix la valeur de Ax comprise entre 268 et 404 en une valeur comprise entre -1000 et 1000 que l'on appelle AX, faire attention à AX différent de Ax
                   AY = mapF(Ay, 271.0, 406.0, -1000.0, +1000.0); // la fonction map convertit par un produit en croix la valeur de Ay comprise entre 270 et 406 en une valeur comprise entre -1000 et 1000 que l'on appelle AY, faire attention à AY différent de Ay
                    return (Ax - 271.0) * (1000.0 + 1000.0) / (406.0 - 271.0) - 1000.0;
                   if (AY>0){
                   I=atan(AX/AY)*180/PI; // I prend la valeur de l'inclinaison de la pente en degrés
                   }
                   else {}
                   }
                 
                void loop() {
                  accelerometre();
                }
                 
                 
                // Implémentation de mapF
                float mapF(float x, float in_min, float in_max, float out_min, float out_max) {
                    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
                }



                • Partager sur Facebook
                • Partager sur Twitter
                  Staff 10 janvier 2019 à 15:05:21

                  L'ADC de l'arduino peut donner une valeur entre 0 et 1023.

                  Donc il est tout à fait possible d'avoir quelque chose qui soit en dehors du range 268-404.

                  Si la température change, il est possible que ton capteur dérive un peu et puisse donner une valeur en dehors.

                  Et si un fils se débranche, tu auras clairement la possibilité d'avoir une valeur en dehors.

                  Mais libre à toi de faire ce que tu veux.

                  ***

                  La fonction mapF fait exactement la même chose que la fonction map.

                  Sauf qu'elle fait ses calculs sur des float, donc il y a moins de risque d'erreur d'arrondie lors de la division.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 janvier 2019 à 8:28:25

                    D'accord, je vais donc utiliser l'ADC total de l'arduino entre 0 et 1023.

                    Merci !

                    EDIT : Donc si j'ai bien compris, Ax prend une valeur entre 0 et 1023, lors de l'analogRead(pot1) ?

                    -
                    Edité par AntoineGros2 17 janvier 2019 à 8:52:02

                    • Partager sur Facebook
                    • Partager sur Twitter
                      Staff 17 janvier 2019 à 13:37:01

                      Tout dépend de ce que renvoie ton capteur !

                      Les pins analogiques peuvent mesurer une tension comprise entre 0V et 5V.

                      La valeur convertie sera comprise entre 0 (pour 0V) et 1023 (pour 5V).

                      Il s'agit bien sûre d'une conversion proportionnelle donc 1V = 204 ; 2V = 409 ; 3V = 613 ; 4V = 818...

                      Si ton capteur renvoie une tension entre 0V et 5V, alors Ax prendra une valeur entre 0 et 1023.

                      Mais si ton capteur renvoie une valeur sur un intervalle plus faible, alors l'intervalle de conversion de l'ADC sera lui aussi plus faible.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Arduino : Accéléromètre et moteur

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      • Editeur
                      • Markdown