Projetos

Jogo do Reflexo: Divirta-se e Melhore os seus Reflexos

Eletrogate 20 de julho de 202015 min

Introdução

Já pensou em fazer um joguinho com Arduino? Com mais um par de LEDs e botões é possível desenvolver coisas interessantes, dentre elas, um teste de reflexo. Isso mesmo, vamos medir seu reflexo e de mais alguém, e em seguida compará-los. Quem de vocês é o mais rápido?

A proposta deste projeto subir um pouco o nível de dificuldade integrando conceitos de entrada, saída e temporização.

O algoritmo é o seguinte:

  1. Gerar um intervalo randômico de no máximo 7 segundos;
  2. Piscar os LEDs de forma emocionante;
  3. Aguardar os botões serem pressionados e registrar o tempo;
  4. Apagar ambos os LEDs e aguardar 1 segundo (suspense);
  5. Acender estaticamente o LED de quem pressionou mais rápido.

Também será impresso via serial algumas mensagens e valores.


Montagem

Materiais necessários para o projeto Jogo do Reflexo: Divirta-se e Melhore os seus Reflexos

cta_cart

Para ilustrar o circuito, nada melhor do que o Fritzing. Já ouviu falar dele? Você deve ter visto outros circuitos aqui no blog e em outros lugares que também que o utilizam. Se quiser aprender mais a respeito, dá uma olhada neste tutorial.

Faça com calma para evitar problemas:

Ilustração do circuíto

Cuidado!

Não negligencie os resistores, pessoa que está lendo. Eles protegem o chip ATmega328 do seu estimado Arduino contra sobrecarga de corrente, por isso não deixe de utilizá-los! Os resistores ligados aos LEDs são de 220 ohms e os ligados aos botões, 10K ohms.


Código

Agora vamos ao código. Basta copiar, colar na IDE e carregá-lo para o Arduino:

#define LED_ESQ 11 // A porta do LED esquerdo
#define LED_DIR 9 // A porta do LED direito

#define BT_ESQ 7 // A porta do botão esquerdo
#define BT_DIR 5 // A porta do botão esquerdo

#define PWM_MAX 255 // O valor máximo de saídas PWM
#define PWM_MIN 0 // O valor mínimo de saídas PWM

#define TEMPO_MIN 1000 // O intervalo mínimo do tempo de espera
#define TEMPO_MAX 7000 // O intervalo máximo do tempo de espera
#define FLASH 150 // Atraso para piscar os LEDs

void setup() {
  // Configuração dos pinos, definir o que é entrada e saída
  pinMode(LED_ESQ, OUTPUT);
  pinMode(LED_DIR, OUTPUT);
  pinMode(BT_ESQ, INPUT);
  pinMode(BT_DIR, INPUT);
  Serial.begin(9600);
  Serial.println("----------");
  Serial.println("ELETROGATE");
  Serial.println("----------");
  Serial.println("");
  Serial.println("Jogo do reflexo");
  Serial.println("(っ▀¯▀)つ");
  Serial.println("");
  
  delay(1000);

  // Acender os leds
  byte pwAtual = PWM_MAX;
  analogWrite(LED_ESQ, pwAtual);
  analogWrite(LED_DIR, pwAtual);
  
  Serial.println("Começando em 3...");
  delay(1000);
  Serial.println("             2");
  delay(1000);
  Serial.println("             1");
  
  // Apagar os LEDs suavemente em aproximadamente 1 segundo
  while(pwAtual > 0) {
    pwAtual -= 17; // A cada loop, reduzir a potência em 17, assim em 15 ciclos os LEDs se apagarão
    analogWrite(LED_ESQ, pwAtual);
    analogWrite(LED_DIR, pwAtual);
    delay(66);
  }
}

