Vídeo: Robô com motor shield – Parte 2

Vídeo: Robô com motor shield – Parte 2

Na segunda parte do projeto do robô móvel autônomo utilizando Arduino UNO e Motor Shield L293D, desenvolveremos o sistema de sensoriamento do mesmo. Na primeira parte deste projeto, no post Robô com Motor Shield – Parte 1, explanamos sobre o controle dos motores e lógica de funcionamento.

A lógica de funcionamento completa do Robô com motor shield 4×4 já foi explanada no primeiro post, porém cabe uma breve revisão da mesma, através do fluxograma da Figura 1.

Robô com motor shield Parte 2

Figura 1 – Fluxograma de funcionamento do Robô

Ao iniciar o programa, o robô move-se para frente lendo o sensor frontal de distância e assim permanecerá até que detecte um obstáculo. Detectando um obstáculo frontal, a unidade pára, vira o sensor para esquerda com auxilio de um servo motor e lê a distância. Após, move o sensor para direita e lê a distância. O robô armazenará estas duas medidas. O próximo passo consiste em comparar as distâncias, para determinar qual é a maior. O robô fará a tomada de decisão, desviando para a maior distância encontrada, pois teoricamente, será o caminho mais simples, não existindo um obstáculo tão próximo.

Sensor Ultrassônico HC-SR04

Quando necessitamos medir alguma distância com precisão de centímetros, o sensor HC-SR04 é um dos dispositivos mais indicados (Figura 2). Gerando-se um pulso de trigger a partir do Arduino, é possível fazer o levantamento das curvas do sensor, que gera um pulso no pino ECHO diretamente proporcional à distância a que se encontra de algum obstáculo.

Sensor-Ultrassonico-HC-SR04

Figura 2 – Sensor Ultrassônico HC-SR04

Na Figura 3 pode-se observar as curvas geradas pelo sensor, que o datasheet do fabricante prevê.

Diagrama de tempo HC-SR04

Figura 3 – Curvas do Sensor Ultrassônico

De acordo com o datasheet, envia-se um pulso de gatilho (trigger) com duração de 10µs, após este pulso, o transmissor do sensor envia 8 pulsos ultrassônicos na frequência de 40kHz que o seu receptor receberá em forma de eco. Após isto, o pino ECHO irá a nível alto por um tempo proporcional à distância a que o sensor encontra-se do obstáculo. A distância em centímetros é o resultado do tempo que o pulso de ECHO permanece em nível alto, dividida por 58 (mais detalhes no datasheet).

O diagrama esquemático completo do Robô pode ser visto na Figura 4.

Diagrama Robô 4x4

Figura 4 – Diagrama esquemático completo do Robô

Como pode-se observar, utilizou-se o Motor Shield L293D como driver para controle dos 4 motores do Robô, adicionando-se o sensor ultrassônico HC-SR04 para verificação de obstáculos e medida de distância e um servo motor de posição, que direciona o sensor adequadamente no momento das medidas. Todos estes componentes para montagem do robô com motor shield estão disponíveis na Loja FILIPEFLOP.

Programa Robô com motor shield – Final

O software completo e comentado pode ser analisado a seguir.

/*
   Curso de Arduino e AVR WR Kits Channel
   
   Aula 72 - Robô com Motor Shield (Parte 2)
*/

// --- Bibliotecas Auxiliares ---
#include <AFMotor.h>         //Inclui biblioteca AF Motor
#include <Servo.h>           //Inclui biblioteca para controle de Servos

// --- Seleção dos Motores ---
AF_DCMotor motor1(1); //Seleção do Motor 1
AF_DCMotor motor2(2); //Seleção do Motor 1
AF_DCMotor motor3(3); //Seleção do Motor 1
AF_DCMotor motor4(4); //Seleção do Motor 1

// --- Mapeamento de Hardware ---
#define   serv        10                 //controle do Servo 1
#define   trig        A4                 //Saída para o pino de trigger do sensor
#define   echo        A5                 //Entrada para o pino de echo do sensor

// --- Protótipo das Funções Auxiliares ---
float measureDistance();                //Função para medir, calcular e retornar a distância em cm
void trigPulse();                       //Função que gera o pulso de trigger de 10µs
void decision();                        //Função para tomada de decisão. Qual melhor caminho?
void robot_forward(unsigned char v);    //Função para movimentar robô para frente
void robot_backward(unsigned char v);   //Função para movimentar robô para trás
void robot_left(unsigned char v);       //Função para movimentar robô para esquerda
void robot_right(unsigned char v);      //Função para movimentar robô para direita
void robot_stop(unsigned char v);       //Função para parar o robô

// --- Objetos ---
Servo servo1;                           //Cria objeto para o servo motor

