O robô mostrado aqui foi construído para participar de campeonato de sumô de robôs na categoria quinhentas gramas. Neste tipo de competição o robô deve mover-se dentro de uma arena preta com bordas brancas procurando seu oponente para empurra-lo para fora da arena. Na categoria do Eniac Jr., como foi batizado, além de não poder pesar mais que quinhentos gramas, o robô não deve ter largura e comprimento superiores a 10 cm.
A estrutura
A estrutura é composta basicamente por duas placas de compensado 4 mm e quatro pedaços de barra roscada de 4mm de diâmetro e 9cm de comprimento. Na primeira plataforma (8cm x 6 cm) estão os servo motores, presos por abraçadeiras, e os sensores de linha. Na segunda (10cm x 8 cm), o arduino com uma sensorshield, que é a placa sobre o arduino, usada para facilitar a conexão dos sensores e servos, o UBEC (regulador 5V x 5A), é necessário pro que os servos são forçados e não é conveniente alimenta-los diretamente pelo arduino. O sensor de oponente e demais componentes eletrônicos também estão na segunda plataforma.
A estrutura
A estrutura é composta basicamente por duas placas de compensado 4 mm e quatro pedaços de barra roscada de 4mm de diâmetro e 9cm de comprimento. Na primeira plataforma (8cm x 6 cm) estão os servo motores, presos por abraçadeiras, e os sensores de linha. Na segunda (10cm x 8 cm), o arduino com uma sensorshield, que é a placa sobre o arduino, usada para facilitar a conexão dos sensores e servos, o UBEC (regulador 5V x 5A), é necessário pro que os servos são forçados e não é conveniente alimenta-los diretamente pelo arduino. O sensor de oponente e demais componentes eletrônicos também estão na segunda plataforma.
Apenas duas rodas são usadas. Foram adaptadas do rolo de tração de uma velha impressora. Uma pequena chapa de alumínio substitui a roda frontal.
A eletrônica
Sensor de linha |
Os motores usados são servomotores modificados para rotação. Usar servos trás a vantagens deles já possuirem circuito de acionamento interno, necessitando apenas do sinal de controle e alimentação que neste caso e de 5 V/ 5A, provida por um UBEC (Universal Battery Eliminator Circuit). A bateria usada é uma LIPO 3 células 1300 mAh.
Sensores
O Eniac Jr possui quatro sensores. Tanto os dois sensores de linha frontal quanto o sensor de linha traseira, que não está sensdo usado por ainda não ser necessário no programa, foram montados conforme digrama ao lado.
O quarto sensor é usado para detectar o oponente. Trada-se de um sensor infravermelho sharp GP2Y0A21. Um excelente sensor para este tipo de aplicação por sua velocidade e facilidade de uso.
O microcontrolador
Para controlar o robô foi escolhido o arduino, uma plataforma excepcional por sua capacidade, versatilidade e enorme quantidade de material de consulta. Este projeto está usando o arduino Uno, equipado com o atmega 328, o mais comumente usado hoje. Talvez fosse melhor usar o arduino mini 3.0 por seu tamanho reduzido.
O código fonte que embarca o arduino pode ser visto, com comentários, abaixo. É um programa básico pretendo incrementa-lo. A dinâmica de funcionamento é a seguinte:
Depois de ligado o robô aguada cinco segundos e inicia seu funcionamento andando para frete. Caso encontre a linha branca retorna e gira em torno de si mesmo procurando o oponente com auxilio do sensor frontal. Se encontrar o oponente o robô para de girar e volta a andar para frete. Não encontrando o adversário ele anda para frente após o fim do tempo de procura.
#include <Servo.h>
Servo esquerdo;
Servo direito;
//******************* PINOS **********************//
int direito_pin = 10;
int esquerdo_pin = 11;
int SLF_esq = 8; // pino do sensor de linha frontal esquerdo
int SLF_dir = 9; // pino do sensor de linha frontal direito
int led_pin = 13; // led no pino 13
int sens_front = 5; // pino do sensor oponente frontal (SHARP)( pino analogico 0 )
//****************** VARIAVEIS ******************//
long cm; // variaveis para sensor frontal
float sharp = 0; // usada na leitura dos sensores analogicos
float distancia = 0; // usada na leitura dos sensores analogicos
int tmp_Re = 5; // tempo de reversão dos motores quando o robo encontra a linha*200 milissegundos
int tmp_Busc =3.4; // tempo de procura do adverssario, girando, em segundos
long raio_front = 35; // raio de procura frontal em centimetros
long tmpRound = 90000; // tempo do round 90.000 milissegundos. 1 minuto e 30 segundos
long prev_tmpRound; // variavel para contar tempo do round
unsigned long current_tmpRound; // variavel para contar tempo do round
long previousMillis; // variavel para contar tempo entre buscas
unsigned long currentMillis; // variavel para contar tempo entre buscas
int aux_SLF = 0; // auxiliar para leitura do sensor de linha frontal
int aux_SLT = LOW; //0; // auxiliar para leitura do sensor de linha traseiro
int aux_front = 0; // auxiliar para leitura do sensor frontal
//**************** SETUP *****************************//
void setup() {
Serial.begin(19200);
pinMode(led_pin, OUTPUT);
pinMode(SLF_esq, INPUT);
pinMode(SLF_dir, INPUT);
// conta os cinco segundos piscando o led do pin 13
for(int conte = 0; conte < 5; conte++)
{
digitalWrite(led_pin, HIGH);
delay(300);
digitalWrite(led_pin, LOW);
delay(700);
}
esquerdo.attach(esquerdo_pin,1000,2000); //servo1 no pino 2, min, max
direito.attach(direito_pin,1000,2000); //servo1 no pino 3
prev_tmpRound = millis(); // prev_tmpRound recebe o tempo atua de execução do programa marcando a contagem do round
current_tmpRound = millis();
// procurar(); // inicia procurando o oponente
}
//***************** FIM SETUP ****************************//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////FUNÇÃO PRINCIPAL///////////////////////////////////////////////////////////////////
void loop()
{
int a1 =0;
int proc = 0;
int cnt =0;
int cnt_tmp =0;
static int direcao = LOW;
frente();
aux_SLF = ler_digital(SLF_esq , SLF_dir); // verifica sensor frontal de linha ( HIGH para branco LOW para preto)
// aqui o robo comeca efetivamente seu trabalho andar no tatame a procurar o oponente
// ele para apos 90 segundos (tempo do round)
do
{
if(aux_SLF == HIGH) // se um dos sensores de linha dianteiros encontrou a linha branca
{
re();
while(cnt_tmp < tmp_Re*4)
{
delay(50);
cnt_tmp++;
}
cnt_tmp =0;
procurar();
}
else
{
frente(); //se nenhum dos sensores for acionado continua indo em frente
}
aux_SLF = ler_digital(SLF_esq , SLF_dir); // verifica sensor frontal de linha ( HIGH para branco LOW para preto)
current_tmpRound = millis(); // atualisa current_tmpRound com o tempo atua de execução do programa
}while(current_tmpRound - prev_tmpRound <= tmpRound);//O ROBO ANDA ATE SE PASSAR O TEMPO DE UM ROUND
parar(999999); // para o robo após fim do round
} // fim do void loop()
///////////////////FUNÇÃO PARAR /////////////////////
// como a modificação dos servos não ficou 100% é dificil para-los totalmente
void parar(int time)
{
direito.write(92.5);
esquerdo.write(89.5);
delay(time);
}
///////////////////FUNÇÃO FRENTE /////////////////////
void frente()
{
direito.write(0);
esquerdo.write(180);
}
///////////////////FUNÇÃO RÉ /////////////////////
void re()
{
direito.write(180);
esquerdo.write(0);
}
///////////////////FUNÇÃO DIREITA /////////////////////
void direita()
{
direito.write(180);
esquerdo.write(180);
}
///////////////////FUNÇÃO ESQUERDA /////////////////////
void esquerda()
{
direito.write(0);
esquerdo.write(0);
}
///////////////////FUNÇÃO ler sensores analogicos sharp/////////////////////
// adaptada de:
/* www.ebay.com/itm/5-x-Arduino-IR-Sensor-GP2Y0A21YK0F-Measuring-Detecting-Distance-
10-80cm-/261031972852?_trksid=p4340.m263&_trkparms=algo%3DSIC%26its%3DI%252BC%26itu%3DUCI%
252BIA%252BUA%252BFICS%252BUFI%26otn%3D15%26pmod%3D260944545770%26ps%3D63%26clkid%3D56665851
1840405440&_qi=RTM1062687 */
int ler_analog(int sensor, int raio)
{
sharp = analogRead(sensor);
distancia = (6762/(sharp-9))-4;
if(distancia <= raio)
{
digitalWrite(led_pin, HIGH);
return(HIGH); // retorna HIGH caso o opnente esteja dentro do raio de alcance definido
}
else
{
digitalWrite(led_pin, LOW);
return(LOW); // retorna LOW caso o opnente NÃO esteja dentro do raio de alcance definido
}
}
///////////////////FUNÇÃO ler sensores digitais /////////////////////
int ler_digital(int sens1 , int sens2)
{
if(digitalRead(sens1) == LOW || digitalRead(sens2) == LOW)
return(HIGH);
else
return(LOW);
}
////função procura oponete chamada depois que o robo encontra a linha e da re/////////////////////////////
void procurar()
{
int cnt1 =0;
int a =0;
static int direcao = LOW;
static int aux_sFront_ant = LOW;
static int aux_sFront = LOW;
previousMillis = millis();
currentMillis = millis();
aux_front = ler_analog(sens_front, raio_front); // verifica sensor procura frontal
aux_SLF = ler_digital(SLF_esq , SLF_dir); // verifica sensor frontal de linha ( HIGH para branco LOW para preto)
while(currentMillis - previousMillis <= (tmp_Busc * 1000) && aux_SLF != HIGH && aux_front != HIGH)
{
direita();
delay(30);
currentMillis = millis();
aux_front = ler_analog(sens_front, raio_front); // verifica sensor procura frontal
aux_SLF = ler_digital(SLF_esq , SLF_dir); // verifica sensor frontal de linha ( HIGH para branco LOW para preto)
}
}