Accueil > La technologie > Arduino > Manœuvre des aiguilles avec des servo-moteurs > Mise en œuvre d’un servo-moteur

Manœuvre des aiguilles en analogique avec des servo-moteurs

Mise en œuvre d’un servo-moteur

dimanche 10 novembre 2013, par Jean-Luc

L’Arduino c’est à la fois une carte équipée d’un microcontrôleur et un environnement logiciel qui fournit à l’utilisateur des fonctions pour manipuler le matériel de manière plus simple que s’il devait mettre en œuvre le micro-contrôleur à partir de rien.

L’Arduino se programme en langage C et quelques fois en C++. Le C est un langage de programmation très populaire, notamment sur les systèmes embarqués, c’est à dire les systèmes informatiques intégrés dans un procédé dans le but de le piloter.

Un programme minimum pour Arduino

Le programme minimum pour l’Arduino est constitué de deux fonctions. Une fonction regroupe une série d’instructions et remplit un rôle. Voici ces deux fonctions, setup() et loop(). La fonction setup() est exécutée 1 seule fois au début de programme. La fonction loop() est exécutée répétitivement.

/*
 * La fonction setup() est exécutée 1 fois
 * au démarrage du programme
 */
void setup()
{
}
 
/*
 * La fonction loop() est exécutée
 * répétitivement
 */
void loop()
{
}

en langage C, une fonction retourne une valeur dont le type est indiqué juste à gauche du nom de la fonction. Il existe plusieurs types de données en C, les nombres entiers positifs et négatif (int), ceux qui sont seulement positif (unsigned int) etc. Nous verrons les types au fur et à mesure des besoins. Ici le type est void, il s’agit d’un type spécial qui signifie « rien » ou « vide » et qui indique que les fonctions setup() et loop() ne retournent aucune valeur.

Une fonction peut prendre des arguments. Les arguments sont donnés entre les parenthèses juste après le nom de la fonction. Ici les deux fonctions n’ont aucun argument.

Les instructions qui constituent la fonction sont données entre les accolades. Ici les deux fonctions sont vides et par conséquent elle ne font strictement rien.

Au dessus des fonctions il y a du texte. Il s’agit de commentaires. Un commentaire commence par /* et termine par */. C’est une bonne habitude de commenter abondamment ses programmes. En effet, quelques semaines plus tard, il est difficile de se rappeler de ce que l’on a voulu faire dans un programme et les commentaires explicatifs sont bienvenus.

Mise en œuvre d’un servo-moteur

La mise en œuvre d’un servo-moteur avec l’Arduino est aisée. Il y a une bibliothèque pour ça !

Une bibliothèque est un jeu de fonctions optionnelles que l’on peut ou non employer dans le programme. Pour utiliser la bibliothèque permettant de piloter des servo-moteurs, il suffit d’inclure, au début du programme la directive suivante

#include <Servo.h>

Il faut ensuite pouvoir manipuler le servo-moteur. Il faut pour cela créer une variable de type Servo. On dit aussi instancier une variable. Le type Servo est un peu spécial, on entre là sur le terrain du C++. Servo est une classe et créer une variable de ce type donne un objet. En plus de contenir une valeur comme une variable de type nombre entier, un objet possède des fonctions qui agissent sur lui. Dans le monde de l’objet on appelle communément ces fonctions des méthodes. Nous n’avons pas besoin d’en connaître plus pour utiliser un objet de type Servo. Voici comment on crée une variable, que nous appelons monServo de type Servo.

Servo monServo;

Notez le « ; » qui termine la ligne, il est nécessaire et termine la directive. Notez aussi que le respect des majuscules et des minuscules est important car le langage C fait la différence entre s et S par exemple. Par conséquent appeler la variable monServo n’est pas la même chose que de l’appeler monservo.

La variable monServo est instanciée, il faut maintenant l’accrocher à une des sorties numériques de l’Arduino. Nous allons choisir la sortie 2 car les sorties 0 et 1 ont un rôle particulier : elles permettent d’envoyer des messages qui seront affichés sur votre ordinateur hôte. Il s’agit d’une aide irremplaçable qui se révèle nécessaire pour comprendre ce qui se passe quand le programme ne fait pas ce que l’on attend.
Accrocher la variable à une sortie se fait avec la méthode attach et, évidemment, dans la fonction setup() car il est inutile de le faire plus d’une fois.

