dimanche 1 novembre 2015

Contrôler un servomoteur en python avec un Raspberry Pi

Cet article a été mis à jour le 21 décembre 2020 (compatibilité Python 3)

Dans le passé, nous avons vu comment faire en sorte que notre Raspberry Pi contrôle un moteur dc et un moteur pas à pas au moyen d'un script en python.  Aujourd'hui, c'est le tour d'un servomoteur.

Comment ça fonctionne

Un peu comme le moteur pas à pas, le servomoteur peut être contrôlé de façon à lui faire prendre une position angulaire très précise.  Une différence importante, c'est qu'avec le moteur pas à pas, on contrôle le déplacement (comme dans "tourne de 5° vers la gauche") alors qu'avec le servomoteur, on contrôle la position (comme dans "va à la position 17°").  

Cette position se contrôle au moyen d'un signal en modulation de largeur d'impulsion (PWM:  voir cet article pour plus de détails):  il s'agit d'une succession de signaux logiques hauts (3,3 V) et bas (0 V).

En général, le signal est envoyé toutes les 20 ms (donc la fréquence est de 50 Hz).  Si le signal demeure haut pendant 1 ms (ce qui correspond à un rapport cyclique de 5 %), le servomoteur se place à sa position minimale, s'il demeure haut pendant 1,5 ms (rapport cyclique de 7,5%), il se place à sa position médiane, et s'il demeure haut pendant 2 ms (rapport cyclique de 10 %), il se place à sa position maximale.

Les valeurs exactes varient d'un servomoteur à l'autre, toutefois, et le mieux est d'effectuer quelques tests avec celui que vous utiliserez, afin de connaître les rapports cycliques nécessaires pour lui faire occuper ses positions extrêmes (le premier exemple de script, présenté un peu plus loin dans cet article, nous permettra d'atteindre cet objectif).

Le circuit

Le servomoteur est muni de trois connecteurs:  le fil noir (ou marron) est la masse (GND), le fil rouge est l'alimentation (5 V) et le fil jaune (ou autre couleur) transmet le signal PWM.

Il est risqué d'alimenter directement votre servomoteur avec une sortie 5 V du Raspberry Pi, car il pourrait consommer un courant trop intense.  Autant que possible, utilisez une alimentation externe pour votre servomoteur.

Il est important que toutes les masses soient connectées ensemble (celle du Raspberry Pi, celle du servomoteur, et celle (borne négative) de l'alimentation utilisée pour le servomoteur).

Le fil qui achemine le signal PWM est branché la broche 12 (numérotation board), aussi appelée GPIO 18 (numérotation BCM).



Des exemples de script

Le premier script nous permettra de trouver par essai/erreur les valeurs de rapport cyclique correspondant aux positions extrêmes de votre servomoteur.  Au départ, le rapport cyclique est réglé automatiquement à 7 (ce qui devrait avoir pour effet de placer votre servomoteur environ à sa position médiane).  On demande ensuite à l'utilisateur d'entrer au clavier le rapport cyclique désiré.  Avec mon servo, la position minimale était atteinte avec un rapport cyclique de 3 (si j'entrais 2, le servo demeurait à la même position qu'à 3), et la position maximale était atteinte avec un rapport cyclique de 11 (là encore, si j'entrais 12, le servo demeurait à la même position qu'à 11).  Notez que vous n'êtes pas limité aux nombres entiers:  vous pouvez écrire "9.35", par exemple.



Vous remarquerez peut-être que plutôt que demeurer sagement immobile à la position que vous avez demandée (comme il le ferait si vous le contrôliez avec un Arduino), votre servomoteur tremblote un peu.  Si j'ai bien compris, c'est l'aspect "multitâche" du système d'exploitation du Raspberry Pi qui est la cause de ces vibrations.  Le Raspberry Pi ne consacre pas 100% de son temps à votre programme en python, ce qui cause certaines irrégularités dans le signal PWM transmis au servomoteur.

Si ce tremblement constitue un irritant majeur, vous pouvez déléguer le contrôle du servomoteur à un dispositif en temps réel comme l'Arduino (vous pouvez vous référer à de précédents articles de blog pour établir une communication entre le Raspberry Pi et l'Arduino par USB, ou par RF 433 MHz); vous pouvez également utiliser un circuit intégré spécialement conçu pour cette tâche.

Voici un deuxième script grâce auquel le servomoteur est toujours en mouvement:  il tourne lentement dans une direction, puis revient rapidement à son point de départ afin de recommencer son cycle.  Avant d'exécuter ce script, il est préférable d'avoir d'abord trouvé les valeurs limites du rapport cyclique au moyen du script précédent, et d'utiliser ces valeurs à la place de celles que j'ai placées (qui correspondent au caractéristiques de mon servo).




À lire également

On peut aussi contrôler un servomoteur avec une carte Arduino, un module ESP8266 ou ESP32, une carte STM32 Nucleo, un microcontrôleur PIC, etc.

D'autre part, vous trouverez sur cette page la liste des billets concernant le Raspberry Pi.

Yves Pelletier   (TwitterFacebook)

5 commentaires:

  1. Bonjour, déjà merci pour vos tutos, ça aide bien, en revanche j'ai essayé cette manip :

    "vous pouvez écrire "9,35", par exemple."

    Perso chez moi ça me plante le programme des qu'il y a une virgule...

    Merci

    RépondreSupprimer
    Réponses
    1. Ça fonctionne mieux avec un point décimal plutôt qu'une virgule?

      Supprimer
  2. Bonjour, super tuto ! Je viens de tester avec un moteur TURNIGY TGY-50090M un servo de 9gr avec un torque de 1.6kg. Le premier script que j'ai testé marche bien par contre le servo moteur devient très chaud immédiatement, problème de branchement ? Branché comme le schéma en haut de page

    RépondreSupprimer
  3. Bonjour,

    Merci bcp pour ce tuto, très clair. Je me demande par contre si pour éviter l'effet de tremblote du servo, il n'y aurait pas moyen de :
    - démarrer le pwm
    - changer le rapport cyclique
    - stopper le pwm,
    ceci à chaque saisie d'une valeur. Avec l'espoir que le servo ne retourne pas à une position 0.

    RépondreSupprimer
  4. Bonjour,

    Une ligne est a adapter pour Python 3 au niveu de la ligne 32. raw_input devient input

    rapport = input ("Rapport cyclique que tu desires: ")

    RépondreSupprimer