Comme indiqué sur la figure ci-contre, tous les modèles de servomoteurs doivent être commandés via un signal codé en largeur d'impulsion. La largeur de l'impulsion doit varier entre 1ms et 2ms et constitue la consigne qui détermine l'angle du servomoteur. 1ms correspond à 0° de consigne et 2ms correspond à 180° de consigne. On répète l'impulsion toutes les 20ms.
Le but de la commande PWM, disponible sur certaines sorties digitales d'un grove PI+ via la fonction analogWrite(port,valeur), est de produire une tension moyenne comprise entre 0V (pour une consigne à 0) et 5V (pour une consigne à 255) et proportionnelle à la valeur de la consigne en jouant sur le rapport cyclique d'un signal de fréquence 500Hz (c'est à dire dont la période est de 2ms).
Comme le fonctionnement de la fonction analogWrite() diffère un peu du besoin, on ne va pas pouvoir lui fournir une consigne conforme à ce que le servomoteur souhaite recevoir pour fonctionner exactement comme il le devrait. On va donc devoir calibrer les valeurs de commande en fonction de la façon dont le servomoteur réagit à celles-ci.
La valeur 0 produisant un signal toujours à l'état bas et la valeur 255 produisant un signal toujours à l'état haut, on dispose de deux façons de ne pas envoyer de consigne (via l'absence d'impulsion) et donc de laisser le servo dans sa position actuelle. Dans le programme de calibrage, après avoir envoyé un semblant de consigne (via la valeur saisie au clavier), pendant le temps nécessaire pour que le servomoteur change d'angle (500ms par exemple), on impose de nouveau la valeur 0.
import time from grovepi import * servo = 5 pinMode(servo,"OUTPUT") def pilote(): try: while True: v=int(input("valeur entre 1 et 254 ? ")) analogWrite(servo,v) time.sleep(0.5) analogWrite(servo,0) except IOError: print ("Erreur servo") except KeyboardInterrupt: analogWrite(servo,0) print() pilote()
La partie matériel du Grove PI+ est en capacité de piloter correctement des servomoteurs, mais son firmware officiel ne contient pas, à ce jour, la partie logiciel nécessaire à ce pilotage.
En modifiant le firmware, on pourrait y intégrer la bibliothèque de pilotage de servomoteur disponible, pour le micro-controleur du Grove PI+, à l'URL : https://www.arduino.cc/reference/en/libraries/servo/. Puis, on pourrait rendre disponible, via la liaison I2C qui sert à piloter le grove PI+ depuis le raspberry PI, les 8 fonctions suivantes :
Pour cela, il faudrait modifier le fichier ~/GrovePI/Firmware/Source/grovepi/src/grovepi.ino et y mettre ce nouveau code.
Après compilation du firmware, en utilisant, sous Windows l'IDE, "Visual Studio Code" avec le plugin "platformio", on obtiendrait le fichier grove_pi_firmware.hex à placer sur le raspberry PI dans le répertoire ~/GrovePI/Firmware. Il faut ensuite procéder au flashage du firmware via la commande :
(cd ~/GrovePI/Firmware ; ./firmware_update.sh)
Enfin, il faut ajouter également 8 fonctions, dans la bibliothèque Python qui a été installée, pour utiliser le grove PI+ depuis le langage Python.
Pour modifier la bibliothèque, il faut mettre :
Ensuite, il faut passer, sur le raspberry PI, la commande suivante :
(cd ~/GrovePI/Software/Python ; sudo python3 setup.py install)
Remarque : Le firmware proposé permet la gestion simultannée d'un servomoteur sur chaque port digital de D2 à D8 (valeur 2 à 8 pour le paramètre pin). La valeur du paramètre angle peut être comprise entre 0 et 180.
On peut également ajouter, dans le répertoire ~/GrovePI/Projet, un sous répertoire Servomotor et y déposer l'exemple suivant (sous le nom "servo_input.py") :
import time from grovepi import * servomotor0_pin = 5 #Port for servomotor0 while True: try: v=int(input("valeur entre 0 et 180 ? ")) servoAttach(servomotor0_pin) servoWrite(servomotor0_pin,v) time.sleep(0.500) servoDettach(servomotor0_pin) except KeyboardInterrupt: servoDetach(servomotor0_pin) break except (IOError,TypeError) as e: print("Error")
On pourrait également y déposer cet autre exemple (sous le nom "servo_range.py") :
import time from grovepi import * servomotor0_pin = 6 #Port for servomotor0 servoAttach(servomotor0_pin) while True: try: v=0 while v<=180: servoWrite(servomotor0_pin,v) time.sleep(0.040) print(servoRead(servomotor0_pin)) v+=1 v=180 while v>=0: servoWrite(servomotor0_pin,v) time.sleep(0.040) print(servoRead(servomotor0_pin)) v-=1 except KeyboardInterrupt: servoDetach(servomotor0_pin) break except (IOError,TypeError) as e: print("Error")
On pourrait également y déposer ce troisième exemple (sous le nom "servo_pot.py") :
import time from grovepi import * servomotor0_pin = 5 #Port D5 for servomotor0 potentiometer = 2 #Port A2 for potentiometer servoAttach(servomotor0_pin) while True: try: v=analogRead(potentiometer) v=int(v*180/1023) servoWrite(servomotor0_pin,v) time.sleep(0.020) except KeyboardInterrupt: servoDetach(servomotor0_pin) break except (IOError,TypeError) as e: print("Error")