Partage
  • Partager sur Facebook
  • Partager sur Twitter

Contrôler Moteur CC avec Arduino

en même temps que deux servomoteurs par une liaison radio

    8 février 2013 à 18:00:39

    Bonjour,

    Dans le cadre d'un projet (PPE) en terminale, je dois faire fonctionner une hélice multidirectionnelle miniature telle que celle-ci par liaison radio.

    Nous avons donc deux Arduinos, un nunchuck, un émetteur et un récepteur radio, deux servomoteur et l'hélice miniature avec un moteur 12v à courant continu.

    Un arduino sert de "télécommande" avec le nunchuck et l’émetteur radio, tandis que l'autre se trouve sur notre prototype de bateau et contrôle les deux servomoteurs et le moteur 12v.

    Nous avons réussi à tout faire fonctionner, mais nous sommes confronté à plusieurs problèmes. Avant tout, voici les deux code source :

    Télécommande :

    #include "Wire.h"  
    #include "WiiChuck.h"
    #include <VirtualWire.h>
    
    WiiChuck chuck = WiiChuck();
    
    int joyX = 0;
    int joyY = 0;
    int z = 0 ;
    char data[12] = {0};
    
    void setup()
    {
      // alimentation du nunchuck 
      DDRC |= _BV(PORTC3) | _BV(PORTC2);  // pattes Analog 2 et 3 en sortie  
      PORTC &=~ _BV(PORTC2);           // patte Analog 2 à 0v  
      PORTC |=  _BV(PORTC3);           // patte Analog 3 à 5v
    
      delay(100);  // une petite attente  
    
      Serial.begin(19200);  
      chuck.begin();  
      chuck.update(); 
    
      //Radio
      vw_setup(2000);                // Bits par seconde, bon compromis pour nous. 
      vw_set_tx_pin(3);             // La broche 3 sera utilisée pour transmettre l'état du nunchuck, j'ai mis cette valeur de manière arbitraire. 
    
    }
    void loop()
    {    
      chuck.update();   
      
      // on lit l'état du joystick 
      joyX = chuck.readJoyX() - 12;  // On corrige les valeurs par rapport à notre nunchuck
      joyY = chuck.readJoyY() +5 ;
      
      if(chuck.zPressed())
      {
            z = 1-z ; //On modifie l'état du moteur
      }
      
      sprintf(data, "%d;%d;%d;", z, joyX, joyY);
      envoyer(data);
      delay(10);                                              // Pour éviter de faire un brouilleur
    }  
    void envoyer(const char* msg)
    {
       vw_send((uint8_t *)msg, strlen(msg));
       vw_wait_tx();                                          // On attend que le message soit envoyé.
    }

    Bateau :

    #include <SoftwareServo.h>
    #include <VirtualWire.h>
    
    #define ANGLE_MIN 0
    #define ANGLE_MAX 180
    #define PLAGE_MIN 20
    #define PLAGE_MAX 70
    
    #define SORTIE_SERVO_X 5
    #define SORTIE_SERVO_Y 6
    #define SORTIE_MOTEUR 10
    
    int z = 0 ;
    int joyX = 0 ;
    int joyY = 0 ;
    
    int i = 0 ;
    
    SoftwareServo servoX;
    SoftwareServo servoY;
    
    void setup()
    {
      servoX.attach(SORTIE_SERVO_X) ;
      servoY.attach(SORTIE_SERVO_Y) ; 
      pinMode(SORTIE_MOTEUR, OUTPUT);
           
        Serial.begin(19200);   
        vw_setup(2000); 
        vw_set_rx_pin(3);             // broches du récepteur.
        vw_rx_start();      // Démarrage du récepteur.
    }
    void loop()
    {
        uint8_t buf[VW_MAX_MESSAGE_LEN];
        uint8_t buflen = VW_MAX_MESSAGE_LEN;
        if (vw_get_message(buf, &buflen)) // On test afin de savoir si un message est reçu.
        {
          sscanf((char*)buf, "%d;%d;%d;", &z, &joyX, &joyY);
        }
            
        servoX.write(angle(plage(joyX)));
        servoY.write(angle(plage(joyY)));
        
        analogWrite(SORTIE_MOTEUR, 255 * z); //Plus tard, nous allons faire varier z de 0 à 1 pour jouer sur la tension d'alimentation du moteur.
        
        i++ ;
        if(i == 10)
        {
             SoftwareServo::refresh();
             i = 0;
        }
        
    }
    int plage(int value) //Fonction permettant d'avoir une "zone morte" et une valeur maximale.
    {
      if(value > 0)
      {
        if(value > PLAGE_MAX)
        {
          value = PLAGE_MAX ;
        }
        else if(value < PLAGE_MIN)
        {
          value = 0;
        }
      }
      else
      {
        if(value < -PLAGE_MAX)
        {
          value = -PLAGE_MAX ;
        }
        else if(value > -PLAGE_MIN)
        {
          value = 0;
        }
      }
      return value ;
    }
    int angle(int value) //Fonction retournant un angle pour les servomoteurs par rapport aux valeurs du joystick.
    {
      return ((value + PLAGE_MAX)*(ANGLE_MAX - ANGLE_MIN))/(PLAGE_MAX*2);
    }

    Premier problème :

    Les librairie Servo et Virtualwire sont incompatibles, pour pouvoir malgré tout faire fonctionner les servomoteurs, nous utilisons SoftwareServo. Cependant il faut appeler la méthode refresh toutes les 20 millisecondes au moins et lorsque nous l'appelons à chaque tour de boucle, j'ai l'impression qu'elle "prend toutes les ressources", les valeurs transmises par radio ne sont pas traitées. L'appeler une fois tous les 10 tours de boucle est le meilleur compromis que nous avons trouvé, mais j'aimerais trouver quelque chose de plus "propre" et de plu réactif.

    J'aimerais aussi ne plus avoir à utiliser sprintf et sscanf car, à mon avis ce n'est pas la manière la plus propre de faire. Toutes le valeurs à envoyer sont comprissent dans une plage inférieure à 256 valeurs, ce qui fonctionnerait avec le type uint8_t, mais je ne suis pas arrivé à faire fonctionner la transmission de cette manière.

    Deuxième problème (le plus grave) :

    Pour contrôler le moteur (maximum 3A), nous utilisons un transistor de type TIP120.

    Une sortie PWN est reliée à la base de celui-ci (avec une résistance de 1kOhm), le collecteur est relié à la même source d'alimentation (12v) que l'arduino, le moteur se situe entre l’émetteur et la masse en parallèle avec une diode de roue libre de type 1N4148. Le problème est que le transistor chauffe énormément (vraiment!) et que la tension aux bornes du moteur est de 4v (à la place de 12). Je ne connais quasiment rien concernant les transistors, mais après une brève recherche, j'ai pu en déduire que pour notre utilisation en "commutation", la tension de saturation était trop élevée.

    Que me conseillez vous ? Nous n'avons pas fait le bon choix de transistor ?

    Merci d'avance.

    -
    Edité par Twixx 8 février 2013 à 18:02:38

    • Partager sur Facebook
    • Partager sur Twitter
      8 février 2013 à 20:16:43

      Pour le transistor : Vire le ! Remplace le par un MOSFET .

      Pour le code, j'ai pas le temps de m'y pencher pour l'instant

      • Partager sur Facebook
      • Partager sur Twitter

      Retrouvez moi sur mon blog et ma chaine Youtube !

        8 février 2013 à 20:38:00

        Merci de ta réponse, mais pourrais-tu expliciter un peut plus ? Pourquoi un mosfet ? Quels avantages par rapport à un transistor ? Pourquoi un transistor ne serait pas une solution adapté ? Je sais que je pose beaucoup de question, mais je cherche justement à comprendre pourquoi le montage ne fonctionne pas et comment faire pour que celui-ci fonctionne.
        • Partager sur Facebook
        • Partager sur Twitter
          8 février 2013 à 22:06:25

          Le Mosfet est un transistor, sauf qu'il est plus fait pour bosser en commutation plutôt qu'en amplification (cas de tes darlingtons). Du coup il sera facile à piloter en tension, et surtout il n'aura pas une grosse chute de tension tout en pouvant faire passer un bon courant.

          Cependant, il est toujours bon de mettre un dissipateur dessus surtout si tu travailles à des intensités élevées.

          • Partager sur Facebook
          • Partager sur Twitter

          Retrouvez moi sur mon blog et ma chaine Youtube !

            8 février 2013 à 22:15:01

            Merci beaucoup pour ces renseignements, c'est parfaitement ce qu'il nous faut. :)
            • Partager sur Facebook
            • Partager sur Twitter
              8 février 2013 à 22:19:31

              Je te laisse chercher les références qui vont bien en fonction des caractéristiques d'alimentation et de consommation ;)
              • Partager sur Facebook
              • Partager sur Twitter

              Retrouvez moi sur mon blog et ma chaine Youtube !

                8 février 2013 à 23:44:46

                Pas de problème pour ça ! :D
                • Partager sur Facebook
                • Partager sur Twitter

                Contrôler Moteur CC avec 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