void loop() {
  Serial.println("");
  Serial.print("Aguarde...");
  unsigned int tempoRandomico = random(TEMPO_MIN, TEMPO_MAX); // Gerar o tempo de espera aleatório
  delay(tempoRandomico); // Aguardar o tempo aleatório
  unsigned long millisInicial = millis(); // Salvar o tempo inicial
  unsigned long millisEsq;
  unsigned long millisDir;
  bool btEsqPressionado = false;
  bool btDirPressionado = false;
  bool ledEsqAceso = false;
  bool ledDirAceso = false;
  Serial.print("Pressione seu botão!!!");
  while (!btEsqPressionado || !btDirPressionado) { // Loop para executar enquanto os botões não forem pressionados
    if (digitalRead(BT_ESQ) && !btEsqPressionado) { // Verficar se o botão esquerdo foi pressionado, mas só na primeira vez
      btEsqPressionado = true; // Salvar que o botão foi pressionado
      millisEsq = millis(); // Salvar o tempo em que o botão esquerdo foi pressionado
      analogWrite(LED_ESQ, PWM_MIN); // Apagar o LED esquerdo
    }

    if (digitalRead(BT_DIR) && !btDirPressionado) { // Verficar se o botão direito foi pressionado, mas só na primeira vez
      btDirPressionado = true; // Salvar que o botão foi pressionado
      millisDir = millis(); // Salvar o tempo em que o botão direito foi pressionado
      analogWrite(LED_DIR, PWM_MIN); // Apagar o LED direito
    }

    if (millis() - millisInicial > FLASH) { // Condição para apagar ou acender os LEDs fazendo-os piscarem
      if (!btEsqPressionado) { // O LED esquerdo só pisca se o botão esquerdo ainda não foi pressionado
        if (ledEsqAceso) {
          analogWrite(LED_ESQ, PWM_MIN);
        }
        else {
          analogWrite(LED_ESQ, PWM_MAX);
        }

        ledEsqAceso = !ledEsqAceso; // Apagar se estiver aceso e acender se estiver apagado
      }
      
      if (!btDirPressionado) { // O LED direito só pisca se o botão direito ainda não foi pressionado
        if (ledDirAceso) {
          analogWrite(LED_DIR, PWM_MIN);
        }
        else {
          analogWrite(LED_DIR, PWM_MAX);
        }

        ledDirAceso = !ledDirAceso; // Apagar se estiver aceso e acender se estiver apagado
      }
    }
  }

  Serial.println("Que rufem os tambores!"); // Suspense
  delay(2000);
  Serial.println("");

  if (millisEsq != millisDir) { // Verificar se não houve empate
    Serial.print("O botão ");
    if (millisEsq < millisDir) { // Verfiricar se o botão esquerdo foi pressionado mais rapidamente
      Serial.print("esquerdo");
      analogWrite(LED_ESQ, PWM_MAX); // Acender led esquerdo indicando vencedor
    }
    else {
      Serial.print("direito");
      analogWrite(LED_DIR, PWM_MAX); // Acender led direito indicando vencedor
    }
    
    Serial.println(" foi pressionado mais rapidamente");
  }
  else {
    Serial.println("Houve um empate! Uau, isso é tão raro...");
  }
  
  Serial.println("");
  delay(1000);
  Serial.println("(っ▀¯▀)つ");
  Serial.println("Parabéns!");
  Serial.println("");
  Serial.println("Tempos:");
  Serial.print("Esquerdo = ");
  Serial.print(millisEsq - millisInicial); // Exibir o tempo demorado para o botão esquerdo ser pressionado
  Serial.println(" ms");
  delay(1000);
  
  Serial.print("Direito = ");
  Serial.print(millisDir - millisInicial); // Exibir o tempo demorado para o botão direito ser pressionado
  Serial.println(" ms");
  delay(1000);
  
  Serial.println("");
  Serial.println("Pressione um botão para jogar de novo");
  Serial.println("");
  // Apagar LEDs
  analogWrite(LED_ESQ, PWM_MIN);
  analogWrite(LED_DIR, PWM_MIN);
  while(!digitalRead(BT_ESQ) && !digitalRead(BT_DIR)) { } // Fazer nada enquanto algum botão não é pressionado
}

Reparou na função millis? Ela retorna o tempo em milissegundos desde quando o Arduino é ligado e é super importante para nosso jogo. É uma função nativa, útil para trabalharmos com tempo. Neste tópico em inglês do fórum oficial do Arduino há mais explicações.

Lembre-se de abrir o Monitor Serial para visualizar as mensagens:

Abra o Monitor Serial com Ctrl + Shift + M


Finalizando

É notável o potencial do Arduino como base para criar montagens interativas e para entretenimento. Devemos lembrar que nem todo projeto precisa necessariamente de uma finalidade prática, isto é, a diversão pode estar intrínseca e ser o objetivo final do desenvolvimento. Afinal, é justamente essa a definição de hobby.

E então, já se sente mais confiante? A Eletrogate sugere que você leia e entenda o código linha por linha para que projetos desafiadores se tornem mais confortáveis no futuro. Que tal modificá-lo e deixá-lo do seu jeito? Ou talvez usar um Arduino diferente?

Divirta-se!

Conheça a Metodologia Eletrogate e ofereça aulas de robótica em sua escola!


Sobre o Autor


Victor Castro

Estudante de Sistemas de Informação na UFMG, prefere desenvolver algoritmos do que fazer circuitos. Ama ensinar e surpreender o interlocutor com novas perspectivas. Joga Uno e Rummikub nos fins de semana.


Eletrogate

20 de julho de 2020

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!