Ferramentas do usuário

Ferramentas do site


cursos:introrobotica:2019-1:grupo06:tp2

Colorful Potato

Trabalho Prático 2 - Locomoção

Introdução

A missão dessa vez era construir um robô móvel que ainda fosse capaz de detectar objetos e suas cores. As tarefas que o Colorful Potato deveria executar são:

  1. Percorrer o perímetro de um quadrado
  2. Percorrer o perímetro de um triângulo
  3. Percorrer uma linha, ida e volta
  4. Detectar as cores de blocos verdes, azuis, vermelhos e amarelos
  5. Explorar um ambiente e ter um comportamento específico toda vez que encontrar um bloco

Estrutura física

A fim de diminuir os efeitos da diferença de velocidade dos motores, a redução feita foi simétrica. As paredes verticais do robô foram feitas com uma peça furada travada em vez de uma pilha de peças convencionais.

O LDR foi utilizado como sensor para detectar as cores e para detectar objetos na frente do robô, com o auxílio de um LED RGB. A luminosidade medida pelo LDR variava muito nos nossos testes, então a etapa seguinte foi fixar a posição relativa do LDR ao LED. Foram furadas 3 peças de lego para encaixar o LED RGB e o LDR de forma que fosse possível montar o sensor convenientemente no robô.

Algoritmo

O código foi modularizado de forma a criar camadas de abstração, permitindo a colaboração mesmo sem a implementações de partes do código ou que todas as pessoas estivessem se preocupando com especificidades da implementação.

Está disponpivel no GitHub:


O arquivo principal “ColorfulPotato.ino” é onde foi implementado o menu, que chama as tarefas de Tarefas.h optadas pelo usuário.


Cada tarefa tem uma função que corresponde a um requisito de comportamento do robô, por exemplo:

void MostraNoLCDCorDetectada();
void ExploraAmbiente();


Cada uma dessas funções executa a sequencia de ações para realizar a tarefa. Essas ações são acionamentos e medições feitas em Movimentacao.h e SensorDeLuz.h


Movimentação:

void para();
void anda(int d);
void gira_sentido_horario(double t);
void anda_re(int d);
void gira_sentido_antihorario(double t);
void set_speed(int left_speed , int right_speed);
void set_speed()


SensorDeLuz

bool DetectaObjeto();
char DetectaCor();
void SENSORDELUZ_SETUP();

Para detecção das cores, foram feitos os procedimentos abaixo:
1) Fazer uma leitura da iluminação ambiente com o LDR, com o LED apagado;
2) Acender separadamente cada uma das 3 cores do LED e medir a reflexão com o LDR;
3) Subtrair a leitura de iluminação ambiente das leituras das cores e armazenar esses valores.

Com esses procedimentos, foi possível realizar diversas medidas com os blocos a detectar e chegar empiricamente ao algoritmo abaixo, com resultados satisfatórios:

  // Algoritmo que calcula a cor
  if(blueOutput > redOutput && blueOutput > greenOutput){
 
    Serial.println("BLUE");
  }else if(greenOutput > redOutput && greenOutput > blueOutput){
 
    Serial.println("GREEN");
  }else if(redOutput*0.55 > greenOutput){
 
    Serial.println("RED");
 
  }else if(redOutput*0.6 < blueOutput){
 
    Serial.println("BLACK");
  }else {
 
    Serial.println("YELLOW");
  }

A lógica por trás desse algoritmo consiste do fato de que para blocos vermelhos, amarelos e pretos a resposta do led vermelho é a mais intensa. Dessa forma, para distinguir entre os três, utiliza-se da proporção entre o valor da resposta ao led vermelho e as demais cores, calculada de forma empírica. Por fim, os blocos são detectados como azuis ou verdes quando a respostas dos leds de suas respectivas cores são as maiores entre as três.

Para detectar a presença de objetos na frente do sensor, foi definido a utilização de um valor limiar de escuridão (THRESHOLD_OBSTACULO_DE_LUZ) que, se houvesse uma medida abaixo desse valor, seria considerado que um objeto havia sido detectado.

As constantes de pinagem, velocidade, limiares, dimensões, etc., necessárias para o código foram definidas em Configuracao.h, que ficou com essa cara:

/*      LED E LDR    */
// Pinos dos LEDs
const int RED_PIN   = 23; // Fio vermelho
const int GREEN_PIN = 25; // Fio azul
const int BLUE_PIN  = 27; // Fio laranja; Fio marrom é o terra
// Pino do LDR
const int LDR_PIN = A8; // VCC=vermelho, GND=marrom, SIG(A8)=amarelo
 
/*      LUZ E LUMINOSA   */		
const int THRESHOLD_OBSTACULO_DE_LUZ = 150;

O uso de #define's foi substituido por definições com const tanto quanto possível em função de uma recomendação encontrada nessa referência

Desafios

Os maiores desafios desse trabalho foram a elaboração do algoritmo de detecção de cores, fazer com que o LDR detectasse um objeto e realizar as tarefas de maneira assíncrona da atividade de multitarefas.

O algoritmo de cores, apesar de ter um código simples, foi complicado de ser elaborado por não haver uma forma teórica de prever e calcular os valores, visto que o LDR é um sensor bem básico para medição de luminosidade e só possui alta sensibilidade em parte do espectro vísivel dos comprimentos de onda da luz. Assim, o algoritmo exigiu que fosse feito um experimento empírico para elaboração do código.

Para detectar um objeto, a dificuldade foi parecida com a do algoritmo de cores. Nesse caso, um sensor óptico deveria ter sido utilizado para maior confiabilidade na detecção, mas no fim foi possível realizar detecção com o LDR satisfatoriamente.

Na operação multitarefa, o desafio era evitar que o código ficasse preso em loops e principalmente delays de uma tarefa específica, impedindo que outras tarefas fossem executadas simultaneamente. Desta forma, foram elaboradas funções para movimentar o robô para frente e para trás que, com os devidos valores passados por parâmetros, não prendem a execução do código dentro das mesmas. Então, foi possível chamar uma função que manda o robô andar indefinidamente, sem travar o código, e realizar outras tarefas como chamar a detecção de objetos e verificar se o tempo de 10 segundos que o robô estava andando havia se esgotado para poder encerrar a tarefa.

Registro AudioVisual

cursos/introrobotica/2019-1/grupo06/tp2.txt · Última modificação: 2019/05/13 19:51 por introrobotica-grupo6

Ferramentas da página