// --- Variáveis Globais ---
unsigned char velocidade = 0x00;       //Armazena a velocidade dos motores (8 bits)
float dist_cm;                         //Armazena a distância em centímetros entre o robô e o obstáculo
float dist_right;                      //Armazena a distância em centímetros da direita
float dist_left;                       //Armazena a distância em centímetros da esquerda
         
// --- Configurações Iniciais ---
void setup()
{
  //A biblioteca configura as entradas e saídas pertinentes ao Motor Shield...  
 pinMode(trig, OUTPUT);                       //Saída para o pulso de trigger
 pinMode(serv, OUTPUT);                       //Saída para o servo motor
 pinMode(echo, INPUT);                        //Entrada para o pulso de echo
 
 servo1.attach(serv);                         //Objeto servo1 no pino de saída do servo
 digitalWrite(trig, LOW);                     //Pino de trigger inicia em low
 servo1.write(80);                            //Centraliza servo
 delay(500);                                  //Aguarda meio segundo antes de iniciar
  velocidade = 0xFF; //Inicia velocidade no valor máximo
} //end setup

// --- Loop Infinito ---
void loop()
{
     robot_forward(velocidade);
     delay(80);
     dist_cm = measureDistance();
     if(dist_cm < 20) //distância menor que 20 cm?
     {
         decision();
     }
} //end loop

// --- Desenvolvimento das Funções Auxiliares ---

float measureDistance()                       //Função que retorna a distância em centímetros
{
  float pulse;                                //Armazena o valor de tempo em µs que o pino echo fica em nível alto
  trigPulse();                                //Envia pulso de 10µs para o pino de trigger do sensor
  pulse = pulseIn(echo, HIGH);                //Mede o tempo em que echo fica em nível alto e armazena na variável pulse
  /*
    >>> Cálculo da Conversão de µs para cm:
   Velocidade do som = 340 m/s = 34000 cm/s
   1 segundo = 1000000 micro segundos
   
      1000000 µs - 34000 cm/s
            X µs - 1 cm
            
                  1E6
            X = ------- = 29.41
                 34000
                 
    Para compensar o ECHO (ida e volta do ultrassom) multiplica-se por 2
    
    X' = 29.41 x 2 = 58.82
 */
  
  return (pulse/58.82);                      //Calcula distância em centímetros e retorna o valor
} //end measureDistante

void trigPulse()                             //Função para gerar o pulso de trigger para o sensor HC-SR04
{
   digitalWrite(trig,HIGH);                  //Saída de trigger em nível alto
   delayMicroseconds(10);                    //Por 10µs ...
   digitalWrite(trig,LOW);                   //Saída de trigger volta a nível baixo
} //end trigPulse

void decision()                              //Compara as distâncias e decide qual melhor caminho a seguir
{
   robot_stop(velocidade);                   //Para o robô
   delay(500);                               //Aguarda 500ms
   servo1.write(0);                          //Move sensor para direita através do servo
   delay(500);                               //Aguarda 500ms
   dist_right = measureDistance();           //Mede distância e armazena em dist_right
   delay(2000);                              //Aguarda 2000ms
   servo1.write(175);                        //Move sensor para esquerda através do servo
   delay(500);                               //Aguarda 500ms
   dist_left = measureDistance();            //Mede distância e armazena em dis_left
   delay(2000);                               //Aguarda 2000ms
   servo1.write(80);                         //Centraliza servo
   delay(500);
   if(dist_right > dist_left)                //Distância da direita maior que da esquerda?
   {                                         //Sim...
      robot_backward(velocidade);            //Move o robô para trás
      delay(600);                            //Por 600ms
      robot_right(velocidade);               //Move o robô para direita
      delay(2000);                           //Por 2000ms
      robot_forward(velocidade);             //Move o robô para frente
   } //end if
   else                                      //Não...
   {
    robot_backward(velocidade);            //Move o robô para trás
      delay(600);                            //Por 600ms
      robot_left(velocidade);                //Move o robô para esquerda
      delay(2000);                            //Por 2000ms
      robot_forward(velocidade);              //Move o robô para frente
   } //end else

} //end decision
 
void robot_forward(unsigned char v)
{
     motor1.setSpeed(v);
     motor1.run(FORWARD);
     motor2.setSpeed(v);
     motor2.run(FORWARD);
     motor3.setSpeed(v);
     motor3.run(FORWARD);
     motor4.setSpeed(v);
     motor4.run(FORWARD);
} //end robot forward

void robot_backward(unsigned char v)
{
     motor1.setSpeed(v);
     motor1.run(BACKWARD);
     motor2.setSpeed(v);
     motor2.run(BACKWARD);
     motor3.setSpeed(v);
     motor3.run(BACKWARD);
     motor4.setSpeed(v);
     motor4.run(BACKWARD);
} //end robot backward

