Podemos dividir a programação da lógica do Eduardoino em vários níveis diferentes. O nível principal é a máquina de estados do fluxo principal de execução. A partir de cada estado, temos várias rotinas diferentes a serem executadas para cada estado.
Essa máquina de estados representa o fluxo de execução principal do robô. Ela é sequencial e sem ciclos, não sendo capaz de, por exemplo, pegar mais de um bloco.
Estado Inicial: Standby. O robô começa em standby até a luz de início da prova ligar. Ele fica lendo o valor do sensor de luz embaixo dele
Transição -> Estado de Localização da Luz. Condição: Sensor de luz embaixo do robô indica que a luz acendeu.
Estado de Localização da luz: O robô gira uma vez, para detectar o máximo e mínimo de luz no sensor LDR diferencial, e uma segunda vez tentando parar de frente para a lâmpada.
Transição -> Estado de Ré. Condição: Quando a leitura do sensor diferencial, no segundo giro, se aproximar do máximo ou mínimo lidos no primeiro giro, de acordo com a base que detectamos que ele está na calibração.
Estado de Ré: O robô gira ambos os motores para andar de ré por 7 segundos, tempo em que ele consegue ultrapassar a segunda linha preta horizontal.
Transição -> Estado Segue Linha. Condição: Após 7 segundos, invariavelmente.
Estado Segue Linha: O robô usa seus sensores LDR na parte de baixo para detectar a linha preta e se orientar na direção dela. Neste estado, uma subrotina envolvendo uma outra máquina de estados é executada enquanto estivermos nesse estado. Nesse estado, também lemos o valor do sensor Óptico para a transição de estado, indicando quando encontramos um bloco ou não.
Transição -> Estado Detectou Bloco. Condição: O sensor Óptico Reflexivo aponta que há um bloco na sua frente.
Estado Detectou Bloco: Nesse estado, identificamos a cor do bloco encontrado, que pode ser preto ou não preto. Essa identificação lê os valores RGB do LDR + LED montados na frente do robô 10 vezes e, a cada RGB lido, diz se a leitura é preta ou não preta. No final das 10 leituras, o resultado é a opção que aparecer mais vezes.
Transição -> Estado de Localização da Luz 2. Condição: O resultado final indica que o bloco não é preto. Transição -> Estado Parado. Condição: O resultado final indica que o bloco é preto.
Estado de Localização da Luz 2: Possui o mesmo comportamento do estado de localização anterior. Difere na transição.
Transição -> Estado de Segue a Luz. Condição: Encontrou, no segundo giro, um valor próximo ao desejado, seja ele o máximo ou mínimo, encontrado no primeiro giro.
Estado de Segue a Luz: O robô se move em linha reta até a intensidade do LDR diferencial ultrapassar um threshold, indicando que ele está dentro da base e, portanto, não precisa se mover mais.
Transição -> Estado Parado. Condição: O valor do LDR diferencial atingiu um threshold definido durante a calibração.
Estado Parado: O robô fica parado, não realizando mais nenhuma ação. Esse é o estado final e, portanto, não podemos sair desse estado.
Durante o Estado Segue Linha, o robô sempre lê os sensores LDR e, de acordo com as leituras dele, se movimenta diferentemente. Sempre assumimos que a linha preta está entre os dois sensores caso ambos sejam brancos.
Estado Branco: Ambos os sensores leram a cor branca, indicando que estamos sob a linha (ou não, mas nesse caso estamos perdidos até encontrar uma linha preta). Nesse caso, o robô anda em linha reta.
Estado Preto Direita: O sensor da direita detectou preto e o da esquerda detectou branco. Indica que ou temos uma curva para a direita ou desajeitamos. Em ambos os casos, a solução é girar para a direita até a próxima leitura.
Estado Preto Esquerda: O sensor da esquerda detectou preto e o da direita detectou branco. Gira para a esquerda até a próxima leitura.
Estado ambos pretos: Ambos os sensores detectaram preto. Nesse caso, o robô sempre vira para a direita, por escolha do grupo.
Realizamos duas calibrações antes da partida. Primeiro, calibramos a luz polarizada. Colocamos o robô na nossa base e ativamos a função de calibrar luz polarizada. Nessa função o robô gira em torno de seu centro e lê o valor lido pelo LDR diferencial. Nessa etapa, guardamos o valor máximo e mínimo lidos e, através desses valores, já estabelecemos em qual base estamos. Depois, calibramos os sensores de linha preta. Posicionamos ele de modo que ele passe por uma parte preta e outra branca em ambos os sensores (não necessariamente nessa ordem). O robô então anda em linha reta e lê o máximo e mínimo dos sensores durante esse percurso e guarda esses valores. A partir dele, podemos estabelecer que valores são pretos e que valores são brancos. Outros thresholds e limites são hard coded ou testados e definidos manualmente, como por exemplo os valores que definem se um bloco é preto ou não.
Tivemos alguns problemas durante a execução, tanto problemas lógicos como físicos, mas em todos o robô foi capaz de sair da base ao menos, o que indica que os problemas não foram no fluxo de execução em si. O robô infelizmente fez exatamente o que foi programado para fazer e seguiu seu fluxo de execução, independente da precisão ou não da leitura que ele recebeu estar correta, ou ser a desejada. De modo geral, com mais tempo seríamos capazes de otimizar e nos preparar para esses problemas, mas no final consideramos a execução em si satisfatória.