void setup()
{
    monServo.attach(2); /* accroche monServo à la pin 2 de l'Arduino */
}

Aller-retours

La première application est très simple, il s’agit de faire faire au servo des aller-retours de part et d’autre de la position médiane. La méthode write(...) permet de donner l’angle auquel le servo doit se positionner. L’argument est une valeur comprise entre 0 et 180°. L’angle minimum choisi est donc de 70° et l’angle maximum de 110°. On fixe la pause entre 2 changements de position à 1s. La fonction loop() est donc la suivante.

void loop()
{
    /* positionne le servo à 70° */
    monServo.write(70);
    /* attend 1000 ms */
    delay(1000); 
    /* positionne le servo à 110° */
    monServo.write(110);
    /* attend 1000 ms */
    delay(1000); 
}

Cette première application ne remplit pas le cahier des charges. À savoir un mouvement lent. Le mouvement a bien lieu toutes les secondes mais il est très rapide, quasi instantané.

Aller-retours lents

Pour obtenir un mouvement lent, il faut faire varier l’angle du servo progressivement. Pour cela, il faut changer l’angle très très peu et le faire plus souvent. Fixons par exemple un changement d’angle de 1°. Si l’on veut que le mouvement, passer de 70° à 110° soit accompli en 1s, il faut augmenter l’angle de 1° toutes les 1000ms / (110 - 70). soit une pause de 25ms. Quand l’angle atteint 110°, il faut inverser le mouvement. Quand l’angle atteint 70°, il faut de nouveau inverser le mouvement. Nous avons donc besoin de deux variables, angle qui contient l’angle courant du servo et vitesse qui contient 1 si on augmente l’angle et -1 si on le diminue. Pour faciliter la programmation, on va placer 70 et 110 dans deux constantes. Le programme est le suivant.

Programme 2

#include <Servo.h>
 
Servo monServo;
int vitesse;
int angle;
 
const int angleMin  = 70;
const int angleMax = 110;
 
/*
 * La fonction setup() est exécutée 1 fois
 * au démarrage du programme
 */
void setup()
{
    monServo.attach(2);
    angle = angleMin;
    vitesse = 1;
}
 
/*
 * La fonction loop() est exécutée
 * répétitivement
 */
void loop()
{
    monServo.write(angle);
    /* calcule le nouvel angle */
    angle = angle + vitesse;
 
    if (angle > angleMax) {
        /* 
         * le nouvel angle dépasse le maximum
         * on le recale au maximum et on inverse la vitesse
         */
        angle = angleMax;
        vitesse = -1;
    }
    else if (angle < angleMin) {
        /*
         * le nouvel angle dépasse le minimum
         * on le recale au minimum et on inverse la vitesse
         */
        angle = angleMin;
        vitesse = 1;
    }
    delay(25);
}

Le mouvement est bien lent comme on le désire mais avec une variation de l’angle par degré, le mouvement est un peu saccadé. Une autre méthode permet un positionnement plus précis. Il s’agit de la méthode writeMicroseconds(...). L’argument de cette méthode n’est plus un angle mais la durée de l’impulsion de commande du servo-moteur en micro-secondes. En effet, le signal de commande du servo-moteur est une impulsion dont la largeur détermine la position du servo (plus d’informations sont données dans l’article « La carte de commande 6 servo-moteurs, le matériel », une autre mise en œuvre utilisant une conception matérielle personnelle). Cette impulsion a donc la forme suivante.

La PWM de commande d’un servo
Seuls les durées extrêmes de l’impulsion et la durée médiane sont montrées mais toutes les valeurs entre 0,5 ms et 2,5 ms sont possibles.

La valeur médiane est donc de 1500µs et les valeurs minimum et maximum pour les angles que nous avions fixés deviennent respectivement et approximativement 1250 et 1750. On va conserver une vitesse de 1 ou -1 et pour avoir un mouvement d’1s alors que l’on franchi 500 pas d’angle on va désormais faire une pause de 2ms. Le programme est donc le suivant.

Programme 3

#include <Servo.h>
 
Servo monServo;
int vitesse;
int angle;
 
const int angleMin  = 1250;
const int angleMax = 1750;
 
/*
 * La fonction setup() est exécutée 1 fois
 * au démarrage du programme
 */
void setup()
{
    monServo.attach(2);
    angle = angleMin;
    vitesse = 1;
}
 
/*
 * La fonction loop() est exécutée
 * répétitivement
 */
