Arduino e servos: como controlar servomotores
Controlar servos com o Arduino para fazer esses motores apontarem precisamente para os ângulos desejados envolve uma conexão física simples, e poucas funções de uma biblioteca padronizada.
Um servomotor, tipicamente chamado de servo, geralmente é um motor que vem acompanhado de circuito especial para permitir que ele aponte com precisão o seu eixo para o ângulo que o usuário definir. Os servos usados em conjunto com o Arduino frequentemente são aqueles desenvolvidos para uso em modelismo radiocontrolado, em aplicações como o controle da direção de carrinhos ou da inclinação dos ailerons de aeromodelos.
Para ter um primeiro contato com os servos, recorri a uma aplicação familiar, embora eu a tenha implementado de forma bem diferente (e bem menos eficiente) que o elegante mecanismo tradicional: um ventilador oscilante.
Os ventiladores tradicionais capazes de movimentar lateralmente seu corpo para dirigir o vento a diferentes partes do ambiente usam um mecanismo que aproveita o mesmo movimento do motor que gira a hélice para também fazer a oscilação lateral. Para o meu objetivo, entretanto, bastava imitar o efeito produzido, e assim usei um motor à parte (justamente o servo, com o qual eu queria me familiarizar) para se encarregar da oscilação, enquanto a hélice era operada pelo nosso velho amigo módulo Keyes 14c04, o mesmo que eu usei para soprar e apagar as chamas de um isqueiro no artigo Arduino, sensor de chamas e hélice: detectando e apagando um isqueiro.
Como em vários outros aspectos deste meu aprendizado sobre o Arduino, acabei descobrindo que a operação básica dos servos é mais simples do que eu imaginava: basta inicializá-los e depois "escrever" neles os ângulos para os quais queremos que eles apontem. Isso ocorre devido à existência da biblioteca Servo, que acompanha o Arduino e cuja documentação, incluindo a lista de funções que ela disponibiliza, foi suficiente para realizar o experimento de hoje.
O circuito
O experimento de hoje exigiu de minha parte apenas um circuito muito simples, interconectando pinos dos componentes envolvidos. É no interior desses componentesque reside a complexidade que eu não preciso1 conhecer para usar ;-)
O esquema de interconexão do Arduino, do servo TowerPro SG90, do módulo do hélice e do suporte para 4 pilhas AA foi este:
O diagrama acima mostra, em blocos, os pinos de cada um dos 4 componentes envolvidos. Sobre o servo SG90 que eu usei, vale mencionar que ele não identifica em seu corpo a função de cada pino, mas verifiquei que seus cabos marrom, vermelho e laranja correspondem, respectivamente, a terra, alimentação e sinal.
Sobre o módulo da hélice, os detalhes já constam no artigo anterior, mas vale resumir: além do pino de alimentação e do terra, temos 2 pinos de controle: INA e INB. Se ambos estiverem com o mesmo valor (HIGH e HIGH ou LOW e LOW), a hélice para. Se estiverem com valores diferentes, ela gira no sentido horário ou anti-horário, conforme o caso.
Note que a simplicidade do circuito que eu montei talvez pudesse ser ainda maior: segundo a documentação, como eu estou usando apenas 1 servo, eu poderia alimentá-lo diretamente do pino 5V do próprio Arduino, sem recorrer a uma fonte externa.
Mas eu fiz algumas contas por alto sobre a possibilidade de consumo no pior caso com relação ao conjunto servo + ventilador, e preferi separar a alimentação do Arduino e a dos 2 motores, recorrendo assim a um suporte para 4 pilhas AA. Também testei com a obtenção de alimentação de uma porta USB do computador, e funcionou igualmente bem. Poderia ter usado transistores para chavear os pinos de comando, para separar ainda mais o Arduino dos demais componentes, e talvez faça isso em futuras aplicações.
Programação do Arduino para controlar o servo
O programa que eu tinha em mente era bem simples: considerando que o módulo ventilador foi fixado ao eixo do servo, bastava ligar a hélice e aí instruir o servo para apontar para diferentes ângulos, indo e voltando.
Veja como ficou:
#include <Servo.h>
Servo servo90g;
const byte vent_INA=10;
const byte vent_INB=11;
void setup() {
servo90g.attach(A0);
pinMode(vent_INA,OUTPUT);
pinMode(vent_INB,OUTPUT);
digitalWrite(vent_INA,LOW);
digitalWrite(vent_INB,HIGH);
}
int angulo=0;
const int pausa=350;
const byte angbase=14;
const byte angmax=28;
void loop() {
for(angulo = angbase; angulo < angmax; angulo++)
{
servo90g.write(angulo);
delay(pausa);
}
for(angulo = angmax; angulo>=angbase; angulo--)
{
servo90g.write(angulo);
delay(pausa);
}
}
Não há nenhuma grande complexidade no programa, mas destaquei com cores os trechos que merecem atenção.
Em vermelho temos as 3 linhas que inicializam os servos, e estarão presentes em todo programa que faz uso deles: a que começa com #include faz a referência à biblioteca, a que inicia com Servo instancia o objeto (a segunda palavra dessa linha será o nome do objeto criado, você pode escolher livremente, desde que repita o mesmo nome nas demais referências), e a terceira, que vem pouco abaixo, na função setup()
, registra2 em qual dos pinos do Arduino o servo está conectado.
Apenas como informação, destaquei em verde as 2 linhas que fazem o ventilador começar a girar. Os detalhes sobre elas você encontra no artigo anterior.
Para completar, em cor salmão, estão as 2 linhas que mandam o servo apontar para um determinado ângulo. A primeira delas está em um loop crescente, e a segunda está em um loop decrescente. Esses loops são os responsáveis pelo efeito de ida e volta graduais típico da oscilação lateral de um ventilador doméstico.
Um detalhe curioso: o protocolo de comando dos servos
Não é necessário saber ou entender isso para usar a biblioteca Servo mas, graças ao capítulo 5 do livro Arduino em Ação (publicado pela Novatec, patrocinadora do BR-Arduino.org), eu satisfiz minha curiosidade sobre como é o protocolo que a biblioteca Servo usa para transmitir ângulos para um servomotor.
A biblioteca envia os comandos pelo pino de sinal, por meio de uma forma de PWM na qual os parâmetros importantes são a frequência com que o pulso se repete (geralmente a cada 20ms), e a duração de cada pulso, que indica o ângulo para o qual o servo deve apontar.
A imagem abaixo mostra 3 variações de duração de pulso, e seu efeito sobre um modelo de servo em particular:
Observe: se o pulso dura 1ms, o servo apontará para o seu ângulo mínimo. Com um pulso de 1,5ms, ele apontará para a posição central, e se o pulso for de 2ms, apontará para seu ângulo máximo. Assim, o ângulo será proporcional a qualquer valor entre 1ms e 2ms.
Esses valores são típicos e esperados, mas podem variar: cada modelo de servo tem seu ângulo mínimo e máximo, bem como pode alterar os limites mínimos e máximos de duração do pulso. Para verificar se o seu motor pode ir abaixo de 1ms (que podem corresponder a ângulos inferiores a 0°) ou acima de 2ms (ângulos superiores a 180°), você pode usar a função writeMicroseconds(), mas leia bem a documentação dela antes, pois ela contém um alerta sobre uma situação a ser evitada.
Mais detalhes sobre servos no Arduino
O exemplo acima é básico mas explora o essencial da interação entre Arduino e servos: inicializá-los e fazê-los apontar para ângulos.
Na maior parte dos modelos de Arduino, até 12 servos podem ser controlados pela biblioteca Servo. Vale observar que, nesses mesmos modelos, o uso de PWM (comando analogWrite()
) nos pinos 9 e 10 fica desativado quando a biblioteca Servo estiver em uso.
Existem mais algumas funcionalidades a explorar, como a possibilidade de ler o ângulo atual do servo, a função writeMicroseconds() (cuja documentação aponta uma situação de alta corrente que deve ser evitada), e mais alguns detalhes que a documentação cobre bem.
Comentar