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.
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.
Figura 2 – Sensor Ultrassônico HC-SR04
Na Figura 3 pode-se observar as curvas geradas pelo sensor, que o datasheet do fabricante prevê.
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.
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 MakerHero.
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? Deixe seu comentário logo abaixo.
Para inserir um controle via bluethooth nesse projeto como ficaria o código?
Jair,
Dê uma olhada nesse link: https://www.makerhero.com/blog/tutorial-modulo-bluetooth-com-arduino/
Com ele você já consegue ter uma ideia mais ou menos de como chegar lá@
Abraços!
Diogo – Equipe MakerHero
Seus projetos são bons
Olá!
É ótimo saber que gostou do nosso trabalho!
Abraço!
Rosana – Equipe MakerHero
Oi, tem uma foto da conexão dos fios do sensor ultrassonico e do servo motor com a placa motor shield? Sou novata em Arduino.
Sim tenho, te mando via e-mail.
Olá pessoal do http://www.makerhero.com, parabéns pelos tutoriais!
Vocês teriam uma dica de componentes para adicionar conexão wifi a este projeto? é possível utilizar um outro shield wifi? li em alguns fóruns que há uma incompatibilidade de pinos. Ou seria melhor integrar apenas um módulo ESP8266?
Abraços
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.
Qual a lista de materiais completa para aquisição do robô?
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.
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.
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.
Valeu Eugenio! Podemos pensar em projeto assim para daqui uns tempos, fique ligado aqui no blog.
Abraço!
Wagner Rambo
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!
Boa tarde Higor,
Muito obrigado. O material para construção do robô você encontra na Loja MakerHero: http://www.makerhero.com
Abraço!
Adilson – Equipe MakerHero
Gostei, vou fazer um.
Valeu Thiago! Bons projetos para você!
abs!
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
Valeu José! Fique sempre ligado aqui no blog da Filipe Flop!
abraços