void loop()
{
    monServo.writeMicroseconds(angle);
    /* calcule le nouvel angle */
    angle = angle + vitesse;
 
    if (angle > angleMax) {
        /* 
         * le nouvel angle dépasse le maximum
         * on le recale au maximum et on inverse la vitesse
         */
        angle = angleMax;
        vitesse = -1;
    }
    else if (angle < angleMin) {
        /*
         * le nouvel angle dépasse le minimum
         * on le recale au minimum et on inverse la vitesse
         */
        angle = angleMin;
        vitesse = 1;
    }
    delay(2);
}

Le résultat est meilleur avec un mouvement plus fluide.

Voici qui conclut cette prise en main des servo-moteurs. Le prochain article portera sur l’ajout d’un bouton permettant de commander le mouvement du servo-moteur.

Mise en œuvre des 3 programmes présentés

Messages

  • Bonjour,

    Avec le même servo j’ai besoin de lui faire faire un aller-retour mais une seule fois, pour actionner un bouton poussoir.
    Est-ce possible ?

    Dans l’attente je vous remercie et champion votre site !!

    André

    • Bonjour,

      Merci :-)

      Je ne comprends pas ce que vous voulez faire. Pourquoi ne pas remplacer le bouton par un dispositif (transistor, relai, que sais-je) commandé par l’Arduino ?

      Quel est le rôle de ce bouton

    • Bonjour
      Meilleurs vœux.

      Tout simplement pour lever un levier commandé par une LDR. Sans plus.

      Comme l’arduino commande directement le servo-moteur, je pensais le faire avec. sans ajouter de composant supplémentaire.

      Merci pour votre éventuelle réponse.

      André

    • Bonsoir,

      Meilleurs vœux également.

      Pour faire un allez-retour lent et un seul, c’est assez simple. Le servo est à son angle initial avec une vitesse de 0. Sur un événement, pression d’un bouton par exemple, la vitesse est mise à 1. Le servo commence son mouvement, quand il atteint son angle maximum, la vitesse est mise à -1, il revient. Quand l’angle atteint l’angle minimum, la vitesse passe à 0 et le servo s’arrête. Le programme serait le suivant :

      #include <Servo.h>
       
      const int angleMin  = 70;
      const int angleMax = 110;
       
      const byte pinServo = 2;
      const byte pinBouton = 3;
      
      Servo monServo;
      int vitesse;
      int angle;
       
      /*
       * La fonction setup() est exécutée 1 fois
       * au démarrage du programme
       */
      void setup()
      {
          pinMode(pinBouton, INPUT_PULLUP);
          monServo.attach(pinServo);
          angle = angleMin;
          vitesse = 0;
      }
       
      /*
       * La fonction loop() est exécutée
       * répétitivement
       */
      void loop()
      {
          if (digitalRead(pinBouton) == LOW && vitesse == 0) {
              vitesse = 1;
          }
      
          monServo.write(angle);
          /* calcule le nouvel angle */
          angle = angle + vitesse;
       
          if (angle > angleMax) {
              /* 
               * le nouvel angle dépasse le maximum
               * on le recale au maximum et on inverse la vitesse
               */
              angle = angleMax;
              vitesse = -1;
          }
          else if (angle < angleMin) {
              /*
               * le nouvel angle dépasse le minimum
               * on le recale au minimum et on inverse la vitesse
               */
              angle = angleMin;
              vitesse = 0;
          }
          delay(25);
      }
    • Bonsoir,

      Merci beaucoup pour votre aide qui m’a été précieuse et je peux continuer mon projet en le modifiant légèrement.

      Merci encore c’est super sympa

      André

  • Bonjour,

    J’avance pas à pas, en prenant le temps de la compréhension, je commence à maîtriser les bases mais je suis confronté à un problème que je ne peux résoudre.

    J’alimente un seul servo avec la carte arduino
    A la mise sous tension de l’Arduino, avec le bon sketch téléchargé, il y a un mouvement assez brutal du servo, notamment dans une position où il dépasse largement l’angle maxi.

    Je peux contourner le problème en alimentant d’abord l’arduino puis en branchant le +5v sur le servo. Cela peut très bien se concevoir ainsi mais n’existe-t’il pas de méthode soft pour régler ce problème, ou comment le contournez-vous ?.

    Merci pour tout ce travail et pour votre réponse

Un message, un commentaire ?

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)