08 junho 2013

Controlando um servo motor com Arduino

O grande barato de comprar as coisas pela internet, e no exterior, é a quase completa falta de manuais. Um exemplo disso é o servo motor abaixo, que chegou essa semana :

controlar servo motor Arduino

Chegou inteiro, mas desse jeito : o servo, os acessórios num plástico, e só. Uma etiqueta escrito "Micro Servo 9g" foi a maior pista que eu tive do modelo.

Aí começa a parte divertida da coisa, que é descobrir como o servo funciona, suas conexões, voltagens e tal. Vasculhando no Google, descobri um modelo muito parecido, chamado HXT900, e que sua voltagem de operação vai de 3 a 6v. Já é um começo. Mas e as conexões ?

Bom, o cabo tem 3 vias : Preto, vermelho e branco. Fácil, não ? Preto no GND, vermelho no 5V e branco para dados.

Testei o servo usando o exemplo que já vem na IDE do Arduino, que usa um potenciômetro para controlar a rotação do motor :

servo motor 9g Arduino
O programa abaixo você pode encontrar no menu Arquivo -> Exemplos -> Servo -> Knob :

 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
32
33
34
35
36
// Programa : Controlando a posicao de um servo usando potenciometro
// Traducao e comentarios : Arduino e Cia
//
// Controlling a servo position using a potentiometer (variable resistor) 
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 


#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

// Pino analgico do potenciometro
int potpin = 0;

// Variavel que armazena o valor lido do potenciometro
int val;     

void setup() 
{ 
  // Define que o servo esta ligado a porta 9
  myservo.attach(9);  
} 

void loop() 
{ 
  // Le o valor do potenciometro (valores entre 0 e 1023) 
  val = analogRead(potpin);            

  // Converte o valor pra ser usado no servo (valores entre 0 e 180) 
  val = map(val, 0, 1023, 0, 179);     

  // Move o eixo do servo, de acordo com o angulo
  myservo.write(val);                  

  // Aguarda o servo atingir a posição
  delay(15);                           
}

O programa lê as informações do potenciômetro ligado à entrada analógica (valores de 0 a 1023), converte esses valores para serem usados no servo (0 a 180), e move o servo motor para a posição correspondente. Gire o potenciômetro nos 2 sentidos, e o servo irá acompanhar o movimento do potenciômetro.

Também podemos controlar o servo usando posições pré-estabelecidas, o que é muito útil quando precisamos usar o motor para movimentos repetitivos. Como no exemplo abaixo, onde utilizei 3 chaves (push-button) :

Circuito Arduino - Servo motor - Push button
 e o seguinte programa :

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Programa : Controlando o servo com 3 chaves
// Autor: Arduino e Cia

#include <Servo.h> 

Servo myservo;

int val; 
int ChaveEsquerda=3; //Pino a ser ligado na chave esquerda
int ChaveCentral=4;  //Pino a ser ligado na chave central
int ChaveDireita=5;  //Pino a ser ligado na chave direita

void setup() 
{ 
  // Pino de dados do servo conectado ao pino 9 do Arduino
  myservo.attach(9);   
  //Define o pino como entrada
  pinMode(ChaveEsquerda, INPUT);      
  //Aciona o resistor pull-up interno
  digitalWrite(ChaveEsquerda, HIGH);  
  pinMode(ChaveCentral, INPUT);
  digitalWrite(ChaveCentral, HIGH);
  pinMode(ChaveDireita, INPUT);
  digitalWrite(ChaveDireita, HIGH);
} 

void loop() 
{ 
 //Le o valor da Chave Esquerda (On/Off)
 val=digitalRead(ChaveEsquerda);  
   //Caso a chave seja pressionada, movimenta o servo
   if(val!=1) 
    {
       myservo.write(60);  //Move o servo para o angulo de 60 graus
       delay(15);          //Delay para o servo atingir a posiçao
    }

 val=digitalRead(ChaveCentral);
   if(val!=1)
    {
       myservo.write(90);  //Move o servo para o angulo de 90 graus
       delay(15);
    }

 val=digitalRead(ChaveDireita);
   if(val!=1)
    {
       myservo.write(120);  //Move o servo para o angulo de 120 graus
       delay(15);
    }
}

Ao pressionar o botão da esquerda, o servo se movimenta para a posição "60 graus", o botão central leva à posição 90 graus, e o botão da direita, à posição 120 graus.


