21 de outubro de 2018

Teste de Reação

O jogo para testar seu tempo de reação.


O display exibirá seu tempo de reação em milissegundos.

Memorize a cor do LED e mantenha o botão pressionado. O LED piscará aleatoriamente em cores diferentes, e ao visualizar a cor memorizada solte o botão!

Consegue ser rápido?

Utilizei um Arduino Nano, um LED RGB de catodo comum, cinco resistores de 220 ohms, um display de 7 segmentos com 4 dígitos de anodo comum, e um botão tipo push-button.


Deixo abaixo o esquema elétrico do display, do projeto e o código fonte com comentários para entendimento.



/*--------------------------------------------------------
  Programa : TESTE DE REAÇÃO
  Autor    : Fellipe Couto [ http://www.efeitonerd.com.br ]
  Data     : 20/10/2018
  --------------------------------------------------------*/

const int button = 2; //Porta do botão
const int led[3] = {3, 4, 5}; //Portas do Led RGB
int d[4] = {13, 14, 15, 16}; //Portas dos digitos do display
int displayLed[7] = {6, 7, 8, 9, 10, 11, 12}; //Portas dos segmentos do display (A, B, C, D, E, F, G)
int reactionTime = 0; //Tempo de reação
int color = 0; //Cor selecionada
int count = 0;
boolean result = false;

/*--- SETUP ---*/
void setup() {
  for (int i = 0; i < 7; i++) {
    pinMode(displayLed[i], OUTPUT); //Configura as portas dos segmentos do display como saída
    if (i < 4) pinMode(d[i], OUTPUT); //Configura as portas dos digitos do display como saída
    if (i < 3) pinMode(led[i], OUTPUT); //Configura as portas do led rgb como saída
  }
  pinMode(button, INPUT_PULLUP); //Configura a porta do botão como entrada com pull-up interno
  randomSeed(analogRead(5)); //Para o random não repetir a sequencia
  RandomColor(); //Seleciona uma cor para o teste de reação
}

/*--- LOOP PRINCIPAL ---*/
void loop() {
  if (digitalRead(button) == LOW) { //Botão pressionado
    if (reactionTime == 0) {
      BlinkColor(); //Pisca o led em outras cores
    }
    digitalWrite(led[color], HIGH); //Acende o led na cor selecionada
    delay(1);
    reactionTime++;
  } else { //Botão não pressionado
    if (reactionTime > 2 && result == false) {
      LedOff(); //Apaga o led
      result = true;
      for (int k = 0; k <= reactionTime; k++) {
        DisplayNumber(k); //Exibe o tempo de reação no display
      }
    }
    if (result == true) {
      DisplayNumber(reactionTime); //Exibe o tempo de reacao no display
      count++;
      if (count > 3000 || digitalRead(button) == LOW) { //Intervalo de 12 segundos. Delay(1) na funcao displayNumber esta dentro do loop de 4 vezes
        count = 0;
        reactionTime = 0;
        result = false;
        DigitOff(); //Apaga o display
        RandomColor(); //Seleciona nova cor, reiniciando o teste
      }
    } else {
      reactionTime = 0;
    }
  }
}

/*--- APAGA TODAS AS CORES ---*/
void LedOff() {
  digitalWrite(led[0], LOW);
  digitalWrite(led[1], LOW);
  digitalWrite(led[2], LOW);
}

/*--- APAGA TODOS OS DIGITOS DO DISPLAY ---*/
void DigitOff() {
  for (int i = 0; i < 4; i++) { //Apaga todos os digitos
    digitalWrite(d[i], LOW);
  }
}

/*--- SELECIONA NOVA COR E PISCA O LED ---*/
void RandomColor() {
  LedOff();
  color = random(3);
  for (int i = 0; i < 10; i++) {
    digitalWrite(led[color], LOW);
    delay(50);
    digitalWrite(led[color], HIGH);
    delay(50);
  }
}

/*--- PISCA O LED EM OUTRAS CORES ---*/
void BlinkColor() {
  digitalWrite(led[color], LOW); //Apaga o led
  delay(random(1, 6) * 1000); //Delay de 1 a 5 segundos
  int qtd = random(7); //Pode piscar ate 6 vezes em outras cores
  for (int i = 0; i < qtd; i++) {
    int c = random(3);
    while (c == color) {
      c = random(3);
    }
    digitalWrite(led[c], HIGH);
    delay(500);
    digitalWrite(led[c], LOW);
    int t = random(1, 11) * 50;
    for (int r = 0; r < t; r++) { //Delay com verificacao do estado do botão, de 0.5 a 5 segundos
      delay(10);
      if (digitalRead(button) == HIGH) { //Botão foi solto
        RandomColor(); //Seleciona nova cor, reiniciando o teste
        return; //Finaliza a funcao blinkColor()
      }
    }
  }
}

/*--- EXIBE NUMERO NO DISPLAY ---*/
void DisplayNumber(int num) {
  String aux;
  int n[4];
  int number[10][7] = {
    {0, 0, 0, 0, 0, 0, 1}, //ZERO
    {1, 0, 0, 1, 1, 1, 1}, //UM
    {0, 0, 1, 0, 0, 1, 0}, //DOIS
    {0, 0, 0, 0, 1, 1, 0}, //TRES
    {1, 0, 0, 1, 1, 0, 0}, //QUATRO
    {0, 1, 0, 0, 1, 0, 0}, //CINCO
    {1, 1, 0, 0, 0, 0, 0}, //SEIS
    {0, 0, 0, 1, 1, 1, 1}, //SETE
    {0, 0, 0, 0, 0, 0, 0}, //OITO
    {0, 0, 0, 1, 1, 0, 0}  //NOVE
  };
  if (num > 9999) {
    num = 9999; //Mantem o numero em 9999 caso seja maior
  }
  if (num < 10) {
    aux += "000" + String(num);
  }
  else if (num < 100) {
    aux += "00" + String(num);
  }
  else if (num < 1000) {
    aux += "0" + String(num);
  }
  else {
    aux += String(num);
  }
  n[0] = aux.substring(0, 1).toInt();
  n[1] = aux.substring(1, 2).toInt();
  n[2] = aux.substring(2, 3).toInt();
  n[3] = aux.substring(3, 4).toInt();
  for (int p = 0; p < 4; p++) { //Acende um digito por vez.
    for (int i = 0; i < 4; i++) { //Apaga todos os digitos
      digitalWrite(d[i], LOW);
    }
    for (int i = 0; i < 7; i++) { //Acende os segmentos do display referente ao digito
      digitalWrite(displayLed[i], number[n[p]][i]);
    }
    if (p == 0 && n[0] == 0) { //Primeiro digito so acende se for diferente de zero
      digitalWrite(d[p], LOW); //Acende a posição do digito.
    } else {
      digitalWrite(d[p], HIGH); //Acende a posição do digito.
    }
    delay(1);
  }
}

Nenhum comentário:

Postar um comentário