Servomoteur à commande de position

Module Grove : Afficheur 4 digits / 7 segments

Présentation

Un servomoteur est un moteur à courant continu capable d'atteindre et de maintenir un angle malgré les contraintes qu'il subit.

Les principales caractéristiques d'un servomoteur sont :

  • son couple : c'est-à-dire sa capacité à faire tourner son axe ou à maintenir sa position ;
  • sa vitesse de rotation.

Fonctionnement

Branchement

Un servomoteur dispose de trois fils :

  • deux fils pour l'alimenter (fil marron ou noir pour la masse et fil rouge pour la phase) ;
  • un fil pour le piloter (fil orange ou jaune)

Attention : l'alimentation du moteur par la carte microbi (dont la tension haute est de 3,3 V) peut être insuffisante pour le moteur. Dans ce cas, il faut utiliser une alimentation externe et faire les branchements du schéma ci-dessous :

Pilotage

Le pilotage du servomoteur se fait à l'aide d'une tension modulée (MLI Modulation à Largeur d'Impulsion en français ou PWM Pulse Width Modulation en anglais).

Concrètement, la tension de pilotage est une un signal périodique composé d'impulsions régulières d'une durée réglable.

C'est le rapport de la durée de l'impulsion sur la période du signal qui définit l'angle de l'axe du moteur.

Programmation

Les sorties analogiques de la carte microbit délivrent des signaux modulés.

La méthode set_analog_periode(periode) disponible pour les sorties analogiques permet de définir la période du signal en ms.

La méthode write_analog(valeur) permet, quant à elle, de définir l'allure du signal par l'intermédiaire du paramètre valeur :

  • Si valeur = 0 alors le rapport (durée impulsion)/(période du signal) = 0
  • Si valeur = 1023 alors le rapport (durée impulsion)/(période du signal) = 1

Spécifications du servomoteur

Les éléments de la spécification du servomoteur qu'il faut prendre en compte pour le piloter sont :

  • la fréquence ou la période du signal à utiliser ;
  • la correspondance entre la durée de l'impulsion et l'angle pris par l'axe du moteur ;
  • l'angle de rotation maximale de l'axe du moteur.

Exemple : données pour le servomoteur SG90

Fréquence du signal : 50Hz (soit une période de 20 ms)

Angle de rotation maximale du moteur : 180°

Correspondance entre le signal et l'angle :

Durée de l'impulsion Paramètre valeur de la méthode write_analog(valeur)
Position minimale environ 1 ms round(1 / 20 × 1024) = 51
Position intermédiaire 1,5 ms round(1.5 / 20 × 1024) = 76
Position maximale environ 2 ms round(2 / 20 × 1024) = 102

Remarque : les valeurs minimales et maximales sont à tester.

Exemple de code python

Exemple simple testé sur un servomoteur NG90

from microbit import *
pin0.set_analog_period(20)
for _ in range(5):
    pin0.write_analog(31) # valeur testée pour avoir l'angle minimal
    sleep(1000)
    pin0.write_analog(122) # valeur testée pour avoir l'angle maximal
    sleep(1000)
pin0.write_analog(0) # permet d'arréter le moteur

Une classe pour simplifier la programmation

from microbit import *
class ServoMoteur:
    """
    Control d'un servomoteur.
    Args:
        pin (pin0, pin1 ou pin2): pin de connection.
        freq (int): fréquence du signal en Hz.
        min_us (int): durée minimale du cycle actif (en µs).
        max_us (int): durée maximale du cycle actif (en µs).
        angle (int): plage de l'angle de rotation du servomoteur (en degrés).
    """

    def __init__(self, pin, freq=50, min_us=700, max_us=2300, plage_degrees=180):
        self.min_us = min_us
        self.max_us = max_us
        self.us = 0
        self.freq = freq
        self.plage_degrees = plage_degrees
        self.periode = round((1/self.freq) * 1000)  # hertz to miliseconds
        self.pin = pin
        self.pin.set_analog_period(self.periode)

    def write_us(self, us):
        us = min(self.max_us, max(self.min_us, us))
        duty = round(us * 1024 * self.freq / 1000000)
        self.pin.write_analog(duty)

    def write_angle(self,angle):
        total_range = self.max_us - self.min_us
        us = self.min_us + total_range * angle // self.plage_degrees
        self.write_us(us)

    def off(self):
        self.pin.write_digital(0)  # turn the pin off


# Utilisation de la classe

moteur = ServoMoteur(pin0)
while True:
    test_a = button_a.is_pressed()
    test_b = button_b.is_pressed()
    if test_a or test_b:
        if test_a:
            display.show('A')
            moteur.write_angle(0)
        else:
            display.show('B')
            moteur.write_angle(180)
    else:
        display.clear()
        moteur.off()
    sleep(50)