Utiliser un servomoteur avec une carte Pi Pico en MicroPython
(Mis à jour le 05/01/2023)
Les servomoteurs, également connus sous le nom de « servo », sont une forme spéciale de moteurs qui peuvent être commandés et maintenir une position angulaire spécifique avec précision. Ils ont un excellent rapport poids puissance. Le servo bleu SG90 de TowerPro, par exemple, offre un couple de 1,5 kg/cm à seulement 9g. Grâce à son faible prix et à sa mise en œuvre facile avec une Pi Pico, il est un choix parfait pour les makers !
Note
Les servos sont très répandus dans le modélisme (direction des roues des voitures télécommandées, commande des gouvernes de dérive et de profondeur sur les avions etc.), mais aussi dans la robotique et l’industrie, comme pour réguler des flux de liquides dans des vannes par exemple.
Prendre en main le fameux servomoteur SG90
La principale différence entre un moteur classique et un servomoteur est que la plupart des servomoteurs peuvent seulement pivoter entre 0 et 180 degrés. Un servomoteur est composé d’un moteur courant continu (CC) standard, d’engrenages pour augmenter le couple (et réduire la vitesse) ainsi que d’un système de régulation. Ce qui est remarquable est que tous ces mécanismes sont intégrés dans un boîtier si petit !
Avertissement
Il est recommandé d’éviter de manipuler manuellement l’axe du servomoteur et de s’arrêter avant la butée, car elle est assez fragile (en plastique).
Fonctionnement d’un servomoteur basique

Un petit moteur à courant continu est lié à un potentiomètre avec un circuit électronique, ce qui permet de réguler la vitesse du moteur en fonction de la position du potentiomètre. Des engrenages sont connectés à l’axe de sortie du moteur pour augmenter le couple et réduire la vitesse de rotation. Lorsque le moteur fonctionne, les engrenages vont faire bouger l’axe principal qui contient le potentiomètre. Si le mouvement s’arrête, le circuit électronique ajuste automatiquement la vitesse du moteur afin de maintenir le bras et le potentiomètre à la même position. Cette caractéristique est utile pour les bras des robots qui ne s’abaissent pas sous leur propre poids lorsque le mouvement s’arrête.
Ce servomoteur bleu SG90 est contrôlé à l’aide d’un signal modulé en largeur d’impulsion (PWM) à une fréquence de 50 Hz, ce qui correspond à une impulsion toutes les 20 ms. Sa position est définie par la durée des impulsions, généralement comprises entre 1 ms et 2 ms.
Comment alimenter le servomoteur avec un Raspberry Pi Pico
La tension d’alimentation optimale de ce servo SG90, selon la fiche technique , est de 5V, mais il semble également fonctionner à 3.3V.
Note
Avec une tension de 5V, le moteur sera plus réactif et la rotation sera beaucoup plus rapide.
Les servomoteurs sont consommateurs en courant, particulièrement quand ils sont soumis à un couple élevé (beaucoup de force exercée sur l’axe de sortie). Le 5V de la carte Raspberry Pi Pico est celui de l’USB, généralement limité à 500mA (sur l’ordinateur). Si l’on veut utiliser plus de deux servomoteurs, il faut alors utiliser une alimentation séparée et veiller à connecter la borne négative de l’alimentation du servomoteur à la broche GND
de la carte.
Branchements du servomoteur SG90 sur la Pi Pico
Le servomoteur SG90 contient 3 fils, 2 pour l’alimentation et 1 pour le signal de commande. Les couleurs des fils sont différentes afin de les distinguer.
Servomoteur SG90 |
Couleur du fil |
RPi Pico |
---|---|---|
|
Marron |
|
|
Rouge |
|
Signal |
Orange |
|
Note
Chez certains modèles, le fil pour le signal est jaune ou blanc et non pas orange.
Toutes les broches de sortie de la Pico peuvent être utilisées pour contrôler le servomoteur car elles sont toutes capables de produire une sortie PWM.
Circuit pour piloter un servomoteur avec une Raspberry Pi Pico
Voici le circuit minimaliste pour utiliser un servomoteur. Il y a une version avec la Pi Pico et une version avec la carte uPesy RP2040 DevKit, une Pi Pico améliorée.


Voici un exemple sur breadboard avec la carte uPesy RP2040 DevKit, où le servo est alimenté en 3.3V.