61 comentários:

  1. Parabéns! Excelente postagem, vou estar agendando uma visita sua aqui em nossa empresa, é possível?

    ResponderExcluir
    Respostas
    1. Boa noite e obrigado pela visita ! Tenho interesse, por favor utilize o formulário de contato no lado direito da página para enviar uma mensagem privada e conversamos por email. Abraço.

      Excluir
  2. Boa tarde, gostaria de saber como eu consigo fazer que o arduino comande um servomotor em 90 graus positivo ao apertar um botão, e após soltar o mesmo botão o braço do servo motor volte para posiçõ anterior

    ResponderExcluir
    Respostas
    1. Boa noite !

      Você pode usar o programa deste post como base, e definir o angulo de 90 graus quando o botão for acionado, e o angulo de 0 graus quando não houver alteração no estado do botão.

      Se precisar de ajuda com a programação, entre em contato.

      Abraço !

      Excluir
  3. Cara, você sabe quantos servomotores podem ser controlados ao mesmo tempo com o arduino?

    ResponderExcluir
    Respostas
    1. Boa noite,

      Como eles utilizam apenas um pino para controle, você teoricamente pode ligar vários deles ao mesmo tempo. Mas... use alimentação externa, senão o Arduino não vai suportar tantos motores.

      Quanto à biblioteca, a Servo permite o controle de até 12 motores.

      Abraços !

      Excluir
  4. Boa tarde!

    Poderia me ajudar?

    Consigo fazer meu servo se movimentar de 0 a 180 graus (indo e vindo), e no meio desse movimento quero que ao pressionar um botão o servo pare,veja quantos graus esta e ande mais 5 graus e se mantenha parado.

    Explicando melhor: tenha uma garra robótica que ao detectar que pegou um objeto (botão foi pressionado) quero que ele veja quantos graus andou ( botão foi pressionado e estava em 90 graus) quero que ele ande mais 5 graus e pare (95 graus) (para detectar e segurar com firmeza o objeto)

    Segue o código que tenho:





    #include



    Servo myservo; // create servo object to control a servo

    // a maximum of eight servo objects can be created



    int pos = 0; // variable to store the servo position



    void setup()

    {

    myservo.attach(9); // attaches the servo on pin 9 to the servo object

    }





    void loop()

    {

    for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees

    { // in steps of 1 degree

    myservo.write(pos); // tell servo to go to position in variable 'pos'

    delay(15); // waits 15ms for the servo to reach the position

    }

    for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees

    {

    myservo.write(pos); // tell servo to go to position in variable 'pos'

    delay(15); // waits 15ms for the servo to reach the position

    }

    }

    ResponderExcluir
    Respostas
    1. Boa tarde Filipe,

      Você pode utilizar comandos IF e WHILE dentro do código, mas não tenho certeza se irão funcionar. Talvez uma alternativa melhor seja acionar uma das interrupções do Arduino :

      http://arduino.cc/en/Reference/Interrupts

      Abraço !

      Excluir
  5. Olá, amigo, esse micro servo é de baixa potência, certo ? será que é possível limitar no potenciômetro um movimento de + 45 e - 45º ? e pode ser ligado 3 servos no mesmo espaço para que eles se movam juntos ?

    ResponderExcluir
    Respostas
    1. OI Marcos,

      Exato. Você pode fazer isso no próprio programa, determinando que o servo não se movimente além dos 45 graus que você precisa. Você pode usar 3 servos ao mesmo tempo, contanto que cada um use uma porta do Arduino.

      Abraço !

      Excluir
  6. BOA NOITE.
    PARABENS PELOS TRABALHOS E PELAS DICAS.
    ATT,
    THOMAZ

    ResponderExcluir
    Respostas
    1. Bom dia Thomaz !

      Muito obrigado. Aguardo sua visita sempre que puder.

      Abraço !

      Excluir
  7. Boa tarde,
    Estou precisando de ajuda.
    Possuo um trabalho que precisa ler o ângulo do potenciômetro sendo que o mesmo estando na posição central e deverá aparecer no LCD a indicação de 0 graus se virar o pot para direita devera ler em ordem positiva 1,2,,3,4....até 90 gruas, se for pra a esquerda deverá ser -1,-2,-3....ate -90 gruas.

    O código abaixo lhe da de 0 a 180 contínuos.
    Pode me ajudar...

    #include // inclui a biblioteca LCD
    LiquidCrystal lcd(8,9,4,5,6,7); // pinos conectados ao lcd

    void setup() {

    lcd.begin(16,2); // declara um lcd com 16 colunas e 2 linhas
    }
    void loop() {
    int angle = analogRead(1); // Lê o valor do potenciômetro
    angle=map(angle, 0, 1023, 0, 179); // Mapeia os valores de 0 a 180 graus


    lcd.setCursor(0,0); /* define a posição do cursor */
    lcd.print("GR: "); // printa Angulo
    lcd.setCursor(4,0);
    lcd.print(angle); /* printa a leitura do angulo de 0 a 180 */
    if(angle < 10) { // se for menor que 10 apaga os digitos "sobrando"
    lcd.setCursor(8,1);
    lcd.print(" ");
    }
    if(angle < 100){
    lcd.setCursor(9,1);
    lcd.print(" ");
    }
    }

    ResponderExcluir
    Respostas
    1. Boa tarde,

      Você tem que alterar a linha do comando map. Fica assim :

      angle=map(angle, 0, 1023, -90, 90);

      Abraço !

      Excluir
  8. Preciso de de uma orientação para seguinte questão baseado no código acima. quando apertar botão_1 servo vai a 180 graus e fica a demora delay(3000); bem devagar. e quando voltar a apertar o botão _1 ele vai a zero (0) grau no mesmo delay(3000); devagar. e fica até eu decidir novamente a ele ir para 180 mais só quando apertar o botão.desde já agradeço e parabéns pelo conteúdo do site recheado de excelentes matérias é o que precisamos para melhorar cada vez mais nossos conhecimentos. Obrigado

    Como posso fazer essa combinação do botão e acionar o servo.

    ResponderExcluir
    Respostas
    1. Boa tarde,

      Para o controle da velocidade, usar o delay() não vai resolver o problema da velocidade. Tente usar a biblioteca VarSpeedServo :

      https://github.com/netlabtoolkit/VarSpeedServo

      Abraço !

      Excluir
  9. Boa noite,
    muito obrigado pela informação, funcionou perfeitamente,
    Mais uma vez parabéns pelas dicas.
    Att,
    THOMAZ EDSON

    ResponderExcluir
  10. Boa Noite!

    Parabens pelas postagens!! Sempre muito boas!!

    Tenho uma duvida, sou leigo no assunto mas seria possivel utilizar PushButton como "joystick" apenas criando um codigo para incrementar um angulo num determinado delay, relacionado com o tempo que o botão é pressionado?

    ResponderExcluir
    Respostas
    1. Boa tarde Guilherme,

      É possível sim, eu faço isso nesse post aqui, mas com motor de passo :

      http://www.arduinoecia.com.br/2013/11/ligando-motor-de-passo-28byj-48-e.html

      veja se consegue adaptar para um servo motor.

      Abraço !

      Excluir
  11. Boa noite,
    preciso do caminho das pedras para fazer um motor de vidro elétrico funcionar como servo, vc teria alguma dica ou algum site.
    Vi no youtube alguns porém não passam o circuito.
    att,
    THOMAZ EDSON

    ResponderExcluir
    Respostas
    1. Boa tarde,

      Infelizmente ainda não tenho nada nesse sentido.

      Abraço !

      Excluir
  12. Agradeço sempre pelo apoio.
    Em meus trabalhos consegui fazer uma montagem perfeita, utilizando o circuito de um micro servo. Os fios que vão para o motor são retirados e colocadas duas lâmpadas usando o terra com referencia para cada lâmpada e dois LDR ligadas há uma ponte H. Conforme a lâmpada que acender o motor irá girar o ângulo correspondente. sendo que o potenciômetro do servo tem que estar no eixo do motor. Caso queira posso lhe enviar o circuito para postagem.
    Desde já obrigado.
    ATT,
    THOMAZ EDSON

    ResponderExcluir
    Respostas
    1. Boa noite Thomaz,

      Queria ver essa engenhoca funcionando. :) se puder, mande sim.

      Abraço !

      Excluir
  13. Boa tarde, gosto muito do trabalho de vocês, e gostaria de saber se tem como me ajudar em um projeto que estou fazendo, é que eu não sei quase nada da parte de programação, a princípio queria que vocês me dissessem se este código está certo, o objetivo é movimentar um servo através da váriação apontada pelo sensor reflexivo, :
    #include

    Servo garra;

    int sensorpin = 7;
    int val;

    void setup()
    {
    garra.attach(9);
    }

    void loop()
    {
    val = digitalRead(sensorpin);
    val = map(val, 0, 1023, 0, 60);
    garra.write(val);
    delay(15);
    }

    Ficarei grato se puderem me ajudar !

    ResponderExcluir
    Respostas
    1. Boa noite Leonardo,

      Me diga qual o tipo de sensor que vc vai utilizar.

      Abraço !

      Excluir
  14. Boa noite,
    Estou precisando controlar 4 servo, com 2 chaves PushButton, 1 para +90 outra para -90. eles precisam funcionar independentes. Como eu faria ???
    tem como me ajudar com o esquema de ligação e programação ??
    muito obrigado

    ResponderExcluir
  15. Este comentário foi removido pelo autor.

    ResponderExcluir
  16. Boa tarde. Como fazer os cálculos para saber o peso que o servo levanta. Tipo, tenho uma tampa de 1 quilo e 25 centímetros. Como saber qual servo preciso para levar isso. O servo vai abrir uma lixeira.

    ResponderExcluir
    Respostas
    1. Boa tarde Claudio,

      Acho que esse link aqui pode te ajudar:

      http://www.instructables.com/answers/Is-there-a-way-to-calculate-how-much-weight-a-serv/

      Abraço!

      Excluir
  17. boa tarde.
    cara preciso controlar um servo motor, sendo controlado por dois sensores. assim um sensor aciona ele para 90 graus e o outro sensor traz ele para a posição anterior

    ResponderExcluir
  18. Bom dia!
    Preciso controlar 2 servos de 0 a 180 com 1 potenciômetro, sendo que, ao girar o potenciômetro um se mova no sentido horário e o outro anti-horário.

    ResponderExcluir
    Respostas
    1. Bom dia,

      Você pode fazer a programação inversa para cada motor, criando um objeto para o segundo motor com os comandos:

      Servo myservo2;
      myservo2.attach(8);

      Abraço!

      Excluir
  19. Boa tarde, como faço para controlar 2 servos motores com um controle remoto IR e o arduino uno?

    ResponderExcluir
    Respostas
    1. Boa tarde,

      Não tenho nenhum post com essa configuração, mas é uma boa sugestão para um post futuro.

      De qualquer forma, você pode usar como base as informações deste post:

      http://www.arduinoecia.com.br/2013/10/modulo-rele-4-canais-e-controle-remoto.html

      Abraço!

      Excluir
  20. Ola,

    Gostaria de saber qual o codigo para controlar o servo por um determinado tempo e logo apos voltar para a posicao inicial, porem apertando o push-button uma vez so! a ideia seria para fazer uma valvula para uma maquina de cafe.

    Agradeco desde ja.

    ResponderExcluir
  21. boa tarde tentei fazer o servo mover com os três botão mas ele move direto e nao para fiz as mesma ligação que vc fez e o programa mas ele não para de movimentar poderia me ajudar por favor

    ResponderExcluir
    Respostas
    1. Boa noite Hugo,

      Qual seria a função de cada botão ?

      Abraço!

      Excluir
    2. o mesmo programa que vc fez para movimentar os servos mas nao foi.
      so copie ele e colei o programa funcionou mas na pratica o servo nao moveu. o programa com tres botao que movimenta o servo nao funcionou na pratica as ligaçoes
      me ajude por favor

      Excluir
  22. Boa tarde,

    É possível fazer um programa sem o potenciometro? Ligando o servo diretamente no arduino? E nesse programa queria o sevo andasse de um em um grau, tem como?
    Desculpe se as duvidas são bestas mas estou começando agora.

    Obrigada

    ResponderExcluir
    Respostas
    1. Boa tarde Ana,

      É possível sim, você pode substituir essa leitura do potenciometro por uma variavel, fica mais ou menos assim:

      #include "Servo.h"
      Servo myservo; // create servo object to control a servo

      // Pino analgico do potenciometro
      int potpin = 0;

      // Variavel que armazena o valor lido do potenciometro
      int val;

      void setup()
      {
      // Define que o servo esta ligado a porta 9
      myservo.attach(9);
      }

      void loop()
      {
      //valor para o servo entre 0 e 180 graus
      for (int angulo = 0; i<179; i++)
      {
      myservo.write(angulo);
      // Aguarda o servo atingir a posição
      delay(35);
      }
      //Aguarda dois segundos e reinicia o processo
      delay(2000);
      }

      Abraço!

      Excluir
    2. Muito obrigada, vocês são muito atenciosos. Vou testar aqui :D

      Excluir
  23. Uma duvida:um servo SG90 usando um Nano, aguarda sinal de um sensor para movimentar o servo, mas enquanto não recebe o comando, o servo fica fazendo barulho como se estivesse ligado, eu li 5v no pino de comando do servo, isso é normal?

    ResponderExcluir
    Respostas
    1. Bom dia Vanderlei,

      Dependendo da programação, pode acontecer isso sim. O sinal que vc está lendo é analógico ? Talvez uma pequena variação nesse sinal pode fazer com que o servo se movimente.

      Tente colocar alguma condição para que o servo se movimente, por exemplo. Ele só vai se movimentar se o ângulo for maior do que "X" graus.

      Abraço!

      Excluir
    2. Este foi o programa usado com um nano,copiei de um post daqui e modifiquei, funcionou perfeitamente por uns dias, mas acho que o nano queimou, parou e ficou com o led ligado e não aceita a programação e da erro, estou esperando outro chegar para continuar os testes.
      Abraço!

      #include
      int pirPin1 = 3;
      int pirPin2 = 5;
      int val2;
      int val1;
      Servo myservo;
      void setup()
      {
      myservo.attach(9);
      pinMode(pirPin1, INPUT);
      digitalWrite(pirPin1, LOW);
      pinMode(pirPin2, INPUT);
      digitalWrite(pirPin2, LOW);
      }
      void loop()
      {
      val1 = digitalRead(pirPin1);
      val2 = digitalRead(pirPin2);
      if (val1 == 1 && val2 != 1 )
      {
      myservo.write(40);
      // delay(50);
      }
      val1 = digitalRead(pirPin1);
      val2 = digitalRead(pirPin2);
      if (val2 == 1 && val1 == 1 )
      {
      myservo.write(90);
      // delay(50);
      }
      val1 = digitalRead(pirPin1);
      val2 = digitalRead(pirPin2);
      if (val2 == 1 && val1 != 1 )
      {
      myservo.write(140);
      //delay(50);
      }
      }

      Excluir
  24. Help,
    referente ao exemplo do código com três botões, como faço para que o mesmo, com apenas dois botões gire o servo para os lados de cada botão. Ao apertar um dos botoes, gire 1 grau a cada apertar o botão.

    att,
    Thomaz

    ResponderExcluir
  25. Boa tarde,
    sabe como posso alterar a frequência do pwm para controle dos servos?
    O pwm do arduino gera 500hz, queria alterar essa frequência, como posso proceder?

    ResponderExcluir
  26. estou tendo um pouco de dificuldade para fazer um código para meu quadrupede de 8 servos será se vcs podem me ajudar?

    ResponderExcluir
  27. boa noite. obrigado pelas postagens.
    eu gostaria de ao inves de usar potenciometro ou push boton com posiçoes fixas para o servo motor usar as referencias de um RTC fazendo com que o servo motor movimente 1 grau a cada 3 minutos. como posso fazer isso? agradeço se puder ajudar.

    ResponderExcluir
    Respostas
    1. Oi Valter!

      Obrigado. Você pode colocar uma condição no programa do RTC para que a cada 3 minutos ele movimente o servo... Só não se esqueça que o servo geralmente vai só até 180 graus, então você tem que colocar uma condição para ele retornar à posição inicial quando atingir esse valor.

      Quanto ao código, infelizmente não tenho ele pronto ainda, mas vou deixar como sugestão de post.

      Abraço!

      Excluir
  28. e como controlo com o arduino um servo motor de 1/4 cv de potencia. é por reles?
    obrigado

    ResponderExcluir
    Respostas
    1. Oi Valter,

      Tem o modelo de servo que você vai usar ?

      Abraço!

      Excluir
  29. Ola, muito bom o post! Meus parabéns! Tenho uma dúvida, para controlar o servo motor tem que ser numa porta PWM?

    ResponderExcluir
    Respostas
    1. Oi Alvaro!

      Não, você pode usar qualquer porta.

      Abraço!

      Excluir
  30. Ola. Poderia me orientar na minha dúvida.? Obrigado

    ResponderExcluir
    Respostas
    1. Oi Valter,

      Respondido. Desculpe a demora. :)

      Abraço!

      Excluir
  31. posso colocar um motor de 5v no lugar do servo?

    ResponderExcluir
    Respostas
    1. Oi Rafaela,

      Até pode, se você não precisar realmente de um servo motor. Nesse caso, também vai precisar alterar algumas coisas no programa. :)

      Abraço!

      Excluir
  32. Ola.

    Tenho uma duvida.
    Como faria para o servo ficar girando sem parar e sem utilizar potenciometro?

    Obrigada

    ResponderExcluir
    Respostas
    1. Boa noite,

      Comente a linha 30 (val = digitalRead... ) e inclua uma linha assim:

      val=1;

      Abraço!

      Excluir