void robot_left(unsigned char v)
{
     motor1.setSpeed(v);
     motor1.run(FORWARD);
     motor2.setSpeed(v);
     motor2.run(FORWARD);
     motor3.setSpeed(v);
     motor3.run(BACKWARD);
     motor4.setSpeed(v);
     motor4.run(BACKWARD);
} //end robot left

void robot_right(unsigned char v)
{
     motor1.setSpeed(v);
     motor1.run(BACKWARD);
     motor2.setSpeed(v);
     motor2.run(BACKWARD);
     motor3.setSpeed(v);
     motor3.run(FORWARD);
     motor4.setSpeed(v);
     motor4.run(FORWARD);
} //end robot right

void robot_stop(unsigned char v)
{
     motor1.setSpeed(v);
     motor1.run(RELEASE);
     motor2.setSpeed(v);
     motor2.run(RELEASE);
     motor3.setSpeed(v);
     motor3.run(RELEASE);
     motor4.setSpeed(v);
     motor4.run(RELEASE);
} //end robot stop

Para mais detalhes, acesse o vídeo disponível no início deste post, e para download dos arquivos utilizados neste post sobre robô com motor shield, acesse este link.

Gostou ? Ajude-nos a melhorar o blog atribuindo uma nota a este tutorial (estrelas no final do artigo), comente e visite nossa loja FILIPEFLOP!

2
Vídeo: Robô com motor shield – Parte 2
9 votos, 4.56 classificação média (91% pontuação)

Wagner Rambo é bacharel em Engenharia Eletrônica, Computadores e Telecomunicações, e colaborador do site FILIPEFLOP.

Compartilhe este Post

12 Comentários

  1. Mariana - 15 de junho de 2017

    Muito bom o tutorial, porém estou enfrentando alguns problemas.

    Ao plugar o USB o carrinho funciona perfeitamente, porém, ao usar a bateria de 9V ele fica com uma velocidade muito alta e acaba batendo nos obstáculos, poderia me ajudar a resolver o problema?

    Aguardo seu retorno,
    Att.

  2. Jean Júnio - 25 de outubro de 2016

    Qual a lista de materiais completa para aquisição do robô?

  3. rogerio - 8 de outubro de 2016

    Wagner,
    como sempre muito didático, parabéns. Cara, montei o projeto, usei o programa, porém estou enfrentando 2 problemas:
    1- ao alimentar o arduino com a bateria de 9v (recarregável – 260mAh), o servo e o sensor parecem não estar recebendo energia suficiente para rodar, quando retiro a alimentação por bateria e plugo o cabo USB, funciona normal. A bateria não me parece ser o problema pois já medi e está com a tensão correta (também troquei por uma nova e nada…). O motor shield estou com as 5 pilhas, conforme orientação.
    2- o funcionamento é automático e não autômato, ou seja, ele segue a rotina do programa fazendo o que está lá passo a passo, mas não está medindo ou tomando decisões. Por exemplo: ao ligar, ele gira o servo, supostamente faz as medições e anda para frente por um intervalo de tempo. Então pára, supostamente faz as medições de novo e segue… isto é, se ao seguir tiver um objeto a frente, ele bate até dar o tempo pré estabelecido e supostamente o sensor fazer as medições novamente, mas ao fazer as medições ele segue “cegamente” para frente, não importa se já estava empurrando o objeto ou não.
    Como faço para que o sensor fique constantemente medindo enquanto o robô anda para frente e se encontrar um obstáculo ele efetivamente pare e tome a decisão?! Desculpe se eu estiver errado na conclusão, mas é o que me parece que este robô está fazendo. O que posso estar fazendo de errado?
    Obrigado pela atenção.
    rogerio.

  4. Cheila Silva Santos - 6 de setembro de 2016

    Olá, tem como fazer esse robô utilizando o módulo Bluetooth? Estou estudando fazer um robô para projeto de Feira na minha escola… e como ficaria o código se colocasse também o Bluetooth?
    Att, Cheila.

  5. Eugenio Paccelli Bittencourt Rocha - 28 de julho de 2016

    Gostei do exemplo. Estou trabalhando em um protótipo que irá funcionar de maneira autonoma e também por meio de comandos que enviarei na porta serial através de uma shield wi-fi e uma interface web. Gostaria de ver algum exemplo prático.

  6. Higor - 27 de julho de 2016

    Venho acompanhando filipiflop e WR KIts Engenharia, Adilson…… são feras…… deve ter mais gente (PARABÉNS)….. como faço pra adquirir as peças para montar este projeto? Tenho o arduino já. Me envia contato por e-mail por gentileza. Abraço!

  7. Thiago - 26 de julho de 2016

    Gostei, vou fazer um.

  8. José Bernardes - 26 de julho de 2016

    WAGNER RAMBO, obrigado pelas orientações. vou montar o meu, se tiver dúvidas entrarei em contato.
    Espero que continues a ajudar nos nossos primeiro passos.
    ABÇS!
    Bernardes

Deixe uma resposta