Piloter un servomoteur depuis la Pico avec un script Python
Il n’est pas indispensable d’utiliser une librairie contrôler le servo c’est uniquement un signal PWM qui indique au servomoteur la position angulaire voulue. Cependant, le calcul des bonnes valeurs peut s’avérer laborieux quand on veut contrôler plusieurs servomoteurs à la fois. Par conséquent, je suggère d’utiliser une librairie déjà en place pour vous faire gagner du temps dans vos projets DIY à venir.
En fait, puisque c’est la largeur d’impulsion du signal PWM qui indique au servomoteur la position angulaire voulue, il n’y a pas vraiment besoin de librairie pour maîtriser la bête 😎. Mais cela peut venir rapidement fastidieux de calculer les bonnes valeurs, surtout quand on veut en piloter plusieurs en même temps. C’est pour cela que je recommanderai d’utiliser plutôt une librairie toute faite pour vous simplifier la vie dans nos projets DIY futurs.
Script Python basique pour piloter le servo avec ses propres calculs
Dans le cas du servo SG90 de TowerPro, la position minimale correspond à un signal PWM avec une largeur de 0.5ms et la position maximale à 2.4ms. En effectuant des calculs, on peut déterminer le duty-cycle du PWM et la valeur en bits de la largeur d’impulsion à mettre dans le script.
Note
Le défi est de trouver la largeur d’impulsion PWM appropriée pour obtenir la position angulaire désirée.
Je ne vais pas détailler les calculs, car on va plutôt utiliser une libraire toute faite pour la suite. Voici un script de base à ce sujet :
from machine import Pin,PWM
from time import sleep
sg90 = PWM(Pin(12, mode=Pin.OUT))
sg90.freq(50)
# 0.5ms/20ms = 0.025 = 2.5% duty cycle
# 2.4ms/20ms = 0.12 = 12% duty cycle
# 0.025*65535=1638
# 0.12*65535=7864
while True:
sg90.duty_u16(1638)
sleep(1)
sg90.duty_u16(7864)
sleep(1)
Piloter un servo via un script Python avec la librairie servo.py
Je vous invite à utiliser cette bibliothèque MicroPython pour contrôler facilement le servomoteur. Elle s’installe comme les autres bibliothèques MicroPython.
Avertissement
Dans la version 1.19 de MicroPython pour la Raspberry Pi Pico, la librairie servo n’est pas incluse par défaut. Seule la Pyboard en est dotée d’une par défaut dans MicroPython.

On peut sauvegarder la librairie sur la Pi Pico directement depuis Thonny IDE
Voici la librairie qu’il faut utiliser:
from machine import Pin, PWM
class Servo:
__servo_pwm_freq = 50
__min_u16_duty = 1640 - 2 # offset for correction
__max_u16_duty = 7864 - 0 # offset for correction
min_angle = 0
max_angle = 180
current_angle = 0.001
def __init__(self, pin):
self.__initialise(pin)
def update_settings(self, servo_pwm_freq, min_u16_duty, max_u16_duty, min_angle, max_angle, pin):
self.__servo_pwm_freq = servo_pwm_freq
self.__min_u16_duty = min_u16_duty
self.__max_u16_duty = max_u16_duty
self.min_angle = min_angle
self.max_angle = max_angle
self.__initialise(pin)
def move(self, angle):
# round to 2 decimal places, so we have a chance of reducing unwanted servo adjustments
angle = round(angle, 2)
# do we need to move?
if angle == self.current_angle:
return
self.current_angle = angle
# calculate the new duty cycle and move the motor
duty_u16 = self.__angle_to_u16_duty(angle)
self.__motor.duty_u16(duty_u16)
def __angle_to_u16_duty(self, angle):
return int((angle - self.min_angle) * self.__angle_conversion_factor) + self.__min_u16_duty
def __initialise(self, pin):
self.current_angle = -0.001
self.__angle_conversion_factor = (self.__max_u16_duty - self.__min_u16_duty) / (self.max_angle - self.min_angle)
self.__motor = PWM(Pin(pin))
self.__motor.freq(self.__servo_pwm_freq)
Pour utiliser la librairie, c’est extrême simple :
Importez la classe
Servo
.Définissez un objet
Servo
qui représente votre servomoteur bleu en spécifiant la broche utilisée pour le piloter.Indiquez la position angulaire souhaitée avec la fonction
.move(angle)
from servo import Servo
import time
sg90_servo = Servo(pin=12) # A changer selon la broche utilisée
while True:
sg90_servo.move(0) # tourne le servo à 0°
time.sleep(1)
sg90_servo.move(90) # tourne le servo à 90°
time.sleep(1)
Avertissement
Vous devrez peut-être modifier les valeurs de l’offset si vous avez un autre type de servomoteur :
class Servo:
__servo_pwm_freq = 50
__min_u16_duty = 1640 - 2 # offset for correction
__max_u16_duty = 7864 - 0 # offset for correction
Voici une vidéo de démonstration avec le code ci-dessus :
