Os motores são uma boa forma de permitir que seus projetos interajam com o ambiente. Ainda mais os servomotores que possibilitam um controle de posição preciso. Portanto, vamos aprender a controlar um servomotor utilizando PWM e usando a biblioteca padrão do Arduino.
O que é
O servomotor é um tipo de motor de corrente contínua. A diferença dele pros demais é que sua posição pode ser controlada de maneira precisa. Isto é, posso mandar ele ir até um certa posição (em graus) e ele fará isso de forma precisa. A maioria dos servomotores possuem movimento limitado e podem girar apenas de 0º a 180º. Entretanto, existem versões que giram 360º. Abaixo está a imagem de um servomotor comum para interações com o Arduino.
Ele possui três pinos, sendo: Vcc e GND que são pinos para alimentação; e o pino de sinal que é utilizado para comandar o servomotor. Os principais componentes dentro dele, são: um motor de corrente contínua comum, um circuito de controle e um potenciômetro.
O circuito de controle pega os sinais de entrada e os transforma em movimento. O potenciômetro fica acoplado ao conjunto de engrenagens interna do motor. Dessa forma, de acordo com a rotação do potenciômetro, o motor sabe em qual posição o motor se encontra. A imagem abaixo mostra os elementos dentro do servomotor.
Portanto, o circuito de controle aciona o motor CC interno e verifica constantemente, com o potenciômetro, se a posição desejada foi alcançada. Esse funcionamento pode ser melhor visto no diagrama abaixo:
Neste caso, o erro é informado pelo potenciômetro.
Entretanto, todo esse trabalho pesado fica por conta do CI interno ao servomotor. E, para controlá-lo externamente é bem simples.
Controle
Circuito
Todo os procedimentos que irei descrever nos tópicos seguintes se baseiam na ligação abaixo:
É um circuito bem simples. Basta ligar o Vcc do motor no 5v do Arduino e o pino GND (marrom no meu caso) no GND. O pino de sinal (laranja) pode ser ligado em qualquer pino digital do Arduino. No meu caso, liguei no pino 2.
Com PWM
Princípio de funcionamento
Para controlar o motor, os sinais de entrada precisam ser na forma de PWM. A forma padrão de acionamento é controlar o movimento do motor com um pulso de 50Hz com o tempo em alta variando de 1ms a 2ms.
Ou seja, você deve ficar mandando um pulso de período 20ms (50Hz -> 1/50=0,02 segundos). E, neste pulso, você controla a posição do motor mudando o tempo em alta do pulso. Por padrão, o tempo em alta deve variar de 1ms a 2ms. Sendo que, 1ms corresponde ao motor na posição 0º e 2ms corresponde à posição 180º. A imagem abaixo ilustra melhor o processo.
Entretanto, existem motores que o limite inferior e o superior são diferentes. No meu caso, parece que o limite inferior era perto de 0ms e o superior algo em torno de 3ms. Na própria biblioteca para o Arduino, os limites padrões são diferentes: o limite inferior padrão é 544μs e o superior é 2400μs. Portanto, neste caso, a posição 0º seria 544μs de tempo em alta e a posição 180º seria 2400μs de tempo em alta.
Infelizmente, nós não podemos utilizar a função analogWrite (PWM padrão do Arduino), pois ela trabalha com uma frequência de 490Hz. Sendo assim, vamos ter que criar nossa própria função de acionamento.
Programação
O primeiro passo é definir o pino responsável pelo motor. É o pino 2 no meu caso:
#define motor 2
E, claro, setar ele como saída no void setup:
pinMode(motorV, OUTPUT);
Agora, vamos pensar na nossa função para controlar o motor. Ela deve receber um parâmetro que informa qual a posição (0º até 180º) que o motor deve ficar. Como ela não retornará nada, será uma função void:
void controlaMotor(int posicao){
O parâmetro posição varia de 0 a 180, mas o nosso PWM precisa ter um tempo de alta de 1ms até 2ms. Para resolver esse problema, basta mapear os nossos limites de 0 a 180 para os novos limites de 1ms até 2ms. Uma observação importante: como 1ms é um valor baixo, irei trabalhar com microssegundos para ter uma faixa maior. Portanto, vou mapear para valores de 1000μ até 2000μs usando a função map().
int tempo = map(posicao, 0, 180, 1000, 2000);
Temos, então, o tempo em alta correspondente a posição que foi informada. Por fim, basta mandar um sinal de nível alto durante esse tempo e mandar sinal de nível baixo no tempo restante. Como o período da onda é de 20ms, é só calcular que o tempo restante é 20ms – TempoEmAlta. Logo:
1 2 3 4 5 | digitalWrite(motor, HIGH); delayMicroseconds(tempo); digitalWrite(motor, LOW); delayMicroseconds(20000-tempo); digitalWrite(motor, HIGH); |
Por fim, basta envolver o acionamento acima em um ‘for’ para garantir que o comando repita até o motor chegar a posição desejada. Pelos testes que fiz, repetir 5 vezes já garantiu o deslocamento. Porém, não adicionei nenhuma carga, então você deve testar e ver qual é um valor ideal para seu caso. Obs.: O acionamento da nossa função não é constante, por isso é necessário essa repetição.
for(i=0; i<5; i++){
Pronto, agora é só testar sua função.
Código completo
O código abaixo implementa a função que criamos e faz o motor girar de 0º até 180º e depois girar de 180º até 0º.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #define motor 2 void setup() { pinMode(motor, OUTPUT); controlaMotor(180); // Começa setando a posição para 180º delay(1000); } void loop() { int i; for (i = 0; i < 180; i++) { // Gira de 0º a 180º controlaMotor(i); } delay(1000); for (i = 180; i > 0; i--) { // Gira de 180º até 0º controlaMotor(i); } } void controlaMotor(int posicao) { int tempo = map(posicao, 0, 180, 1000, 2000); // Altere o limite inferior (1000) e superior (2000) para o seu caso int i; for (i = 0; i < 5; i++) { digitalWrite(motor, HIGH); delayMicroseconds(tempo); digitalWrite(motor, LOW); delayMicroseconds(20000 - tempo); digitalWrite(motor, HIGH); } } |
Com biblioteca
Utilizar a biblioteca não tem muito mistério. Basta utilizar alguns comandos para fazer o setup e então controlar o motor.
Programação
O primeiro passo é importar a biblioteca e criar o objeto servo para controlar o motor:
#include <Servo.h>
Servo NomeDoMotor;
Para criar o objeto é só escrever “Servo” seguido do nome que você quer dar ao seu motor. Feito isso, você precisa anexar o objeto criado ao pino que você ligou o servomotor na função setup. Isso é feito da seguinte forma:
NomeDoMotor.attach(pino);
Por fim, resta apenas controlar seu motor. E, para isso, existe uma função que recebe um parâmetro em graus e movimenta o motor até essa posição:
NomeDoMotor.write(posição);
Repare que é uma função bem parecida com a que criamos no tópico acima. Agora é só juntar tudo isso e criar seu código.
Código completo
O código abaixo faz o motor girar de 0º até 180º e depois girar de 180º até 0º. (Igual o código anterior do PWM)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <Servo.h> Servo motor; void setup() { motor.attach(2); } void loop() { int i; for (i = 0; i < 180; i++) { motor.write(i); } delay(1000); for (i = 180; i > 0; i--) { motor.write(i); } delay(1000); } |
Preciso de um progeto de um conta giro rpm
Para este tipo de aplicação você pode utilizar um encoder ou então um tacômetro (sensor que mede as rotações por minuto (rpm) do motor). Também dá para utilizar LEDs infravermelhos, como é possível ver neste site aqui.
Como faço para o servomotor ir de O° a 180° e voltar para 0° de forma contínua, sem parar?
Olá, Allisson. O código do post praticamente já faz isso, sendo necessário apenas você remover os comandos delay(1000).
como faço para definir posições setadas para o servo?
vou usar 4 servos motores e gostaria de saber pra definir posições fixas para eles.
desde já agradeço.
Olá, Gustavo. Imaginando que você está usando a biblioteca, é só criar uma instância para cada motor:
Servo motor1;
Servo motor2;
…
Servo motor4;
Depois, no void setup, você usa o comando attach em cada um:
motor1.attach(pino_motor_1);
…
motor4.attach(pino_motor_4);
Por fim, você define a posição de cada um usando o comando write:
motor1.write(posicao_motor_1);
…
motor4.write(posicao_motor_4);