Lorsque vous voulez piloter plusieurs servomoteurs et que vous avez besoin de beaucoup d’entrées/sorties disponibles pour faire fonctionner votre robot (pour piloter Hexana, par exemple), il est plus pratique d’utiliser un contrôleur série de servomoteur tel que le Mini Maestro de Pololu.
Prérequis: Programmez avec Arduino, Communiquez avec votre Arduino, Pilotez un servo avec Arduino
Matériel
- Ordinateur
- Carte Arduino UNO
- Câble USB pour connecter la carte Arduino à l’ordinateur
- Câble USB mini B pour connecter la carte Maestro à l’ordinateur
- 3x câble mâle/mâle
- Contrôleur série Mini Maestro x1
- 1 ou plusieurs servomoteurs
Présentation du contrôleur série Maestro
Lorsqu’on utilise plusieurs servomoteurs, typiquement, lorsque le nombre de servomoteurs dépasse le nombre de sortie de la carte électronique, il est nécessaire d’utiliser un contrôleur de servomoteur externe au microcontrôleur principal. Il en existe plusieurs types et certains vont même vous permettre de piloter jusqu’à 32 servomoteurs en même temps.
Celle que je vais vous présenter est la carte Maestro de chez Pololu. Elle existe sous différents formats 6, 12, 18 ou 24 sorties pour servomoteur.
Avec cette solution, la carte principale (la carte maître, Arduino ou Raspberry Pi) donne les ordres au contrôleur (carte esclave) via un port série qui les transmet et fournit la puissance aux servomoteurs.
Cela permet de :
- protéger le matériel en découplant la partie puissance de la partie commande
- réduire le coût en diminuant le nombre d’entrée-sortie de la carte principale
- utiliser différents types de carte (pour piloter 32 servomoteurs vous pouvez désormais utiliser une Raspberry PI ou encore une carte Arduino Mini !)
Retrouvez toutes les infos sur la série de driver Mini Maestro sur le site de Pololu.
Configuration et test préalable du contrôleur série Maestro
Pour configurer le contrôleur série Maestro, il vous suffit de télécharger le logiciel et les pilotes pour Windows (ou pour Linux). Vous pouvez retrouver les procédures d’installation en anglais pour Windows et pour Linux en suivant les liens respectifs.
Une fois le logiciel Maestro Control Center et les pilotes installés, branchez le contrôleur Maestro au PC en utilisant le câble USB.
Lorsque le contrôleur est connecté vous pouvez voir son numéro d’identification en haut à gauche et retrouver ses paramètres de configuration dans l’onglet « Serial Settings ».
Vous pouvez tester le contrôleur série Maestro et vos servomoteurs à l’aide du logiciel sur l’onglet « Status ». N’oubliez pas de brancher une alimentation sur le bornier du Mini Maestro sinon le servomoteur ne bougera pas.
Les servomoteurs peuvent avoir des paramètres de fonctionnement différents. Vous pouvez modifier les paramètres des sorties du contrôleur série dans l’onglet « Channel Settings ». A vous de tester les paramètres qui correspondent à votre servomoteur.
Schéma de connexion
La carte Arduino accepte une tension d’alimentation entre 7 et 12V et peut être alimenter par le port USB de l’ordinateur. La logique du contrôleur série est alimentée par la sortie 5V de l’Arduino et les servomoteurs sont alimenté par une batterie. Il peut être nécessaire de rajouter un régulateur de tension si la tension d’alimentation est différente de la tension nominale des servomoteurs (par exemple : une Lipo 2S délivre 7,4V alors que la tension nominale d’un servomoteur SG90 est de 5V).
Les bornes 2(Rx) et 3(Tx) de la carte Arduino sont connectées aux bornes TX et RX de la carte Maestro respectivement.
Le schéma de câblage est facilement transposable pour les contrôleurs série Mini Maestro 6 12 et 18 voies.
Code de base pour piloter un contrôleur série Maestro
Pour piloter le contrôleur série avec une carte Arduino, il faut envoyer une séquence de commande via un port série. Le programme suivant permet d’envoyer une commande de position aux différentes voies d’un Mini Maestro à l’aide du moniteur série de l’IDE Arduino.
Tout d’abord, nous initialisons le port série permettant de communiquer avec la carte Maestro.
#include <Maestro.h> Maestro maestro(2,3);
Puis, nous ajoutons une fonction permettant de recevoir les données envoyées via le moniteur série.
void readSerialPort(){ while (Serial.available()) { delay(10); if (Serial.available() >0) { char c = Serial.read(); //gets one byte from serial buffer msg += c; } } }
Pour des raisons pratiques, nous n’envoyons qu’une commande via le moniteur. Nous créons donc une fonction pour séparer l’ID du servo de la valeur de position à l’aide du caractère séparateur « x ».
void convertMsgToCmd(){ if (msg.length() >0) { Serial.println(msg); sep = msg.indexOf('x'); m1 = msg.substring(0, sep); //get servo id m2 = msg.substring(sep+1, msg.length()); //get servo pos servoId=-1; servoPos=-1; char carray1[6]; //magic needed to convert string to a number m1.toCharArray(carray1, sizeof(carray1)); servoId = atoi(carray1); char carray2[6]; m2.toCharArray(carray2, sizeof(carray2)); servoPos = atoi(carray2); msg=""; } }
Enfin, nous envoyons ces données à la carte Maestro en utilisant le protocole Pololu qui se résume en une séquence de bytes contenant la sélection du protocole, l’ID de la carte maestro, la sélection de la commande et la valuer de la position.
void setTarget(unsigned char servo, unsigned int target){ /* envoie la séquence de commande au contrôleur série Maestro pour actionner le servomoteur*/ const int deviceId = 0x0C; //controller ID 12 const int startByte = 0xAA; // Protocol selection const int targetCmd = 0x04; // Command ID maestro.write(startByte); //start byte maestro.write(deviceId); //device id maestro.write(targetCmd); //command number maestro.write(servo); //servo number maestro.write(target & 0x7F); // Send first 4bits maestro.write((target >> 7) & 0x7F); // Send last 4bits delay(3); }
Mis bout à bout, cela nous donne le code suivant:
/*---------------------------------------------------------------------------------------- Ce programme permet de piloter différents servomoteurs à l'aide du moniteur série. Tapez YxZZZZ dans le terminal Y entre 0 et 5 pour Mini Maestro 6 voies (selon Maestro) ZZZZ entre 4000 et 8000 (selon servomoteur) Ex: Tapez 0x6000 dans le moniteur série Materiel: - 1x servomoteur ou plus - 1x Mini Maestro - 1x Arduino Auteur: Xavier Wiedmer http://www.aranacorp.com ----------------------------------------------------------------------------------------*/ #include "SoftwareSerial.h" SoftwareSerial maestro(2,3); String msg, m1, m2; int sep, servoId=-1, servoPos=-1; void setup() { Serial.begin(9600); pinMode(2, INPUT); pinMode(3, OUTPUT); maestro.begin(9600); Serial.println(F("Waiting for command (YxZZZZ): ")); } void loop() { readSerialPort(); convertMsgToCmd(); //Apply command to servo if (servoId>=0 && servoPos>=0 && servoId<18 && servoPos>=500 && servoPos<=10000) { setTarget(servoId, servoPos); Serial.print(F("Command ")); Serial.print(servoPos); Serial.print( F(" sent ")); Serial.print(F("to servo ")); Serial.println(servoId); servoId=-1; servoPos=-1; Serial.println(F("Waiting for command ... ")); } } void setTarget(unsigned char servo, unsigned int target){ /* envoie la séquence de commande au contrôleur série Maestro pour actionner le servomoteur*/ const int deviceId = 0x0C; //controller ID 12 const int startByte = 0xAA; // Protocol selection const int targetCmd = 0x04; // Command ID maestro.write(startByte); //start byte maestro.write(deviceId); //device id maestro.write(targetCmd); //command number maestro.write(servo); //servo number maestro.write(target & 0x7F); // Send first 4bits maestro.write((target >> 7) & 0x7F); // Send last 4bits delay(3); } void readSerialPort(){ /*Permet de lire une commande provenant du terminal Arduino*/ while (Serial.available()) { delay(10); if (Serial.available() >0) { char c = Serial.read(); //gets one byte from serial buffer msg += c; } } } void convertMsgToCmd(){ /*convertit le message provenant du terminal en commande à envoyer au contrôleur série*/ if (msg.length() >0) { Serial.println(msg); sep = msg.indexOf('x'); // expect a string like 0x0021 containing the two servo positions m1 = msg.substring(0, sep); //get servo id m2 = msg.substring(sep+1, msg.length()); //get servo pos servoId=-1; servoPos=-1; char carray1[6]; //magic needed to convert string to a number m1.toCharArray(carray1, sizeof(carray1)); servoId = atoi(carray1); char carray2[6]; m2.toCharArray(carray2, sizeof(carray2)); servoPos = atoi(carray2); msg=""; } }
Librairie pour piloter un contrôleur série Maestro
Si vous utilisez des contrôleurs série Maestro dans différents projets, il est plus pratique de coder les règles de communication dans une librairie. Vous pouvez ainsi réutiliser la librairie sans faire de copier/coller et alleger votre code. Vous pouvez écrire votre propre librairie ou utiliser celle créée par Ryan Mulligan sur Github.
Pour créer une librairie, nous créons deux fichiers .cpp et .h que nous copions dans un dossier Documents\Arduino\libraries\Maestro.
le fichier Maestro.h
/*****************************************************************\ * Library header : Maestro.h * Author : X.Wiedmer * Version : v00 * Date : 05/03/2015 * Revision : * v01 - 05/03/2015 * Description : * Library to setup Maestro board * www.aranacorp.com \*****************************************************************/ #ifndef Maestro_h #define Maestro_h // Libraries #include "Arduino.h" #include "SoftwareSerial.h" /******************************************************************\ * CLASS DESCRIPTION \******************************************************************/ class Maestro { public: Maestro(int pinRx, int pinTx); //~Maestro(); void setTarget(unsigned char servo, unsigned int target); void stop(unsigned char servo); void begin(unsigned int baudrate); private: int _pinRx; int _pinTx; int _id; SoftwareSerial *_maestroSerial; }; #endif
Le fichier Maestro.cpp
/*****************************************************************\ * Library : Maestro.cpp * Author : X.Wiedmer * Version : v00 * Date : 05/03/2015 * Revision : * v01 - 05/03/2015 * Description : * Library to setup Maestro board * www.aranacorp.com \*****************************************************************/ //Libraries #include "Arduino.h" #include "Maestro.h" #include "SoftwareSerial.h" // Parameters #define DELAY_WRITE 3 //set up maestro configuration #define deviceId 0x0C //12 #define startByte 0xAA // // Command list #define targetCmd 0x04 // /******************************************************************\ * PRIVATE FUNCTION: Constructor * * PARAMETERS: * ~ void * * DESCRIPTIONS: * object constructor \******************************************************************/ Maestro::Maestro(int pinRx, int pinTx) { pinMode(pinRx, INPUT); pinMode(pinTx, OUTPUT); _pinRx = pinRx; _pinTx = pinTx; _maestroSerial = new SoftwareSerial(pinRx,pinTx); } /******************************************************************\ * PRIVATE FUNCTION: begin * * PARAMETERS: * ~ baudrate (serial port speed) * * DESCRIPTIONS: * Initialize serial port \******************************************************************/ void Maestro::begin(unsigned int baudrate) { _maestroSerial->begin(baudrate); } /******************************************************************\ * PRIVATE FUNCTION: setTarget * * PARAMETERS: * ~ servo ID number, target specified with integer * * DESCRIPTIONS: * Send sequence of command so that the maestro board send the right * pwm value to set servo to the desired position \******************************************************************/ void Maestro::setTarget(unsigned char servo, unsigned int target) { _maestroSerial->write(startByte); //start byte _maestroSerial->write(deviceId) ; //device id _maestroSerial->write(targetCmd); //command number _maestroSerial->write(servo); //servo number _maestroSerial->write(target & 0x7F); // Send first 4bits _maestroSerial->write((target >> 7) & 0x7F); // Send last 4bits delay(DELAY_WRITE); } /******************************************************************\ * PRIVATE FUNCTION: stop * * PARAMETERS: * ~ servo ID number * * DESCRIPTIONS: * Send sequence of command so that the maestro send nothing to the * the servo \******************************************************************/ void Maestro::stop(unsigned char servo) { _maestroSerial->write(startByte); //start byte _maestroSerial->write(deviceId) ; //device id _maestroSerial->write(targetCmd); //command number _maestroSerial->write(servo); //servo number _maestroSerial->write((byte)0x00); // Send first 4bits _maestroSerial->write((byte)0x00); // Send last 4bits delay(DELAY_WRITE); }
Le programme ressemble alors à cela:
/*---------------------------------------------------------------------------------------- Ce programme permet de piloter différents servomoteurs à l'aide du moniteur série. Tapez YxZZZZ dans le terminal Y entre 0 et 5 pour Mini Maestro 6 voies (selon Maestro) ZZZZ entre 4000 et 8000 (selon servomoteur) Ex: Tapez 0x6000 dans le moniteur série Materiel: - 1 servomoteur ou plus - 1x Mini Maestro - 1x Arduino Auteur: Xavier Wiedmer http://www.aranacorp.com ----------------------------------------------------------------------------------------*/ #include <Maestro.h> Maestro maestro(2,3); String msg, m1, m2; int sep, servoId=-1, servoPos=-1; /************** Main Program **************/ void setup() { Serial.begin(9600); maestro.begin(9600); Serial.println("Waiting for command (YxZZZZ): "); } void loop() { readSerialPort(); convertMsgToCmd(); //Apply command to servo if (servoId>=0 && servoPos>=0 && servoId<18 && servoPos>=500 && servoPos<=10000) { maestro.setTarget(servoId, servoPos); Serial.print(F("Command ")); Serial.print(servoPos); Serial.print( F(" sent ")); Serial.print(F("to servo ")); Serial.println(servoId); servoId=-1; servoPos=-1; Serial.println(F("Waiting for command ... ")); } } /************** Functions **************/ void readSerialPort(){ while (Serial.available()) { delay(10); if (Serial.available() >0) { char c = Serial.read(); //gets one byte from serial buffer msg += c; } } } void convertMsgToCmd(){ if (msg.length() >0) { Serial.println(msg); sep = msg.indexOf('x'); m1 = msg.substring(0, sep); //get servo id m2 = msg.substring(sep+1, msg.length()); //get servo pos servoId=-1; servoPos=-1; //declare as number char carray1[6]; //magic needed to convert string to a number m1.toCharArray(carray1, sizeof(carray1)); servoId = atoi(carray1); char carray2[6]; m2.toCharArray(carray2, sizeof(carray2)); servoPos = atoi(carray2); msg=""; } }
N’hésitez pas à nous laisser un commentaire ou à nous envoyer un message si vous rencontrez des difficultés pour piloter votre contrôleur série.
Applications
- Pilotez des robots quadripode, hexapode ou octopode
Références
- Et plus particulièrement référence servo https://www.arduino.cc/en/Reference/Servo
- maestro user guide https://www.pololu.com/docs/0J40
- Apprenez à utliser le port série avec Arduino
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie
Super intéressant et bravo pour votre article. J’ai fabriqué un bras uArm et je passe à la partie commande des servomoteurs. Je pense utiliser un contrôleur Maestro pour gérer la vitesse des servomoteurs. Bonne continuation.
Merci beaucoup pour votre commentaire. Si vous avez besoin d’aide n’hésitez pas!