Tabela de conteúdos
Robótica móvel - Locomoção
Introdução
O Trabalho Prático 2 consiste no desenvolvimento de um robô diferencial que seja capaz de realizar três tarefas: se locomover, identificar a cor dos bloquinhos disponibilizados e executar um movimento ao encontrar um bloquinho. Para facilitar a usabilidade e execução de tais atividades foi requisitado, também, a criação de um menu.O objetivo desse trabalho consiste em experimentar os problemas e soluções encontrados na robótica móvel, como por exemplo o de sua cinemática. Além disso foi introduzido o uso de sensores e o estudo de suas leituras e estruturas funcionais. A robótica móvel ao contrário da robótica de manipuladores é um campo mais amplo e, portanto apresentando mais áreas de pesquisa em aberto como localização,locomoção, mapeamento, manipuladores móveis, entre outros. Nessa temática lidamos com um espaço tridimensional, logo para que seja possível a interação do robô com esse ambiente que se encontra é necessário o uso de sensores.Assim, os sensores coletam dados que permitiram determinar uma decisão que o dispositivo será encarregado de executar.
Materiais
- Lego
- Arduino Mega 2560 (com respectivo cabo)
- 2 motores DC
- Braçadeiras
- Alicate de corte
- Alicate de bico
- Fios
- Ferro de solda
- Solda
- Termo Retrátil
- Abraçadeira
- Rolon
- LDR
- 3 LED'S - (Vermelho,Azul e Verde)
- Resistor
Procedimentos
A montagem do robô foi dividida em 3 etapas:
- Criação da base do robô;
O processo criativo da base se dividiu em três etapas e foi a parte mais demorada do trabalho por demandar diversas montagens que se adequassem à solução do problema. Primeiramente montamos uma base simples onde um dos motores movia o robô enquanto outro direcionava o mesmo o problema com essa montagem era a incapacidade de rotacionar no seu próprio eixo, então decidimos mudar para um robô diferencial que fosse capaz de realizar tal tarefa colocando o Arduíno na frente do eixo do motor nessa segunda montagem nos deparamos com o problema do torque, sendo que era muito difícil do robô carregar o peso do Arduíno nessa configuração. Assim em nosso ultimo modelo colocamos o peso do Arduíno exatamente em cima do eixo de rotação para maximizar a potência, essa montagem se mostrou bem resistente e conseguiu carregar mais peso com uma velocidade considerável.
- Sensor;
- Implementação do código para o Arduino;
Documentação do código
O código foi estruturado em partes e em partes testado. Há basicamente 6 partes do código: o código do menu(que foi baseado na lógica demonstradas nos vídeos abaixo), o código de andar reto e voltar, de fazer um triangulo e um quadrado, a parte do sensor e do multitarefa.
https://www.youtube.com/watch?v=tRoznRBYQHA
https://www.youtube.com/watch?v=1XO13niGXps
- O Menu
Para o Menu foi implementado um loop infinito, que podia ser acessado com os botões Para Baixo e Para a Esquerda
// --- Loop Infinito ---
void loop()
{
if(!sub_menu)
{
lcd.setCursor(1,line[0]);
lcd.print("1) Locomocao ");
lcd.setCursor(1,line[1]);
lcd.print("2) Identificacao de cor ");
lcd.setCursor(1,line[2]);
lcd.print("3) Multitarefa ");
lcd.setCursor(1,line[3]);
lcd.print("4) Calibracao ");
}
botao = analogRead (0); //Leitura do valor da porta analógica A0
readButts(botao);
} //end loop
Lista do MENU
void list_menu()
{
for(int i=3; i>-1; i--)
{
index = i-1;
line_bk[i] = line[i];
if(index < 0) line[i] = line_bk[i+3];
else line[i] = line[i-1];
}
} //end list_menu
Ao escolhermos uma opção com o botão Para a direita o programa executava a atividade desejada.
2. O Sensor
O código do sensor era composto por 4 funções básicas, nas quais eram: Calibragem(), Reconhecimento_Blocos(), Leitura() e ConvertRGB(int atual, char palavra[4]).
A função Calibragem() é chamada apenas no setup, onde ela calibra o sensor para os valores mínimos e máximos de cada cor que serão lidos pelo arduino, no qual se pede uma superficie branca e outra preta para se ter os valores.
A função Leitura() é a que fica por conta de fazer verificar de fato a leitura da cor, onde, primeiro liga o LED vermelho por 0,1s e lê o valor que está no pino 8 do Arduino, e registra esse valor em uma variável e repete o procedimento para os leds verde e azul. e no fim da leitura dos 3 LEDS, ele espera por 0,3s.
A função ConvertRGB tem como função converter o valor do LDR, que pode variar de 0 a 1023 para cada uma das 3 cores, para valores do padrão da representação numérica RGB, que varia de 0 a 255. A função recebe dois parametros, onde um é a leitura no formato analógico, e uma string com 4 caracteres que se refere a qual cor aquela leitura, na qual pode ser “verm”, “verd”, e “azul” (Que são os valores de cada um dos 3 leds). Após isso, a função retorna o valor da superficie lida no padrão numérico RGB.
A função Reconhecimento_Blocos() tem como função aprender os valores RGB de cada um dos blocos da apresentação, e salva os valores nos vetores blocoVermelho[3], blocoVerde[3], blocoAzul[3] e blocoAmarelo[3], onde a posição [0] dos vetores corresponde a cor vermelha, a [1] corresponde a verde, e a [2] corresponde a azul. Com isso, ele aprende qual é a cor do bloco para posteriormente poder ler e comparar com esses valores.
Abaixo estão os códigos de cada uma das funções:
FUNÇÃO CALIBRAGEM
void Calibragem(){
//CALIBRAGEM BRANCO
int botao;
botao = analogRead (0);
do{
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("PAPEL BRANCO:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
lcd.clear();
lcd.setCursor(0,0);
lcd.print("PAPEL BRANCO:");
lcd.setCursor(0,1);
lcd.print("Calibrando.");
digitalWrite(PinVerm, 1);
delay(100);
VermMax = analogRead(sensorPin);
digitalWrite(PinVerm, 0);
lcd.print(".");
digitalWrite(PinVerd, 1);
delay(100);
VerdMax = analogRead(sensorPin);
digitalWrite(PinVerd, 0);
lcd.print(".");
digitalWrite(PinAzul, 1);
delay(100);
AzulMax = analogRead(sensorPin);
digitalWrite(PinAzul, 0);
lcd.clear(); // CALIBRAGEM DE PRETO
do{
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("PAPEL PRETO:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
lcd.clear();
lcd.setCursor(0,0);
lcd.print("PAPEL PRETO:");
lcd.setCursor(0,1);
lcd.print("Calibrando.");
digitalWrite(PinVerm, 1);
delay(100);
VermMin = analogRead(sensorPin);
digitalWrite(PinVerm, 0);
lcd.print(".");
digitalWrite(PinVerd, 1);
delay(100);
VerdMin = analogRead(sensorPin);
digitalWrite(PinVerd, 0);
lcd.print(".");
digitalWrite(PinAzul, 1);
delay(100);
AzulMin = analogRead(sensorPin);
digitalWrite(PinAzul, 0);
lcd.clear();
}
FUNÇÃO LEITURA
void Leitura(){
digitalWrite(PinVerm, 1); // Leitura Pino Vermelho
delay(100);
int sensor_val = analogRead(sensorPin);
Red = ConvertRGB(sensor_val,"verm");
digitalWrite(PinVerm, 0);
digitalWrite(PinVerd, 1); // Leitura Pino Verde
delay(100);
sensor_val = analogRead(sensorPin);
Green = ConvertRGB(sensor_val,"verd");
digitalWrite(PinVerd, 0);
digitalWrite(PinAzul, 1); // Leitura Pino Azul
delay(100);
sensor_val = analogRead(sensorPin);
Blue = ConvertRGB(sensor_val,"azul");
digitalWrite(PinAzul, 0);
delay (300);
}
FUNÇÃO DE RECONHECIMENTO DOS BLOCOS
void Reconhecimento_Blocos(){
int botao;
botao = analogRead (0);
lcd.clear(); // Reconhecimento Bloco Vermelho
do{
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("BLOCO VERMELHO:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
Leitura();
blocoVermelho[0] = Red;
blocoVermelho[1] = Green;
blocoVermelho[2] = Blue;
lcd.clear(); // Reconhecimento Bloco Verde
do{
botao = analogRead (0);
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("BLOCO VERDE:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
Leitura();
blocoVerde[0] = Red;
blocoVerde[1] = Green;
blocoVerde[2] = Blue;
lcd.clear(); // Reconhecimento Bloco Azul
do{
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("BLOCO AZUL:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
Leitura();
blocoAzul[0] = Red;
blocoAzul[1] = Green;
blocoAzul[2] = Blue;
lcd.clear(); // Reconhecimento Bloco Amarelo
do{
botao = analogRead (0);
lcd.setCursor(0,0);
lcd.print("BLOCO AMARELO:");
lcd.setCursor(0,1);
lcd.print("Aperte Select");
}while(not(botao >= 600 & botao < 800));
Leitura();
blocoAmarelo[0] = Red;
blocoAmarelo[1] = Green;
blocoAmarelo[2] = Blue;
lcd.clear();
}
FUNÇÃO DE CONVERSÃO PARA O PADRÃO RGB
int ConvertRGB(int atual, char palavra[4]) // Convertendo para o formato de cores RGB{
if (palavra == "verm")
{
float aux = (float(atual) - float(VermMin)) / (float(VermMax) - float(VermMin));
aux = aux*255;
if (aux > 255)
return (255);
else if (aux <0)
return (0);
else
return (aux);
}
else if (palavra == "verd")
{
float aux = (float(atual) - float(VerdMin)) / (float(VerdMax) - float(VerdMin));
aux = aux*255;
if (aux > 255)
return (255);
else if (aux <0)
return (0);
else
return (aux);
}
else if (palavra == "azul")
{
float aux = (float(atual) - float(AzulMin)) / (float(AzulMax) - float(AzulMin));
aux = aux*255;
if (aux > 255)
return (255);
else if (aux <0)
return (0);
else
return (aux);
}
}
A função Loop usa as funções pré-estabelecidas chamando a função Leitura, e verificando as variáveis Red, Green e Blue, que são os valores já convertidos para o padrão RGB, e compara se os valores são próximos (com um grau de sensibilidade) aos registrados nos vetores dos blocos, como descritos acima. Após os testes lógicos, ele imprime na tela a cor do bloco e altera o valor da variável global Cor_Bloco para o valor respectivo de cada bloco, e caso se a cor não for a de nenhum bloco, ele imprime “Sem Bloco”, e variável Cor_Bloco continua 0. Essa variável serve para que no modo Multitarefas, ele chame a função e só teste o valor da variável global, para saber qual será a ação a ser realizada.
Resultados
Problemas encontrados
Durante a confecção do robô alguns desafios surgiram principalmente na parte física, inicialmente questões sobre robustez e a capacidade de carregar peso foram a primeira barreira encontrada perante nossas ideias iniciais no entanto a discussão sobre onde o peso do robô, em especial o Arduíno que constitui a parte mais expressiva da massa do objeto, se posicionaria em relação os eixo da roda para minimizar o torque e reduzir dessa forma o gasto energético dos motores.
Ao longo da construção vimos que a diferença entre os motores que estavam disponíveis poderia se tornar um problema cada vez maior, a primeira ideia para transpor essa dificuldade foi a criação de uma caixa diferencial ligando as caixa de redução e assim possibilitar um maior equilíbrio para o robô ao se locomover em linha reta , ideia essa que foi abandonada e subsistida por uma solução em software.
Após diversas montagens e configurações diferentes para a estrutura chegou-se em um patamar mais estável onde a massa expressiva estava posicionada logo a cima dos eixos de rotação e assim podemos passar para uma fase de teste do código, nessa etapa encontramos a maior dificuldade que não conseguimos solucionar a tempo da apresentação final: o grande gasto energético que o sistema possuía, com esse gasto incomum os testes do código foram todos inconclusivos pois em menos de três testes seguidos a caraga das pilhas diminuíam significativamente modificando o movimento desejado. Esse erro fazia o nosso robô ir muito rápido enquanto a bateria estivesse cheia e ia gradativamente abaixando sua velocidade e força em poucos minutos dia cordo com o grande gasto, foram gastos mais ou menos oito pacotes contendo quatro pilhas alcalinas em um dia e meio de teste, além disso era impossível testar utilizando a fonte do Arduíno pois essa montagem não possuía força o suficiente para mover o carrinho a partir da inercia.
Pontos a melhorar
Os principais pontos a melhorar que foram levantados pelo professor durante a apresentação foram a falta de robustez do apoio do Arduíno que se soltava com facilidade quando era necessário mover o controlador e isso causava uma leve desregulagem da engrenagem motriz que atrapalhava a rotação das rodas ocasionando um gasto maior de energia.
Outro ponto a melhorar são questões referente aos motores não somente a apresentação mas principalmente se estava funcionando de maneira adequada pois como dito na seção de dificuldades enfrentamos ma gasto energético extremamente alto e um dos motivos poderia ser um motor ruim ou que gastava muita energia.













