Trabalho Prático 2 - Robótica móvel (locomoção)
1. Objetivo:
O Trabalho Prático 2 - Robótica Móvel teve como premissa a introdução aos conceitos de controle em malha-aberta, utilização de sensores ópticos (detecção de objetos e cores) e processamento dos sinais medidos. As tarefas a serem desempenhadas pelo robô móvel são:
1.1. Locomoção:
Realização de um determinado caminho que será selecionado através do menu. Os caminhos a serem selecionados são: linha reta, triângulo retângulo e quadrado, onde para a linha reta e quadrado, a distância deverá ser de 30cm (para o segmento de reta, aresta) e para o triângulo retângulo, os segmentos dos catetos a serem percorridos são também de 30cm. A restrição mecânica imposta foi de que somente dois motores poderiam ser utilizados na construção do robô.
1.2. Identificação de cor:
Identificação das cores de objetos (cubos de isopor pintados de vermelho, verde, azul, amarelo e preto) utilizando 3 LEDs RGB (Red, Green, Blue) e sensor LDR (Light Dependent Resistor) conectado à entrada analógia da placa de controle.
1.3. Multitarefa e tomada de decisão:
Realização de tarefas múltiplas de locomoção e identificação de um objeto e da cor deste objeto: durante a realização da trajetória em linha reta, em um determinado momento, o robô deverá detectar a presença de um objeto na pista (bloco de isopor pintado) e determinar a cor do mesmo. Conforme a cor do objeto detectada o robô deverá tomar uma decisão: bloco azul - virar à direita 90^o DEG, amarelo - virar à esquerda 90^o DEG e andar para frente, bloco vermelho - girar 180^o DEG e andar para frente, boco verde - parar e dar um giro de 360^o DEG. Observando que após a identificação de cor, o robô deve fazer um pequeno movimento para trás antes de realizar o giro. As tarefas devem ser interrompidas se o robô não encontrar nenhum bloco no intervalo de 10s.
Todas as tarefas devem ser acessadas através de um menu visualizada no LCD e selecionáveis através de push-buttons.
2. Introdução:
Para a realização das tarefas, foi construído um robô móvel utilizando dois motores elétricos e uma roda livre (do tipo Castor). Duas caixas de redução foram utilizadas sendo que para cada uma delas há duas correntes conectando a caixa de redução as rodas. Objetivando uma montagem robusta, na parte superior do motor, foi inserido um compartimento para alojamento da caixa de baterias e logo acima a placa de controle contendo: placa de Interface Gráfica com o Usuário (placa com display e teclado); placa de potência para acionamento dos motores e placa principal contendo o microcontrolador e demais periféricos. Na parte frontal do robô há uma pequena caixa contendo um LED RGB e um LDR para detecção e identificação da cor do objeto.
3. Desenvolvimento:
O desenvolvimento foi desmembrado em três áreas: mecânica, elétrica/eletrônica e software embarcado.
3.1. Mecânica:
A montagem mecânica foi elaborada utilizando duas caixas de redução conectadas as rodas principais via conjunto de duas correntes. Por utilizar somente dois motores elétricos e sendo necessário o robô realizar curvas, uma roda livre do tipo Castor foi usada, possibilitando a realização de curvas através do controle do acionamento dos motores elétricos. As figuras abaixo exibem a montagem mecânica completa do robô onde pode-se observar a conexão entre os motores elétricos e as caixas de redução, e das caixas de redução as rodas. A roda que possibilita o movimento livre do robô em qualquer sentido é a roda do tipo Castor. Optou-se pelo uso da roda do tipo Castor como opção ao uso de uma roda livre implementada com esfera de desodorantes do tipo roll-on. Ainda na base mecânica do robô há a construção de uma espécie de torre para abrigar o conjunto de baterias e as placas eletrônicas.
O sensor para detecção e identificação de cores foi montado na parte da frente do robô, tendo sido utilizadas peças mecânicas como extensão de forma a obter o melhor posicionamento do sensor em relação ao objeto a ser detectado. A estrutura da caixa do sensor foi elaborada de forma a abrigar o sensor de luz (LDR) e o LED RGB. Uma separação mecânica foi inserida (internamente) entre o LDR e o LED RGB de forma a não ter uma saturação do LDR quando no acionamento do LED RGB.
3.2. Elétrica/Eletrônica:
A parte elétrica/eletrônica do robô foi elaborada através de uma placa de interface com o usuário (LCD e push-buttons), placa de controle principal (Arduino Atmega 2560) e placa para controle dos motores elétricos. Associada à placa principal, utilizou-se uma placa de adaptação (fornecida pelo Prof. da disciplina) para conexão com o sensor de luz (LDR) e LED RGB.
Devido ao acionamento dos motores causar interferência eletromagnética (seja por condução ou irradiação), procurou separar ao máximo as conexões dos sinais das conexões dos motores elétricos. As conexões foram isoladas eletricamente e agrupadas de forma a não haver interferência nas partes móveis do robô.
3.3. Software Embarcado:
O software embarcado foi elaborado em C/C++ na IDE Arduino para uma placa do tipo Atmega 2560. A parte de acionamento do motor seguiu o padrão anterior (utilizado no TP1), com a ressalva de que houve necessidade de uma espécie de calibração do valor do PWM (Pulse Width Modulation) para acionamento do motor uma vez que os motores elétricos apresentaram comportamente diferente no número de rotações (ao acionar os motores elétricos ao mesmo tempo para o deslocamento em linha reta, devido o número de rotação dos motores diferirem, o robô acabava por deslocar tendendo a fazer uma curva). O valor do PWM necessário para que o robô fizesse uma trajetória em linha reta foi realizado de forma experimental uma vez que neste trabalho não era permitido o uso de sensores de rotação.
3.3.1. Identificação de objeto/cor:
Para resolver a tarefa de identificar blocos posicionados à frente do sensor e detectar suas respectivas cores, foi feita uma montagem utilizando um sensor LDR e um LED RGB (emite as três cores). Sua configuração final segue abaixo:
O sensor LDR é um resistor cuja resistência varia de acordo com a intensidade da luz que incide sobre ele. Seu funcionamento típico é: à medida que a intensidade da luz aumenta, a sua resistência diminui. Dessa forma, na escuridão, o LDR possui uma resistência máxima, e na luz muito brilhante, sua resistência é mínima.
Para a montagem física do sensor, o LDR foi posicionado em cima do LED RGB e eles foram separados por uma divisória branca (folha grossa). Feito isso, ambos foram envoltos por uma caixinha coberta por fita isolante. Essa configuração foi necessária para deixar a luz emitida pelo LED um pouco mais difusa (sombra sutil e quase imperceptível). Além disso, a caixa escura possibilitou uma melhora nos resultados de leitura do sensor LDR.
Para o circuito do sensor, foi usado um resistor de 10kΩ (R1), um de 180Ω e dois de 100Ω (R2,R3 e R4). O resistor de 10kR foi usado para completar o divisor de tensão com o sensor LDR. Já os outros resistores foram utilizados para limitar as correntes em cada uma das cores (vermelho, verde e azul).
Como dito anteriormente, a resistência (R2) do sensor LDR varia de acordo com a intensidade da luz. Ao montar um divisor de tensão adicionando um outro resistor ao circuito (R1), temos como resultado a equação:
V_LDR = R2*V / (R1+R2) → V_LDR = 1/((R1/R2)+1)
Através da equação, observa-se que a tensão de saída (V_LDR) é diretamente proporcional à resistência (R2) do sensor LDR. Ou seja, a tensão de saída será maior com um índice de luminosidade incidente menor. O circuito do divisor de corrente segue abaixo:
Para a calibração do sensor foi feito primeiro a identificação dos blocos posicionados à sua frente. Essa identificação foi feita seguinido os seguinites passos:
- Pega a média de dez leituras do sensor LDR com a luminosidade ambiente
- Decrementa ao valor da média uma tolerância (média/10) para facilitar a detecção
- Aproxima um objeto ao sensor LDR
- Pega a média de dez leituras do sensor LDR com o objeto colocado a sua frente
- Acrescenta ao valor da média uma tolerância (média/10) para facilitar a detecção
Segue abaixo o código para essa parte da calibração:
// Analiza a luminosidade do ambiente ambiente_cal = mediaLeituras(mediasSensor); // Tolerância para facilitar detecção ambiente_cal -= ambiente_cal/toleraciaDeteccao; // Aproxime um objeto qualquer ao sensor delay(5000); // Aguarda 5 segundos para aproximação do objeto // Calibrando... // Analiza a intesidade de luz com o objeto colocado em frente ao sensor objeto_cal = mediaLeituras(mediasSensor); // Tolerância para facilitar detecção objeto_cal += objeto_cal/toleraciaDeteccao; // Remova o objeto while(analogRead(ldr) < ambiente_cal); // Aguarda a remoção do objeto
A calibração para a identificação das cores dos blocos posicionados à frente do sensor foi um pouco diferente. Foi preciso saber o máximo e o mínimo da leitura do sensor e depois mapear/converter esses valores para uma escala RGB(0-255). Dessa forma, foi feito o que segue:
- Calibração do Branco (Maior incidência de luz): Posicionando-se um objeto branco à frente do sensor, incide-se as três luzes (vermelho, verde, azul) sobre a superfície. São feitas 10 leituras de tensão proporcional às cores incididas (vermelho, verde, azul). É feito a média para o vermelho, para o verde e para o azul. As médias são armazenadas em um vetor, cada cor em uma posição diferente (1-vermelho, 2-verde, 3-azul).
- Calibração do Preto (Menor incidência de luz): Faz-se o mesmo, mas agora com um objeto preto à frente do sensor. A média dos valores lidos é salva em outro vetor, e assim a calibração está concluída.
Temos abaixo o vídeo da calibração seguido do código para a calibração do preto:
// São realizadas 10 medidas para encontrar o valor mínimo registrado pelo sensor for(int i = 0; i < 10; i++) { // Acende o LED vermelho digitalWrite(led_r, LOW); delay(100); // Realiza leitura do sensor e avalia se é o menor para o vermelho leitura_ldr[0] = mediaLeituras(mediasSensor); if (leitura_ldr[0] < black_cal[0]) { black_cal[0] = leitura_ldr[0]; } // Apaga o LED vermelho digitalWrite(led_r, HIGH); delay(100); // Acende o LED verde digitalWrite(led_g, LOW); delay(100); // Realiza leitura do sensor e avalia se é o menor para o verde leitura_ldr[1] = mediaLeituras(mediasSensor); if (leitura_ldr[1] < black_cal[1]) { black_cal[1] = leitura_ldr[1]; } // Apaga o LED verde digitalWrite(led_g, HIGH); delay(100); // Acende o LED azul digitalWrite(led_b, LOW); delay(100); // Realiza leitura do sensor e avalia se é o menor para o azul leitura_ldr[2] = mediaLeituras(mediasSensor); if (leitura_ldr[2] < black_cal[2]) { black_cal[2] = leitura_ldr[2]; } // Apaga o LED azul digitalWrite(led_b, HIGH); delay(100); } // Remova o objeto while(analogRead(ldr) < ambiente_cal); // Aguarda a remoção do objeto // Fim da calibração delay(1000);
Partindo do pressuposto que a calibração foi terminada, a identificação de cores e a multitarefa já podem ser realizadas. A etapa de identificação de cores é feita através das funções leSensor() e enviaCores(). A função leSensor(), faz a leitura incidindo cada um dos leds 10 vezes e armazenando a média desses valores. Essa rotina segue abaixo:
// Rotina de leitura do sensor void leSensor() { digitalWrite(led_r, LOW); // Acende o LED vermelho delay(100); // Aguarda 100ms para o LDR estabilizar leitura_ldr[0] = mediaLeituras(mediasSensor); // Realiza a leitura do sensor digitalWrite(led_r, HIGH); // Apaga o LED vermelho delay(100); // Aguarda 100ms para o LDR estabilizar digitalWrite(led_g, LOW); // Acende o LED verde delay(100); // Aguarda 100ms para o LDR estabilizar leitura_ldr[1] = mediaLeituras(mediasSensor); // Realiza a leitura do sensor digitalWrite(led_g, HIGH); // // Apaga o LED verde delay(100); // Aguarda 100ms para o LDR estabilizar digitalWrite(led_b, LOW); // Acende o LED azul delay(100); // Aguarda 100ms para o LDR estabilizar leitura_ldr[2] = mediaLeituras(mediasSensor); // Realiza a leitura do sensor digitalWrite(led_b, HIGH); // Apaga o LED azul }
Para construir a função enviaCores(), foi necessário montar uma base de dados com várias medidas RGB obtidas pela função leSensor(). Foram feitos vários testes para cada um dos blocos (verde, vermelho, azul, amarelo e preto). A partir dessa base de dados, observamos um padrão para cada uma das cores, esse padrão foi utilizado para construir as condições (IF-ELSE) as quais definiram as cores. Segue abaixo o vídeo final da calibração e identificação das cores:
4. Testes:
Os vídeos abaixo exibem o funcionamento do robô na execução das tarefas pré-programadas de locomoção:
Linha reta:
Triangulo:
Quadrado:
A exibição das opções de seleção das tarefas a serem executadas no display são dadas no vídeo abaixo:
Display:
O vídeo seguinte exibe a execução da multitarefa:
Multitarefa:
5. Conclusão:
O trabalho prático propiciou um melhor entendimento dos conceitos apresentados na disciplina de Introdução à Robótica, possibilitando a implementação de um robô móvel capaz de realizar as tarefas pré-programadas de locomoção de, identificação de objetos no curso da trajetória, identificação da cor do objeto e tomada de decisão baseado na cor do objeto identificado. Caso a trajetória seja livre, a limitação por tempo de funcionamento do robô é realizada, parando-o através do desacionamento dos motores elétricos.
Referências:
1. The Art of Lego Design; Martin, Fred G.; March 1995
2. Shield do display/teclado: https://www.dfrobot.com/wiki/index.php/Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)
3. Shield do motor: https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-software








