Proyecto integrado · Arduino Uno R3

Medidor de reflejos con Arduino Uno

El Uno enciende una lámpara en un momento al azar e imprime cuántos milisegundos tardaste. Todo el proyecto, un Arduino Uno y 5 componentes más, corre aquí en tu navegador con el firmware de abajo; ábrelo en el editor para cambiar las conexiones o el código y ejecutarlo de nuevo.

¿Das clases? Asígnalo a tu grupo con un clic.

Intermedio About 15 minutes to build and run. Funciona en tu navegador. Gratis y sin necesidad de cuenta.

Ármalo como el Starter Kit: los componentes en bolsas numeradas y un instructivo que revisa cada paso. Cuesta unos $34 en tiendas, gratis en Mokxi.

Medidor de reflejos · Arduino Uno R3live0.000 s 0.00x
Mantén presionado el botón
El circuito en sí, corriendo aquí en el simulador. Presiona lo que se pueda presionar; haz clic en cualquier otra cosa para abrirlo en el editor.

What you'll learn

  • A random wait with random
  • Timing with millis
  • Detecting a false start while waiting
  • Active buzzer versus passive piezo
  • A button with INPUT_PULLUP
  • Difficulty: Intermedio
  • Time: About 15 minutes
  • Board: Arduino Uno R3
  • Parts: 7

Cómo funciona

Each round waits a random 1.5 to 4 seconds, then lights the lamp on pin 9 and starts a clock. You press the button on pin 2, conectado a ground with the internal pull-up. The sketch prints how many milliseconds you took and plays a 1 kHz beep on the piezo for 120 ms.

If you press before the lamp, that is a false start. The sketch prints too soon, the active buzzer on pin 8 growls for 400 ms, and the round is thrown away.

The two sound parts need different signals. The active buzzer has its own oscillator, so steady power is enough. The piezo on pin 7 has none, so the sketch toggles the pin itself.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Componente y pinConnects to
LED, green pin CArduino Uno R3 pin GND
Pushbutton pin 2aArduino Uno R3 pin GND
Buzzer pin 2Arduino Uno R3 pin GND
Piezo speaker pin 2Arduino Uno R3 pin GND
Resistor, 220 Ω pin 1Arduino Uno R3 pin 9
Buzzer pin 1Arduino Uno R3 pin 8
Piezo speaker pin 1Arduino Uno R3 pin 7
Pushbutton pin 1aArduino Uno R3 pin 2
LED, green pin AResistor, 220 Ω pin 2

El código

El firmware exactamente como lo abre el editor. Cambia una línea ahí y presiona Ejecutar: se compila en el navegador.

sketch.ino · Arduino Uno R3
// Reaction timer: how fast are you, in milliseconds.
//
//   pin 9  the lamp, through 220 ohm to GND
//   pin 2  the button, to GND, internal pull-up
//   pin 8  an active buzzer straight to GND
//   pin 7  a passive piezo straight to GND
//
// Each round waits a random 1.5 to 4 seconds, lights the lamp, and times the
// button. Press before the lamp and it is a false start: the buzzer (the
// active kind, with its own oscillator, so DC across it is all it needs)
// growls for a moment and the round is thrown away.
//
// The piezo is the other kind. It has no oscillator, so a steady voltage does
// nothing at all; the beep at the end of a good round is this sketch toggling
// pin 7 at 1 kHz for a tenth of a second. Two sound parts, two completely
// different things to send them.
//
// random() here is deterministic (the same sequence every run), which is
// what you want in a simulator. Call randomSeed() with something that varies
// to break that.

const int LAMP = 9;
const int BUTTON = 2;
const int BUZZER = 8;
const int PIEZO = 7;

static bool pressed() { return digitalRead(BUTTON) == LOW; }

// A square wave on the piezo: half a period high, half low, for `ms`.
static void beep(unsigned int hz, unsigned long ms) {
  unsigned int half = (unsigned int)(500000UL / hz);
  unsigned long cycles = (ms * 1000UL) / (2UL * half);
  for (unsigned long i = 0; i < cycles; i++) {
    digitalWrite(PIEZO, HIGH);
    delayMicroseconds(half);
    digitalWrite(PIEZO, LOW);
    delayMicroseconds(half);
  }
}

