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.



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*--------------------------------------------------------
  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);
  }
}

Um comentário: