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.

Servomotor comum

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.

Parte interna de um 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:

Malha de controle servomotor

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:

circuito base servomotor

É 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.

servomotor controle por pwm

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);
}