Um dos principais objectivos da robótica é fazer objectos se moverem por si sós. Para isso, é muito comum utilizar motores elétricos, e mais especialmente servomotores. Neste artigo, aprenderemos a programar a placa Arduino de modo a poder controlar um servomotor e veremos um pouco mais sobre o uso das bibliotecas, em especial a Servo.h.
Leia antes: Programar com Arduino
Equipamento
- Computador
- Placa Arduino UNO
- Cabo USB para conectar a placa Arduino ao PC
- 3 x cabos macho/fêmea
- 1 x servomotor
Servomotor
Os servomotores são pequenos concentrados de tecnologia que combinam mecânica e eletrônica. Eles são muito utilizados no modelismo e na robótica. Seu nome vem do fato de eles poderem controlar a sua própria posição (ou velocidade).
Eles são compostos por um motor de corrente contínua, uma caixa de redução e de uma placa de circuito interno, que permitem controlar a posição por meio de um sinal de modulação por largura de pulso (em inglês, PWM – Pulse Width Modulation).
Esquema de ligação
O servomotor é alimentado pelo fio terra preto/marrom (GND) e pelo fio vermelho de tensão da bateria (+5V); ele é controlado por um sinal PWM enviado através do fio amarelo/branco (terminal 9). Dependendo da quantidade de servomotores utilizados e da sua potência, é possível alimentá-lo pelo terminal 5V da placa Arduino. A placa Arduino pode ser alimentada pelo computador através de entrada USB.
Código básico para controle do servomotor
Para controlar a posição do servomotor, é preciso enviar um sinal por modulação de largura de pulso.
//Déclaration des constantes #define UPDATE_TIME 20 //Déclaration des paramètres int servoPin = 9; int pulse = 1500; void setup() { // Code d'initialisation pinMode(servoPin,OUTPUT); Serial.begin(9600); } void loop() { // Code principal digitalWrite(servoPin,HIGH); delayMicroseconds(pulse); digitalWrite(servoPin,LOW); delay(UPDATE_TIME); }
Evidentemente, isso não é muito prático. Seria melhor pedir uma posição ao servomotor. Para tanto, podemos criar uma subfunção que permita converter uma posição em largura de pulso. Isso exige uma pequena dose de matemática: Se temos:
- 5V durante 500µs (0,5ms) correspondem a 0 grau
- 5V durante 1500µs (1,5ms) correspondem a 90 graus
- 5V durante 2500µs (1,5ms) correspondem a 180 graus
Podemos então determinar a regra para conversão da posição angular em largura de pulso.
//Déclaration des constantes #define UPDATE_TIME 20 //Déclaration des paramètres int servoPin = 9; int angle = 50; void setup() { // Code d'initialisation pinMode(servoPin,OUTPUT); Serial.begin(9600); } void loop() { // Code principal digitalWrite(servoPin,HIGH); delayMicroseconds(convertirAngleEnImpulsion(angle)); digitalWrite(servoPin,LOW); delay(UPDATE_TIME); } // Déclaration d'un sous fonction int convertirAngleEnImpulsion(int ang){ float a = 2000.0/180.0; float b = 500; return int(a*ang+b); }
É possível escrever programas muito mais complexos para o Arduino, mas diversas aplicações já podem ser realizadas com essas informações básicas e o conhecimento de certas bibliotecas. Uma delas é a biblioteca do servomotor, que veremos em seguida.
N.B. Este código nos mostra o princípio de um sinal PWM. Na prática, para aplicar um sinal PWM a um servomotor ou a um LED, utilizaremos a função analogWrite() disponível em certo pino do Arduino. Esta função toma um valor inicial entre 0 e 255.
//Déclaration des constantes #define UPDATE_TIME 20 //Déclaration des paramètres int servoPin = 9; void setup() { // Code d'initialisation pinMode(servoPin,OUTPUT); Serial.begin(9600); // Initialise la communication série PC/Arduino } void loop() { // Code principal for(int i=0;i<180;i++){ analogWrite(servoPin,convertirAngleEnPWM(i)); delay(UPDATE_TIME); } delay(200); for(int i=180;i>=0;i--){ analogWrite(servoPin,convertirAngleEnPWM(i)); delay(UPDATE_TIME); } delay(200); } // Déclaration d'un sous fonction int convertirAngleEnPWM(int ang){ float a = 255.0/180.0; return (a*ang); }
Controle do servomotor com a biblioteca Servo.h
Já vimos que é possível criar subfunções com códigos que poderão ser reutilizados sempre que desejarmos. Essas subfunções são armazenadas nas bibliotecas, em ficheiros externos ao programa principal, podendo ser utilizadas em qualquer aplicação. Elas são criadas para organizar o programa com maior clareza e para simplificar o trabalho dos programadores, evitando copiar e colar ou reescrever o código. Para utilizar a biblioteca, adicione-a biblioteca ao código com a palavra-chave #include. Confira a documentação disponível para Arduino para utilizá-la corretamente (por exemplo).
//Librairie #include <Servo.h> //Déclaration des constantes #define UPDATE_TIME 15 #define MAX_POS 180 #define MIN_POS 0 //Déclaration des paramètres int servoPin = 9; int pulse = 1500; //Déclaration des variables Servo myServo; // création d'un objet Servo // Sur la plupart des cartes, on peut créer jusqu'à douze objets int pos=0; // variable contenant la position du servomoteur void setup() { myServo.attach(servoPin); } void loop() { for (pos = MIN_POS; pos <= MAX_POS; pos += 1) { myServo.write(pos); delay(UPDATE_TIME); } for (pos = MAX_POS; pos >= MIN_POS; pos -= 1) { myServo.write(pos); delay(UPDATE_TIME); } }
Crie a sua própria biblioteca ServoLib.h
A criação de uma biblioteca permite reutilizar segmentos de códigos em diversos projectos sem precisar reescrevê-los. Uma biblioteca se compõe de dois ficheiros em linguagem c (um ficheiro .cpp e um ficheiro .h), ambos com o mesmo nome. O ficheiro .h, chamado de header, contém a declaração das variáveis, das funções e das classes utilizadas. O ficheiro .cpp contém o código propriamente dito. Esses ficheiros devem ser salvos numa pasta com o mesmo nome da biblioteca no seguinte diretório: .Documents/Arduino/libraries.
Ficheiro ServoLib.h
#ifndef ServoLib_h #define ServoLib_h //Déclaration des constantes #define UPDATE_TIME 15 #define MAX_POS 180 #define MIN_POS 0 #define MAX_PULSE_WIDTH 2500 #define MIN_PULSE_WIDTH 500 //Déclaration de la classe class ServoLib { public: ServoLib(); //constructeur int servoPin; //broche du servomoteur void associePin(int pin); void envoiePosition(int value); int convertirAngleEnImpulsion(int ang); void appliquerImpulsion(int pulse); }; #endif
Ficheiro ServoLib.cpp
#include <ServoLib.h> ServoLib::ServoLib(){} void ServoLib::associePin(int pin){ servoPin=pin; pinMode(servoPin,OUTPUT); } void ServoLib::envoiePosition(int value){ int pulse=0; if (value<MIN_POS) value=MIN_POS; else if (value>MAX_POS) value=MAX_POS; value=map(value,MIN_POS,MAX_POS,MIN_PULSE_WIDTH,MAX_PULSE_WIDTH); pulse=this->convertirAngleEnImpulsion(value); this->appliquerImpulsion(pulse); } void ServoLib::appliquerImpulsion(int pulse){ digitalWrite(servoPin,HIGH); delayMicroseconds(pulse); digitalWrite(servoPin,LOW); delay(UPDATE_TIME); } int ServoLib::convertirAngleEnImpulsion(int ang){ float a = 2500/180; float b = 500; return int(a*ang+b); }
O ficheiro keyword.txt é opcional. Ele permite modificar a cor dos nomes no programa Arduino.
####################################### # Syntax Coloring Map ServoLib ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### ServoLib KEYWORD1 ServoLib ####################################### # Methods and Functions (KEYWORD2) ####################################### associePin KEYWORD2 envoiePosition KEYWORD2 convertirAngleEnImpulsion KEYWORD2 appliquerImpulsion KEYWORDS2 ####################################### # Constants (LITERAL1) ####################################### UPDATE_TIME LITERAL1 MIN_POS LITERAL1 MAX_POS LITERAL1 MIN_PULSE_WIDTH LITERAL1 MAX_PULSE_WIDTH LITERAL1
Sem o ficheiro keywords.txt
Com o ficheiro keywords.txt
Após recarregar o programa, poderá conferir, no Menu Esboço > Incluir Biblioteca, que a biblioteca que acabou de criar foi adicionada à lista.
Então o código pode ser simplificado da seguinte forma:
//Librairie #include "ServoLib.h" //Déclaration des paramètres int servoPin = 9; //Déclaration des variables ServoLib myServo; // création d'un objet Servo // Sur la plupart des cartes, on peut créer jusqu'à douze objets int pos=0; // variable contenant la position du servomoteur void setup() { myServo.associePin(servoPin); } void loop() { for (pos = MIN_POS; pos <= MAX_POS; pos += 1) { myServo.envoiePosition(pos); delay(UPDATE_TIME); } for (pos = MAX_POS; pos >= MIN_POS; pos -= 1) { myServo.envoiePosition(pos); delay(UPDATE_TIME); } }
Próximos passos
- Controlar diversos servomotores com um controlador serial
- Controlar um motor CC
- Controlar um motor de passo
Referências
- “A” grande referência https://www.arduino.cc/
- especificamente para servomotor https://www.arduino.cc/en/Reference/Servo
- para biblioteca: https://arduino.cc/en/Guide/Libraries
- Programar com Arduino
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie