O trabalho do projeto final teve o objetivo de aprimorar e corrigir problemas no robô com base no Trabalho Prático 3, de forma que ele fosse capaz de executar as seguintes tarefas na Competição de Robôs:
O robô foi capaz de executar todas as tarefas propostas.
O objetivo era ser capaz de participar da competição, com o desenho de campo abaixo:
Construímos o robô com a estratégia de pegar blocos não pretos e levar para a base.
Houve mudanças significativas na estrutura física para acomodar melhor o kit Arduino dentro do robô, pois a estrutura anterior se demonstrava frágil nesse quesito. Fizemos uma montagem ao redor das rodas para ajudar na sustentação e proteção lateral robô.
Uma estrutura estática em forma de “U” foi construída para que fosse possível captar os blocos espalhados na mesa da competição. Além disso, nas corridas de teste que fizemos, notamos que blocos se encaixavam nas laterais do robô e eram arrastados de forma não intencional, então tivemos que montar estruturas dos dois lados para evitar esse problema.
A estratégia do robô consistia de uma máquina de estados, com a seguinte lógica de operação :
Como citado na sessão anterior, a máquina de estados era a base da lógica do robô. Ela possuía uma função principal, que chamava as funções de cada estados, por meio de um switch case. Dentro de cada estado são realizadas as lógicas e chamadas funções referentes a ações mais complexas.
int Localiza() { Tarefas::AlinhaComLampada(); delay(1000); return GIRA180; } int Gira180() { gira_sentido_antihorario(12); return SAIDABASE; } int SaiDaBase() { set_speed(DEFAULT_LEFT_PWM_SPEED*1.2, DEFAULT_RIGHT_PWM_SPEED*1.2); anda(35); return SEGUELINHA; } int SegueLinha() { lcd.begin(16, 2); lcd.setCursor(8, 1); if(DetectaObjeto()) { lcd.print("DETECTEI"); para(); return OLHACOR; } else { Tarefas::SegueLinha(); } delay(10); return SEGUELINHA; } int OlhaCor() { delay(100); char cor = DetectaCor(); delay(10); if(cor == black ) { return RECUA; } else { return GIRABASE; } } int GiraBase() { Tarefas::AlinhaComLampada(); return RETORNABASE; } int RetornaBase() { anda(60); return RECUABASE; } int RecuaBase() { anda_re(10); return GIRA1802; } int Gira1802() { gira_sentido_antihorario(12); return SAIDABASE2; } int SaiDaBase2() { anda(20); return SEGUELINHA; } int Recua() { anda_re(10); return GIRA60; } int Gira60() { gira_sentido_horario(2); return ANDARETO; } int GiraMenos60() { gira_sentido_antihorario(4); return SEGUELINHA; } int AndaReto() { set_speed(DEFAULT_LEFT_PWM_SPEED, DEFAULT_RIGHT_PWM_SPEED); anda(12); return GIRAMENOS60; } int MaquinaDeEstados(int estadoAtual) { int proximoEstado; switch(estadoAtual) { case LOCALIZA: proximoEstado = Localiza(); break; case GIRA180: proximoEstado = Gira180(); break; case SEGUELINHA: proximoEstado = SegueLinha(); break; case GIRABASE: proximoEstado = GiraBase(); break; case RETORNABASE: proximoEstado = RetornaBase(); break; case RECUABASE: proximoEstado = RecuaBase(); break; case RECUA: proximoEstado = Recua(); break; case GIRA60: proximoEstado = Gira60(); break; case ANDARETO: proximoEstado = AndaReto(); break; case GIRAMENOS60: proximoEstado = GiraMenos60(); break; case OLHACOR: proximoEstado = OlhaCor(); break; case SAIDABASE: proximoEstado = SaiDaBase(); break; case SAIDABASE2: proximoEstado = SaiDaBase2(); break; case GIRA1802: proximoEstado = Gira1802(); break; } return proximoEstado; }
Os maiores desafios nesse ponto foram fazer o robô detectar com precisão os blocos e ajustar os giros quando ele estava se localizando, saindo da base e seguindo a linha. Na detecção de blocos, o bloco preto foi um desafio a parte, pois sua cor dificulta a detecção. Esta detecção falhou na competição. Tivemos problemas com os giros também devido à falha em cima da hora da apresentação de nossos encoders e a consequente necessidade de adaptar algumas funções para executarem com base em tempo e não mais na medição das rotações das rodas.