Étiquettes : , , , ,
0
(0)

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

Références

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?