Contador de tempo automático para competições de Robô Seguidor de Linha
Nas competições de robô seguidor de linha, robôs autônomos devem seguir um trajeto determinado por uma linha. O robô vencedor é aquele que completa o trajeto em menor tempo. Desta forma, a contagem de tempo deve ser precisa, pois a diferença de um milissegundo pode definir o campeão.
Neste tutorial, vamos montar um contador de tempo automático para competições de robô seguidor de linha utilizando o Arduino. O contador irá medir o tempo em que o robô gasta para percorrer o percurso (tempo da volta).
Nas competições de robô seguidor de linha, o tempo da volta é medido entre o instante de tempo em que o robô é detectado pelo sensor da linha de partida e o instante de tempo em que o sensor da linha de chegada detecta o mesmo. Desse modo, faz-se necessária a utilização de dois sensores.
O sensor escolhido em nosso projeto foi o reflexivo infravermelho (Figura 2), composto por um transmissor e um receptor infravermelho. O transmissor emite ondas de luz infravermelha que é refletida para o receptor quando interrompidas por qualquer objeto, fazendo assim a detecção do sinal.
O tempo da volta será exibido em um display gráfico LCD 128×64 (Figura 3).
MATERIAIS NECESSÁRIOS
- 2x Sensor reflexivo infravermelho distância ajustável tipo PNP;
- 1x Arduino Nano V3.0 R3 Atmega 328;
- 1x Placa borne para Arduino Nano;
- 1x Cabo USB;
- 1x Potênciometro 10 kΩ;
- 1x Mini Chave gangorra de duas posições;
- 1x Display LCD 128×64 gráfico;
- 1 x Cabo Rabicho com Plug P4 Fêmea;
- Fio cabinho de cobre de 0,3 mm.
IMPRESSÃO 3D
Os arquivos para impressão 3D da case do contador de tempo automático para competição de seguidor de linha pode ser baixado através do seguinte link:
www.blogdarobotica.com/contador-de-tempo-3D
ESQUEMÁTICO DE LIGAÇÃO
A Figura 4 ilustra o esquemático de ligação para o contador de tempo automático.
Ao montar seu circuito preste atenção nos seguintes pontos:
– Os terminais GND, BLK e PSB do display devem ser conectadas à porta GND do Arduino;
– Os terminais VCC e BLA do display devem ser conectadas à porta 5V do Arduino;
– O terminal V0 do display deve estar conectado ao terminal do meio da chave liga/desliga;
– O terminal RS do display deve ser ligado à porta digital D6 do Arduino;
– O terminal R/W do display deve ser conectado à porta digital D7 do Arduino;
– O terminal E do display deve ser ligado à porta digital D8 do Arduino;
– O terminal RST deve estar conectado com a porta digital D9 do Arduino;
– Os terminais GND dos sensores devem ser conectados ao GND do Arduino;
– Conecte os pinos de alimentação dos sensores ao 5V do Arduino;
– Os terminais de saída dos sensores devem ser conectados às portas digitais D2 e D3 do Arduino.
Vale lembrar que os terminais dos sensores reflexivo infravermelho possuem suas cores padronizadas, em que o fio marrom indica a alimentação 5V, o azul é o GND e o preto é o pino de saída de sinal, conforme pode ser observado na Figura 5.
MONTAGEM
Inicie a montagem soldando os bornes e pin heads da placa borne para Arduino Nano, conforme a Figura 6.
Para facilitar a montagem do circuito devemos soldar os fios com os terminais que serão utilizados, assim teremos a garantia que os fios não se soltarão e evitamos possíveis problemas de conexão.
Para isolar os fios soldados e fornecer maior resistência aos pontos de solda usamos tubos termo retráteis, conforme a Figura 7.
Realize a soldagem em todos os componentes, conforme o esquemático de ligação. Em seguida, fixe o botão, o display, o potenciômetro e a placa borne na case impressa em 3D, como na Figura 8.
ELABORANDO O CÓDIGO
Após a verificação do circuito montado, vamos a programação do nosso Sketch. Para melhor compreensão o código será explicado passo a passo a seguir. Neste momento, observe o código abaixo e aproveite para analisar sua estrutura.
/* = CONTADOR DE TEMPO AUTOMÁTICO - SEGUIDOR DE LINHA = ===================================================== ==== BLOG DA ROBOTICA - www.blogdarobotica.com ==== ===================================================== Autor: Kleber Rocha, Luan Santana, Wellington Azevedo E-mail: contato@blogdarobotica.com Facebook: facebook.com/blogdarobotica Instagram:@blogdarobotica YouTube: youtube.com/user/blogdarobotica ===================================================== ==== CASA DA ROBOTICA - www.casadarobotica.com ==== ===================================================== Facebook: facebook.com/casadaroboticaoficial Instagram:@casadarobotica ===================================================== */ #include <U8glib.h> //inclusão da biblioteca gráfica U8glib #include <DS3232RTC.h> //inclusão da biblioteca DS3232RTC, responsável por fazer o controle de tempo. #include <Streaming.h> //inclusão da biblioteca Streaming, responsável por suportar o operador de streaming do Arduino #include <Time.h> //inclusao da biblioteca Time.h, responsável por fazer a manipulalção de unidades de tempo #include <Wire.h> //inclusao da biblioteca wire.h, responsável por gerenciar a comunicação entre o arduino e os protocolos I2C do display U8GLIB_ST7920_128X64_1X u8g(8, 7, 6 , 9); // Define as conexoes do display e deve ser ajustado conforme o modelo(Enable, RW, RS, RESET); int posicao = 0; //variaveis utilizadas para armazernar os valores de posição no display durante seu funcionamento int posicaoh = 0; long int startTime = 0; //Variável que irá armazenará o tempo lido quando o sensor do inciar for detectado long int stopTime = 0; //Variável que irá armazenará o tempo lido quando o sensor do parar for detectado const byte sensorStop = 2; //declara a variavel que irá armazenar os valores do sensor reflexivo conectado ao pino digital 2 do Arduino const byte sensorStart = 3;//declara a variavel que irá armazenar os valores do sensor reflexivo conectado ao pino digital 3 do Arduino boolean jogoComecou = false; //Variavel para armazenar o incio e o fim do funcionamento do cronometro, funcionando como uma trava. int tempoTotal = 0; //Variavel responsável por armazenar o tempo total exibido no cronometro int tempoMinuto = 0;// variavel responsavel por armazenar o tempo de minutos no cronometro int tempoSegundo = 0; // variavel responsavel por armazenar o tempo em segundos no cronometro int tempoMilisegundo = 0; // variavel responsavel por armazenar o tempo em segundos no cronometro void tela_1() { mostra_relogio_digital(); //Chamada da funcão responsável por mostrar o relogio digital } void texto_pequeno() { //Função responsável por fazer com que a formatação do tempo em milissegundos apareça de forma pequena no display u8g.undoScale(); //remove uma escala aplicada u8g.setFont(u8g_font_7x13B); //Define a fonte que será usada no texto u8g.setPrintPos(90, 60); //Atribui a posição para a proxima chamada de texto u8g.print(tempoMilisegundo); //imprime a variavel TempoMilisegundo no display } void mostra_relogio_digital() { texto_pequeno(); //chamada da função texto pequeno que exibe o tempo em milissegundos no display u8g.setColorIndex(1); // Define a cor do texto, sendo 1-para branco e 0 para Azul u8g.setFont(u8g_font_fub17); //Define a fonte que será usada no texto u8g.setScale2x2(); //Dobra o tamnho da fonte u8g.drawStr(27, 21, ":"); //Desenha uma string na posição X/Y especifica, no caso, a sting ":" na posição 27,21 do display. if (tempoMinuto < 10) //Se o tempo de minutos for menor que 10... { u8g.drawStr(0, 23, "0"); //desenha a sting "0" na posição 0,23. No display veremos: 01,02,03.... Até que o valor chegue em 10. posicaoh = 13; //atribui posição 13 na variável posicaoh que é a posição horizontal dos minutos } else posicaoh = 0; //se o tempoMinuto não for menor que 10, atribui posição 0 na variável posicaoh para o alinhamento horizontal dos minutos u8g.setPrintPos(posicaoh, 23);//Atribui a posição para a proxima chamada de texto, sendo x = ao conteúdo de posicaoh e y = 23 u8g.print(tempoMinuto); //imprime no display o conteúdo da variável TempoMinuto na posição x,y definida de acordo com as condições if ou else acima if (tempoSegundo < 10) //Se o tempo de segundos for menor que 10... { u8g.drawStr(38, 23, "0"); //imprime no display a string "0" na posição 38,23. No display veremos: 01,02,03.... Até que o valor chegue em 10. posicao = 51; //atribui 51 na variável posicao referente a posição no eixo x do tempo em segundos } else posicao = 38; ///se o tempo de segundos não for menor que 10 então a variável posicao assume o valor 38 u8g.setPrintPos(posicao , 23); //Atribui a posição para a proxima chamada de texto u8g.print(tempoSegundo); //imprime no display o conteúdo da variável tempoSegundo na posição x,y definida de acordo com as condições if ou else acima u8g.setColorIndex(1); // Define a cor do texto, sendo 1-para branco e 0 para Azul } void setup() { pinMode(sensorStop, INPUT_PULLUP); //Define o pino do sensor reflexivo de parada da contagem como sendo de entrada de sinal e pull up, ou seja, lê-se sinal nível alto (HIGH) quando o sensor não é acionado pinMode(sensorStart, INPUT_PULLUP);//Define o pino do sensor reflexivo de começo da contagem como sendo de entrada de sinal e pull up, ou seja, lê-se sinal nível alto (HIGH) quando o sensor não é acionado attachInterrupt(digitalPinToInterrupt(sensorStop), stopTempo, FALLING ); //Quando o sensor de parada for acionado, será chamada a função stopTempo. Usa-se interrupção porque esses sensores tem prioridade durante a execução do código attachInterrupt(digitalPinToInterrupt(sensorStart), startTempo, FALLING ); //Quando o sensor de começo for acionado, será chamada a função starTempo. Usa-se interrupção porque esses sensores tem prioridade durante a execução do código u8g.setFont(u8g_font_7x13B); //Define a fonte que será usada no texto u8g.drawStr(90, 60, "000"); //Desenha uma string na posição X/Y especifica, no caso, a sting "000" na posição 90,60 do display. } void loop() { contador(); //chamada da função do contador u8g.firstPage(); //Função responsável por chamar o incio de loop dos textos que aparecerão no display do { tela_1(); //chamada da função tela_1 } while ( u8g.nextPage() ); //Função responsável por marcar o final do loop dos textos que aparecerão no display } void startTempo() { if (jogoComecou == false) { //Se jogocomecou tiver valor igual a false... startTime = millis(); //passa a contagem de tempo em milissegundos para a variavel starTime jogoComecou = true; //muda a variavel jogoComecou para True } } void stopTempo() { if (jogoComecou == true) { //Se jogocomecou tiver valor igual a true stopTime = millis(); // //passa a contagem de tempo em milissegundos para a variavel stopTime jogoComecou = false; //muda a variavel jogoComecou para false } } void contador() { if (jogoComecou == true) { //Se jogo comecou tiver valor igual a true (Cronômetro iniciado) tempoTotal = (( millis() - startTime) / 1000); //Calculo para achar o tempo total em segundos tempoMinuto = tempoTotal / 60 ; //Pega o tempo total que é em milissegundos e divide por 60 para encontrar os minutos tempoSegundo = tempoTotal % 60; // Pega o resto da divisão entre o tempoTotal (que está em milissegundos) e 60 para encontrar os segundos tempoMilisegundo = ( millis() - startTime) - (tempoMinuto * 60000) - (tempoSegundo * 1000); //Calculo para achar o tempo de milissegundos } }
Para melhor compreensão do código acompanhe os seguintes passos:
1.Incluir as bibliotecas
Para o correto funcionamento do código, adicionamos 5 bibliotecas, que são: “U8glib.h”,” DS3232RTC.h”,” Streaming.h”, “Time.h” e “Wire.h”.
As bibliotecas “U8glib.h”, “DS3232RTC.h” e “Streaming.h” podem ser adicionadas através do gerenciador de bibliotecas do Arduino IDE. Para saber como instalar bibliotecas, acesse o nosso tutorial clicando aqui.
Por sua vez, as bibliotecas “Time.h” e “Wire.h” são nativas do Arduino IDE, ou seja, não precisa instalar.
2.Declarar as principais variáveis que serão utilizadas
Logo após, declaramos todas as variáveis para uso e armazenamento dos dados lidos durante a execução do programa, sendo:
“startTime” usada para armazenar o tempo lido quando o sensor de início for detectado;
“stopTime” usada para armazenar o tempo lido quando o sensor do parar for detectado;
“tempoTotal” utilizada para armazenar o tempo total em segundos;
“tempoMinuto” utilizada para controle dos minutos no display.
“tempoSegundo” utilizada para controle dos segundos no display.
“tempoMilisegundo” utilizada para controle dos milissegundos no display.
3.Criação das principais funções a serem chamadas no código
Para funcionamento de tarefas especificas no projeto foram criadas 8 funções.
“void tela_1()” tem a função de ativar a exibição do relógio digital e iniciar a tela do display.
“void texto_pequeno()” função responsável por deixar o tamanho da visualização de milisegundos em um tamanho menor comparado com os segundos e minutos.
“void mostra_relogio_digital()” Função responsável por exibir e definir o tamanho dos números referentes aos segundos e minutos. Dentro desta função também é feita a chamada da função texto_pequeno() para exibir os milissegundos no display.
“void setup()” Função responsável por declarar os pinos que serão utilizados.
“void loop()” Função responsável por chamar todos os elementos que repetirão no projeto.
“void startTempo()” Função responsável por iniciar a contagem de tempo no contador.
“void stopTempo()” Função responsável por finalizar a contagem de tempo no contador.
“void contador()” Função responsável por fazer os cálculos de conversão para obtenção dos minutos, segundos e milissegundos que serão mostrados no display.
4.Compilar o código
Com todas as bibliotecas, variáveis e funções definidas basta compilar e mandar o código para o Arduino nano, vale lembrar que para esse projeto é necessário que a ide do Arduino esteja configurada para mandar a informação para a placa nano. Para configurar basta seguir o caminho: ferramentas > placa > arduino nano, conforme mostrado na figura 9.
Projeto em funcionamento:
Com o código compilado iremos dar início ao funcionamento do contador. Para isso, conectaremos a fonte na tomada e passaremos algum objeto na frente do sensor de início (conectado à porta 3) para que a contagem comece e a parada do tempo acontece quando algum objeto passa na frente do segundo sensor (conectado à porta 2).
Espero ter ajudado,
Obrigado a todos e em caso de dúvidas deixe seu comentário abaixo!
Att. Jonas Souza
Graduando em Engenharia Elétrica.