static void growl() {
  digitalWrite(BUZZER, HIGH);
  delay(400);
  digitalWrite(BUZZER, LOW);
}

void setup() {
  pinMode(LAMP, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(PIEZO, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: reaction timer");
  Serial.println("wait for the lamp, then press the button");
}

void loop() {
  digitalWrite(LAMP, LOW);

  // the wait, watching for a false start
  unsigned long wait = (unsigned long)random(1500, 4000);
  unsigned long started = millis();
  while (millis() - started < wait) {
    if (pressed()) {
      Serial.println("too soon");
      growl();
      while (pressed()) delay(5);
      delay(500);
      return;
    }
    delay(5);
  }

  digitalWrite(LAMP, HIGH);
  unsigned long lit = millis();
  while (!pressed()) delay(1);
  unsigned long took = millis() - lit;
  digitalWrite(LAMP, LOW);

  Serial.print("reaction: ");
  Serial.print(took);
  Serial.println(" ms");
  beep(1000, 120);

  while (pressed()) delay(5);
  delay(700);
}

Code walkthrough

The key functions of the sketch, and what each one does.

pressed sketch.ino

pressed returns true when the button pin reads LOW. Because the button uses the pull-up, LOW means it is held down.

static bool pressed() { return digitalRead(BUTTON) == LOW; }

beep sketch.ino

beep makes a tone by hand. It works out half a period from the frequency, then sets the piezo pin HIGH and LOW with microsecond pauses, for as many cycles as fit in the time.

// A square wave on the piezo: half a period high, half low, for `ms`.
static void beep(unsigned int hz, unsigned long ms) {
  unsigned int half = (unsigned int)(500000UL / hz);
  unsigned long cycles = (ms * 1000UL) / (2UL * half);
  for (unsigned long i = 0; i < cycles; i++) {
    digitalWrite(PIEZO, HIGH);
    delayMicroseconds(half);
    digitalWrite(PIEZO, LOW);
    delayMicroseconds(half);
  }
}

growl sketch.ino

growl turns the active buzzer on pin 8 HIGH for 400 ms and off again. It needs no tone, just power.

static void growl() {
  digitalWrite(BUZZER, HIGH);
  delay(400);
  digitalWrite(BUZZER, LOW);
}

loop sketch.ino

loop waits a random time, returning early on a false start. Otherwise it lights the lamp, waits for a press, prints the time, beeps, and waits for the button to be released.

void loop() {
  digitalWrite(LAMP, LOW);

  // the wait, watching for a false start
  unsigned long wait = (unsigned long)random(1500, 4000);
  unsigned long started = millis();
  while (millis() - started < wait) {
    if (pressed()) {
      Serial.println("too soon");
      growl();
      while (pressed()) delay(5);
      delay(500);
      return;
    }
    delay(5);
  }

  digitalWrite(LAMP, HIGH);
  unsigned long lit = millis();
  while (!pressed()) delay(1);
  unsigned long took = millis() - lit;
  digitalWrite(LAMP, LOW);

  Serial.print("reaction: ");
  Serial.print(took);
  Serial.println(" ms");
  beep(1000, 120);

  // ... 3 more lines in the editor

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The piezo makes no sound. This project
    A piezo needs a changing signal. Check it is on pin 7 and that beep is being called.
  • Every round says too soon. This project
    The button goes from pin 2 to GND. If it is stuck or wired to 5 V, it reads pressed all the time.
  • The waits repeat the same way every run. This project
    random gives the same sequence each time. Add a randomSeed call with something that changes.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The LED does not light, or it lights once and then dies. LED
    LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin.
  • A blue or white LED stays dark on 3.3 V. LED
    Blue and white LEDs drop about 3 V, so 3.3 V leaves almost nothing for the resistor. Use a 5 V supply, or a smaller resistor and a red or green LED.
  • The input reads random HIGH and LOW when the button is not pressed. Botón pulsador
    A floating pin picks up noise. Add a 10 k pull-down or pull-up resistor, or use INPUT_PULLUP and wire the button between the pin and GND. Then pressed reads LOW.

Cámbialo y consérvalo

Ábrelo en el editor, cambia el circuito o el código y guarda tu versión en una cuenta gratis.