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 (Twitter, Facebook)
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

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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: latin-1 -*- | |
''' | |
Contrôle d'un servomoteur avec un Raspberry Pi | |
Le programme demande à l'utilisateur d'entrer le rapport cyclique | |
(duty cycle) désiré, et le servomoteur se met à la position correspondante. | |
Pour plus d'informations: | |
http://electroniqueamateur.blogspot.com/2015/11/controler-un-servomoteur-en-python-avec.html | |
''' | |
import RPi.GPIO as GPIO | |
servo_pin = 12 # équivalent de GPIO 18 | |
GPIO.setmode(GPIO.BOARD) # notation board plutôt que BCM | |
GPIO.setup(servo_pin, GPIO.OUT) # pin configurée en sortie | |
pwm = GPIO.PWM(servo_pin, 50) # pwm à une fréquence de 50 Hz | |
rapport = 7 # rapport cyclique initial de 7% | |
pwm.start(rapport) | |
while True: | |
print ("Rapport cyclique actuel: " , rapport) | |
rapport = input ("Rapport cyclique desire: ") | |
pwm.ChangeDutyCycle(float(rapport)) | |
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: latin-1 -*- | |
''' | |
Contrôle d'un servomoteur avec un Raspberry Pi | |
Le servo tourne lentement dans une direction, et | |
retourne rapidement à sa position de départ. | |
Pour plus de détails: | |
http://electroniqueamateur.blogspot.com/2015/11/controler-un-servomoteur-en-python-avec.html | |
''' | |
import RPi.GPIO as GPIO | |
import time | |
servo_pin = 12 # gpio18 | |
depart = 3 # rapport cyclique pour que le servo | |
# soit au début de son mouvement | |
# à ajuster pour votre servo! | |
arrivee = 11 # rapport cyclique pour que le servo | |
# soit à la fin de son mouvement | |
# à ajuster pour votre servo! | |
GPIO.setmode(GPIO.BOARD) # notation board plutôt que BCM | |
GPIO.setup(servo_pin, GPIO.OUT) # pin configurée en sortie | |
pwm = GPIO.PWM(servo_pin, 50) # pwm à une fréquence de 50 Hz | |
position = depart # on commence à la position de départ | |
pwm.start(depart) # on commence le signal pwm | |
while True: | |
if position < arrivee: # si nous ne sommes pas pas arrivés, | |
# nous avançons un peu | |
pwm.ChangeDutyCycle(float(position)) | |
position = position + 0.1 | |
time.sleep (0.1) | |
else: | |
position = depart # si nous sommes arrivés, | |
# retour à la position de départ | |
pwm.stop |
À 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 (Twitter, Facebook)
Bonjour, déjà merci pour vos tutos, ça aide bien, en revanche j'ai essayé cette manip :
RépondreSupprimer"vous pouvez écrire "9,35", par exemple."
Perso chez moi ça me plante le programme des qu'il y a une virgule...
Merci
Ça fonctionne mieux avec un point décimal plutôt qu'une virgule?
SupprimerBonjour, 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épondreSupprimerBonjour,
RépondreSupprimerMerci 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.
Bonjour,
RépondreSupprimerUne ligne est a adapter pour Python 3 au niveu de la ligne 32. raw_input devient input
rapport = input ("Rapport cyclique que tu desires: ")