Quando se pretende controlar vários servomotores e são necessárias muitas entradas/saídas livres para operar o seu robô (para controlar o Hexana, por exemplo), é interessante usar um controlador serial de servomotor, como o Mini Maestro da Pololu.
Pré-requisitos: Programar com o Arduino, Comunicar com o seu Arduino, Controlar um servomotor com o Arduino
Material
- Computador
- Placa Arduino UNO
- Cabo USB para ligar o Arduino ao computador
- Cabo USB mini B para ligar o cartão Maestro ao computador
- 3 cabos Dupont M/M
- Controlador serial Mini Maestro
- 1 ou mais servomotores
Introdução ao controlador serial Maestro
Quando utilizamos vários servomotores, especialmente quando o número de servomotores excede o número de saídas da placa eletrônica, é necessário usar um controlador de servomotor externo ao microcontrolador principal. Há vários tipos diferentes, e alguns permitem pilotar até 32 servomotores ao mesmo tempo.
Vamos apresentar aqui a placa Maestro da Pololu. Ela existe em diferentes formatos, com 6, 12, 18 ou 24 saídas para servomotor.
Com esta solução, a placa principal (a placa master Arduino ou Raspberry Pi) dá ordens ao controlador (placa slave) através de uma porta serial, que transmite as ordens e fornece energia aos servomotores.
Isso permite :
- proteger o equipamento, separando a parte de energia da parte de controle;
- reduzir o custo, diminuindo o número de entradas e saídas da placa principal;
- usar diferentes tipos de placas (permite controlar 32 servomotores usando um Raspberry Pi ou mesmo um Arduino Mini).
As informações completas sobre o condutor serial Mini Maestro podem ser encontradas no site da Pololu.
Configuração e teste prévio do controlador serial Maestro
Para configurar o controlador serial Maestro, basta fazer o download do software e dos drivers para Windows (ou para Linux). Os procedimentos de instalação para Windows e para Linux estão disponíveis em inglês nos respectivos links.
Uma vez instalado o software Maestro Control Center e os drivers, conecte o controlador Maestro ao PC com o cabo USB.
Quando o controlador é ligado, o seu número de identificação aparece no canto superior esquerdo. As configurações podem ser acessadas pela aba “Serial Settings” (configurações seriais).
Utilize o software para testar o controlador serial Maestro e os servomotores, na aba “Status”. Não se esqueça de ligar uma fonte de alimentação ao bloco terminal do Mini Maestro, pois do contrário o servomotor não se moverá.
Os servomotores podem ter diferentes configurações de funcionamento. As configurações das saídas do controlador serial podem ser alteradas na aba “Channel Settings” (Configurações de Canal). Teste as configurações que se adaptam ao seu servomotor.
Esquema de ligação
A placa Arduino aceita uma tensão de alimentação entre 7 e 12V e pode ser alimentada pela entrada USB do computador. A lógica do controlador serial é alimentada pela saída de 5V do Arduino, e os servomotores são alimentados por uma bateria. Pode ser necessário acrescentar um regulador de tensão, caso a tensão de alimentação seja diferente da tensão nominal dos servomotores (por exemplo: um Lipo 2S fornece 7,4V enquanto a tensão nominal de um servomotor SG90 é de 5V).
Os terminais 2(Rx) e 3(Tx) da placa Arduino são ligados aos terminais TX e RX da placa Maestro, respectivamente.
O esquema de ligação pode ser facilmente transposto para os controladores seriais Mini Maestro 6, 12 e 18 canais.
Código básico para pilotar um controlador serial Maestro
Para pilotar o controlador serial com uma placa Arduino, é preciso enviar uma sequência de comandos através de uma porta serial. O programa a seguir permite enviar um comando de posição para os diferentes canais de um Mini Maestro utilizando o monitor serial da IDE do Arduino.
Antes de tudo, inicializamos a porta serial utilizada para comunicar com a placa Maestro.
#include <Maestro.h> Maestro maestro(2,3);
Depois, adicionamos uma função para receber os dados enviados pelo monitor serial.
void readSerialPort(){ while (Serial.available()) { delay(10); if (Serial.available() >0) { char c = Serial.read(); //gets one byte from serial buffer msg += c; } } }
Por razões práticas, enviamos apenas um comando através do monitor. Criamos então uma função para separar o ID do servomotor do valor da posição utilizando o caractere separador “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=""; } }
Finalmente, enviamos estes dados para a placa Maestro utilizando o protocolo Pololu, que nada mais é que um sequência de bytes contendo a seleção do protocolo, o ID da placa Maestro, a seleção do comando e o valor da posição.
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); }
Tudo isso junto resulta no seguinte código:
/*---------------------------------------------------------------------------------------- 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=""; } }
Biblioteca para pilotar um controlador serial Maestro
Se for utilizar controladores seriais Maestro em diferentes projetos, é prático codificar as regras de comunicação numa biblioteca. Desta forma, pode reutilizar a biblioteca sem copiar e colar e tornar o seu código mais leve. Pode escrever a sua própria biblioteca ou usar a biblioteca criada por Ryan Mulligan no Github.
Para criar uma biblioteca, criamos dois arquivos .cpp e .h que copiamos para a pasta Documents\Arduino\libraries\Maestro.
O arquivo 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
O arquivo 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); }
O programa fica assim:
/*---------------------------------------------------------------------------------------- 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=""; } }
Fique à vontade para comentar ou nos enviar uma mensagem se tiver dificuldades com o seu controlador serial.
Aplicações
- Controlar robôs de muitas pernas, como o quadripode, hexapode ou o octopode
Referências
- Referência para servomotores Arduino https://www.arduino.cc/en/Reference/Servo
- maestro user guide https://www.pololu.com/docs/0J40
- Aprenda a utilizar a porta serial com Arduino
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie