fbpx
ArduinoNovidade

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.

Foto que mostra uma competição de robótica, envolvendo seguidores de linha, no evento Anicon, realizado em vitoria da Conquista em 2019.
Figura 1: Competição seguidor de linha.

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).

Vídeo 1: Demonstração do funcionamento do contador de tempo automático para seguidor de linha.

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.

A imagem mostra uma foto tirada de um sensor reflexivo infravermelho.
Figura 2: Sensor reflexivo infravermelho.

O tempo da volta será exibido em um display gráfico LCD 128×64 (Figura 3).

A imagem mostra uma foto tirada de um display gráfico LCD 128X64
Figura 3: Display gráfico LCD 128×64

MATERIAIS NECESSÁRIOS

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.

A imagem ilustra o circuito envolvendo o contador. Nela são ilustradas as ligações do Arduino Nano, o sensor reflexivo e o display gráfico lcd.
Figura 4: Circuito para montagem do 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.

A imagem ilustra a pinagem padrão do sensor reflexivo infravermelho, sendo o fio marrom responsável pela alimentação de 5 Vollts. O fio preto responsável pela saída de sinal e o fio azul responsável pelo aterramento(GND) do circuito.
Figura 5: Terminais do sensor reflexivo infravermelho PNP.

MONTAGEM

Inicie a montagem soldando os bornes e pin heads da placa borne para Arduino Nano, conforme a Figura 6.

A Figura mostra uma foto tirada da placa borne conectada a placa Arduino nano.
Figura 6: Placa borne para Arduino Nano soldada.

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.

A figura mostra uma foto retirada da parte de trás do display LCD e do potenciometro, que será utilizado para ajustar o brilho da tela.
Figura 7: Soldas do display e potenciômetro.

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.

A figura mostra uma foto da parte de trás e frente do contador finalizado.
Figura 8: Circuito montado e componentes fixados.

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.

A imagem mostra o ajuste de configuração para selecionar que será utilizada a placa Arduino Nano no Arduino IDE.
Figura 9: selecionando a placa Nano para o projeto

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).

Vídeo 2: Projeto do contador de tempo automático para seguidor de linha em funcionamento.

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.

Jonas Souza

Graduando em Engenharia Elétrica.