
Chismes del Lince 34: Reflejos de Repálago
Amanecía sobre Sierra Bermeja y, delante de la cueva del Lince, una raya azul iba de un pino a otro sin despeinarse.
—Ciento doce vueltas al claro antes del desayuno —dijo Repálago, sin ni siquiera jadear—. ¿Y tú, Lince? ¿Cuántas?
El Lince de la Noche, que acababa de salir con la taza de café en la mano, parpadeó.
—Yo… estaba pensando en la vida.
—Pensar no cuenta como deporte —contestó ella, y pasó otra vez por delante tan deprisa que el café salió volando—. Si quieres, te doy ventaja. Toda la que quieras.
La Gata Montesa, subida a una roca con su tableta, levantó una ceja.
—Lince, no lo hagas. Es Repálago. Corre como la luz. Literalmente.
—Hoy no me gana —gruñó el Lince, con la dignidad de un lince al que acaban de dejar la camisa llena de café—. Soy más rápido que ella. Lo voy a demostrar.
—Eso es imposible.
—Es difícil. No es lo mismo.
Primero probó a salir corriendo desde la roca. Aterrizó en un matorral de jara. Después probó a esprintar cuesta abajo. Aterrizó en el mismo matorral, ya con cierta confianza. Repálago esperaba en la meta bostezando, a ratos en dos sitios a la vez.
—Vale —dijo por fin la Gata, bajando de la roca—. Deja de correr y piensa. Ganar a Repálago, ya te lo digo yo, no vas a poder. Pero puedes saber cuánto tardas tú en reaccionar. ¿Sabes cuántos milisegundos pasan entre que ves algo y mueves el dedo?
—¿Cuántos? —preguntó el Lince, que no tenía ni idea.
—Ni yo. Por eso hay que medirlo.
—Medirlo… —el Lince se iluminó—. ¡Un chisme!
—Un chisme —suspiró la Gata—. Siempre acaba en un chisme.
El Lince ya había cogido la placa Heltec. Quería una pantalla que dijera «YA» y un botón que midiera su reacción. Ahora tenía un objetivo muy serio: no quedar peor que una luz.
Introducción
En este chisme construimos un juego de reflejos con la placa Heltec y el móvil.
La pantalla de la placa muestra «YA!» en un momento al azar. Tú pulsas un botón en la pantalla del móvil lo más rápido que puedas. La placa mide cuántos milisegundos has tardado.
La página va guardando tus tiempos y calcula tu mejor marca y tu media. Y cada vez que pulsas, Repálago cruza la pantalla corriendo, por si se te olvidaba quién manda.
Esta vez no hay que conectar ningún cable: solo la placa y el móvil. Es el chisme ideal para empezar el día… o para perderlo jugando.
Por qué este chisme
En los chismes anteriores la placa avisaba al móvil (el timbre) o el móvil mandaba órdenes a la placa (la luciérnaga). Aquí pasan las dos cosas y el tiempo importa.
Por eso este chisme nos enseña algo nuevo: medir el tiempo con el reloj de la placa y entender qué está midiendo de verdad.
Además, un juego de reflejos es una excusa perfecta para hacer ciencia. Cada alumno puede preguntarse: ¿soy más rápido por la mañana o por la tarde? ¿Mejoro si practico? ¿Quién gana, mi mano derecha o la izquierda?
Y, sobre todo, te quita una duda: ¿qué significa reaccionar en 250 milisegundos? ¿Es mucho? ¿Es poco?
Cómo funciona el juego de reflejos
—¿Y quién mide el tiempo, el móvil o la placa? —preguntó la Gata.
—El móvil, que tiene pantalla grande —respondió el Lince.
—Entonces el móvil tendría que saber cuándo sale el YA. Y para eso la placa tendría que avisarle por Bluetooth. Y el aviso tardaría un poco. Y tu móvil mediría un tiempo que ya no es el tuyo.
—… Mejor lo mide la placa.
Exacto. El reloj lo lleva la placa. Es la que pinta el YA y la que apunta la hora justo en ese momento. Así el aviso por Bluetooth solo tiene que hacer un viaje: el del toque, del móvil a la placa.
Los tres momentos del juego
La placa siempre está en uno de estos tres estados:
| Estado | Qué pasa | Qué se ve en la placa |
|---|---|---|
| PARADO | No hay ronda en marcha | Mensaje y «Pulsa EMPEZAR» |
| ESPERANDO | Se ha pulsado EMPEZAR; espera un rato al azar (2 a 5 s) | «Preparate» |
| YA | Aparece el «YA!» y corre el reloj | Pantalla blanca con «YA!» |
Los mensajes entre la página y la placa
Las dos se hablan con letras sueltas, como en los chismes anteriores:
| Quién manda | Mensaje | Significa |
|---|---|---|
| Página → placa | G | Empieza una ronda |
| Página → placa | P | Toque: el usuario ha pulsado |
| Placa → página | R:243 | Tu tiempo ha sido 243 ms |
| Placa → página | F | Falsa salida: pulsaste antes del YA |
| Placa → página | N | No pulsaste en 2 segundos |
Una ronda va así: pulsas EMPEZAR, la placa espera un tiempo al azar, aparece el YA, pulsas ¡PULSA! y la placa te devuelve el resultado.
Por qué al azar: si la espera fuera siempre la misma, aprenderías el ritmo y pulsarías antes de ver nada. El azar te obliga a mirar de verdad.
Qué necesitamos
- Una placa Heltec LoRa 32 (o TTGO con pantalla OLED), con su cable USB.
- Un móvil o un ordenador con Chrome o Edge (Web Bluetooth).
- Arduino IDE con las librerías Adafruit SSD1306 y Adafruit GFX.
- Dos archivos para la placa y la página:
chisme-34-reflejos.inoychisme-34-reflejos.html. - La imagen de Repálago,
repalago.png, en la misma carpeta que el HTML (si no, cruzará un hueco vacío).
No hace falta botón, resistencia ni protoboard. El botón es el de la pantalla del móvil.
Construcción
Esta es la parte más corta de toda la serie: no hay que construir nada.
- Conecta la placa al ordenador con el cable USB.
- Abre el Arduino IDE y elige la placa «ESP32 Dev Module».
- Pega el código de la placa (está justo debajo) y súbelo.
- Si dice «Sketch too big», ve a Herramientas → Partition Scheme → «Huge APP (3MB No OTA/1MB SPIFFS)» y vuelve a subirlo.
Cuando termine, la pantalla de la placa dirá «Reflejos de Repalago» y «Listo?».
El código de la placa
Copia todo el código en un sketch nuevo del Arduino IDE. Tiene cuatro partes, pero solo la PARTE 1 es el chisme. La PARTE 2 (la pantalla) esta vez sí es necesaria, porque el «YA!» sale ahí.
/*
Chisme 34 · Reflejos de Repálago
¿Puedes ganarle a Repálago? No. Pero ¿cuál es TU velocidad máxima?
Cómo se juega:
1) En la página del móvil pulsas EMPEZAR.
2) Miras la pantalla de la placa. Tras una espera al azar (de 2 a 5 segundos)
aparece un "YA!" blanco.
3) Pulsas el botón ¡PULSA! del móvil lo más rápido que puedas.
4) La placa mide el tiempo desde que apareció el YA hasta que llegó tu toque
y se lo cuenta a la página, que va guardando tus tiempos.
Este programa tiene 4 partes. Solo la PARTE 1 es el chisme:
PARTE 1 · EL JUEGO <- LEE ESTA. Es lo único importante.
PARTE 2 · LA PANTALLA <- Aquí SÍ se usa: es el "YA!" que tienes que ver.
PARTE 3 · EL BLUETOOTH <- Como en el chisme 31. No hace falta tocarla.
PARTE 4 · setup() y loop()
Esta vez NO hay que conectar nada a la placa: solo la placa y el móvil.
Librerías: Adafruit SSD1306 y Adafruit GFX.
Placa en el Arduino IDE: "ESP32 Dev Module".
Si al compilar dice "Sketch too big":
Herramientas -> Partition Scheme -> "Huge APP (3MB No OTA/1MB SPIFFS)".
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
/* ============================================================
PARTE 1 · EL JUEGO (lo importante)
El juego siempre está en uno de estos tres momentos ("estados"):
PARADO -> no hay ronda en marcha
ESPERANDO -> se ha pulsado EMPEZAR y esperamos un rato al azar
YA -> la pantalla muestra "YA!" y el reloj está corriendo
============================================================ */
enum Estado { PARADO, ESPERANDO, YA };
Estado estado = PARADO; // en qué momento del juego estamos
unsigned long momentoAviso = 0; // cuándo toca enseñar el YA (en milisegundos)
unsigned long momentoYa = 0; // cuándo apareció el YA en la pantalla
volatile unsigned long momentoPulsacion = 0; // cuándo llegó el toque del móvil
volatile bool hayPulsacion = false; // ¿ha llegado un toque?
volatile bool hayEmpezar = false; // ¿ha llegado la orden de empezar?
String mensaje = "Listo?"; // texto grande de la pantalla
String subtitulo = "Pulsa EMPEZAR (movil)"; // texto pequeño de la pantalla
void empezarRonda() {
estado = ESPERANDO;
momentoAviso = millis() + 2000 + esp_random() % 3000; // entre 2 y 5 segundos al azar
mensaje = "Preparate";
subtitulo = "Espera el YA...";
pintarPantalla();
}
void alPulsar(unsigned long t) { // t = el instante en que llegó el toque
if (estado == YA && t >= momentoYa) {
long ms = t - momentoYa; // tiempo de reacción = llegada del toque - aparición del YA
estado = PARADO;
mensaje = String(ms) + " ms";
subtitulo = "Otra? Pulsa EMPEZAR";
avisar("R:" + String(ms)); // R = resultado
} else if (estado == ESPERANDO || estado == YA) {
estado = PARADO; // ¡has pulsado antes de que saliera el YA!
mensaje = "Muy pronto";
subtitulo = "Espera al YA!";
avisar("F"); // F = falsa salida
} else {
return; // si no hay ronda, ignoramos el toque
}
pintarPantalla();
}
void vigilarTiempo() { // se llama sin parar desde loop()
if (estado == ESPERANDO && millis() >= momentoAviso) {
estado = YA;
pintarPantalla(); // pintar el YA tarda unas decenas de milisegundos...
momentoYa = millis(); // ...así que apuntamos la hora cuando YA está pintado
}
if (estado == YA && millis() - momentoYa > 2000) { // 2 segundos sin pulsar: demasiado lento
estado = PARADO;
mensaje = "Muy lento";
subtitulo = "Otra? Pulsa EMPEZAR";
avisar("N"); // N = no ha pulsado
pintarPantalla();
}
}
/* ============================================================
PARTE 2 · LA PANTALLA (aquí sí hace falta: es el estímulo)
============================================================ */
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST 16
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
volatile bool conectado = false; // ¿hay un móvil conectado?
void pintarPantalla() {
display.clearDisplay();
if (estado == YA) { // el "YA!": pantalla entera blanca con letras negras
display.fillScreen(SSD1306_WHITE);
display.setTextColor(SSD1306_BLACK);
display.setTextSize(5);
display.setCursor(18, 14);
display.print("YA!");
} else {
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Reflejos de Repalago");
display.setTextSize(2);
display.setCursor(0, 20);
display.print(mensaje);
display.setTextSize(1);
display.setCursor(0, 42);
display.print(subtitulo);
display.setCursor(0, 56);
display.print(conectado ? "Bluetooth: conectado" : "Bluetooth: esperando");
}
display.display();
}
void arrancarPantalla() {
Wire.begin(OLED_SDA, OLED_SCL);
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW); delay(20); digitalWrite(OLED_RST, HIGH);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
}
/* ============================================================
PARTE 3 · EL BLUETOOTH (como en el chisme 31)
La placa se anuncia como "Heltec-Reflejos". Tiene dos "buzones":
RX: por aquí LLEGAN las órdenes de la página:
"G" = empieza una ronda "P" = toque (pulsado)
TX: por aquí la placa AVISA a la página:
"R:243" = tu tiempo en ms "F" = pulsaste antes de tiempo
"N" = no pulsaste a tiempo
============================================================ */
#define SERVICE_UUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
#define UUID_RX "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
#define UUID_TX "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
BLECharacteristic *tx = nullptr;
class AlConectar : public BLEServerCallbacks {
void onConnect(BLEServer *s) { conectado = true; }
void onDisconnect(BLEServer *s) { conectado = false; BLEDevice::startAdvertising(); }
};
class AlEscribir : public BLECharacteristicCallbacks { // llega algo desde la página
void onWrite(BLECharacteristic *c) {
auto v = c->getValue();
if (v.length() == 0) return;
if (v[0] == 'P') {
momentoPulsacion = millis(); // ¡apuntamos la hora YA, justo cuando llega el toque!
hayPulsacion = true; // (y loop() lo atenderá enseguida)
}
if (v[0] == 'G') hayEmpezar = true;
}
};
void avisar(String texto) { // manda un mensaje corto a la página
if (!conectado || !tx) return;
tx->setValue((uint8_t *)texto.c_str(), texto.length());
tx->notify();
}
void arrancarBluetooth() {
BLEDevice::init("Heltec-Reflejos");
BLEServer *servidor = BLEDevice::createServer();
servidor->setCallbacks(new AlConectar());
BLEService *svc = servidor->createService(SERVICE_UUID);
tx = svc->createCharacteristic(UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
tx->addDescriptor(new BLE2902());
BLECharacteristic *rx = svc->createCharacteristic(UUID_RX,
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
rx->setCallbacks(new AlEscribir());
svc->start();
BLEAdvertising *pub = BLEDevice::getAdvertising();
pub->addServiceUUID(SERVICE_UUID);
pub->setScanResponse(true);
BLEDevice::startAdvertising();
}
/* ============================================================
PARTE 4 · setup() y loop()
setup() se ejecuta UNA vez al encender. loop() se repite sin parar.
============================================================ */
void setup() {
arrancarPantalla();
arrancarBluetooth();
pintarPantalla();
}
bool conectadoAntes = false;
void loop() {
if (hayEmpezar) { // ¿han pulsado EMPEZAR en el móvil?
hayEmpezar = false;
empezarRonda();
}
if (hayPulsacion) { // ¿ha llegado un toque?
hayPulsacion = false;
alPulsar(momentoPulsacion);
}
vigilarTiempo(); // ¿toca enseñar el YA? ¿se acabó el tiempo?
if (conectado != conectadoAntes) { // ¿cambió la conexión?
conectadoAntes = conectado;
pintarPantalla();
}
delay(1);
}
Lee y predice
Antes de probarlo, intenta responder sin mirar la solución:
- En
empezarRonda(), ¿qué pasa si cambias2000 + esp_random() % 3000por1000 + esp_random() % 1000? ¿Cuánto esperará como mínimo y como máximo? - ¿Por qué
momentoYa = millis();va después depintarPantalla();? - Si pulsas mientras la pantalla dice «Preparate», ¿qué mensaje manda la placa a la página?
Soluciones: 1) entre 1 y 2 segundos. 2) Porque pintar el YA tarda unas decenas de milisegundos y tu reloj debe empezar cuando YA ya se ve. 3) La letra F (falsa salida).
La página web del juego de reflejos
Guarda este código como chisme-34-reflejos.html y ábrelo con Chrome o Edge. Pon repalago.png en la misma carpeta.
La PARTE 1 es lo importante: ahí están los botones, los tiempos y Repálago. La PARTE 2 es el Bluetooth y es casi igual que en el chisme 31: no hace falta tocarla.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chisme 34 · Reflejos de Repálago</title>
<style>
/* Los colores, en un solo sitio: cámbialos y cambia toda la página */
:root { --fondo:#eef2ef; --texto:#10201c; --suave:#4d625b; --verde:#1f5b4a; --luz:#ffd23f; }
@media (prefers-color-scheme: dark) {
:root { --fondo:#0f1a17; --texto:#e8f1ed; --suave:#9db3aa; --verde:#5fc4a2; }
}
body { margin:0; padding:1.5rem 1rem; background:var(--fondo); color:var(--texto);
font:18px/1.45 system-ui, sans-serif; text-align:center; }
h1 { font-size:1.5rem; margin:0 0 .3rem; }
p { color:var(--suave); margin:.3rem 0; }
button { font:inherit; font-weight:700; padding:.8rem 1.4rem; margin:.6rem .3rem;
border:2px solid var(--verde); background:var(--verde); color:var(--fondo);
border-radius:.9rem; cursor:pointer; touch-action:manipulation; user-select:none; }
button:disabled { opacity:.45; cursor:not-allowed; }
/* El botón grande de reflejos */
#botonPulsar { width:11rem; height:11rem; border-radius:50%; font-size:1.6rem;
background:var(--luz); border-color:var(--luz); color:#10201c; margin:1.2rem auto; display:block; }
#resultado { font-size:1.6rem; font-weight:700; color:var(--texto); min-height:2.2rem; }
/* Repálago: espera fuera de la pantalla (a la izquierda) y, cuando corre, cruza de lado a lado */
#repalago { position:fixed; bottom:1rem; left:0; height:7rem; pointer-events:none;
transform:translateX(-120%); }
#repalago.corre { animation:pasa .7s ease-in forwards; }
@keyframes pasa { from { transform:translateX(-120%); } to { transform:translateX(100vw); } }
</style>
</head>
<body>
<h1>Reflejos de Repálago</h1>
<p>¿Puedes ganarle a Repálago? No. Pero, ¿cuál es tu máxima velocidad?</p>
<p id="estado">Sin conectar.</p>
<button id="botonConectar">Conectar la placa</button>
<button id="botonEmpezar" disabled>Empezar ronda</button>
<button id="botonPulsar" disabled>¡PULSA!</button>
<p id="resultado">Pulsa «Empezar ronda» y mira la pantalla de la placa.</p>
<p id="comentario"></p>
<p id="estadisticas"></p>
<p id="historial"></p>
<img id="repalago" src="repalago.png" alt="Repálago corriendo">
<script>
/* ============================================================
PARTE 1 · LO IMPORTANTE (léela)
============================================================ */
let tiempos = []; // todos tus tiempos de reacción, en milisegundos
// EMPEZAR: le decimos a la placa que arranque una ronda.
document.getElementById("botonEmpezar").onclick = function () {
document.getElementById("resultado").textContent = "Mira la pantalla de la placa...";
document.getElementById("comentario").textContent = "";
enviarOrden("G"); // "G" = go: empieza una ronda
};
// ¡PULSA!: avisamos a la placa en el instante de tocar.
// Usamos "onpointerdown" (al tocar) y no "onclick" (que espera a que sueltes el dedo): es más rápido.
document.getElementById("botonPulsar").onpointerdown = function () {
enviarOrden("P"); // "P" = pulsado
pasaRepalago(); // ¡y Repálago cruza la pantalla, claro!
};
// Repálago cruza corriendo de izquierda a derecha.
function pasaRepalago() {
const r = document.getElementById("repalago");
r.classList.remove("corre"); // la quitamos...
void r.offsetWidth; // (truco: obliga al navegador a notar el cambio)
r.classList.add("corre"); // ...y la ponemos otra vez: la animación vuelve a empezar
}
// La placa nos AVISA con el resultado. Nosotros solo lo enseñamos y lo apuntamos.
function alRecibirAviso(texto) {
if (texto.startsWith("R:")) { // "R:243" = has tardado 243 ms
const ms = Number(texto.slice(2));
tiempos.push(ms);
mostrarResultado(ms);
}
if (texto === "F") { // "F" = falsa salida
document.getElementById("resultado").textContent = "¡Demasiado pronto!";
document.getElementById("comentario").textContent = "Espera a que salga YA en la placa.";
}
if (texto === "N") { // "N" = no has pulsado a tiempo
document.getElementById("resultado").textContent = "Demasiado lento";
document.getElementById("comentario").textContent = "Tienes 2 segundos desde que sale el YA.";
}
}
function mostrarResultado(ms) {
// La luz da la vuelta a la Tierra (40 075 km) a 299 792 km por segundo.
const vueltas = (ms / 1000 * 299792 / 40075).toFixed(1).replace(".", ",");
document.getElementById("resultado").textContent = ms + " ms";
document.getElementById("comentario").textContent =
"Mientras reaccionabas, Repálago (la luz) dio " + vueltas + " vueltas a la Tierra.";
const mejor = Math.min(...tiempos); // el tiempo más bajo
let suma = 0;
for (const t of tiempos) suma = suma + t;
const media = Math.round(suma / tiempos.length); // la media de todos
document.getElementById("estadisticas").textContent =
"Mejor: " + mejor + " ms · Media: " + media + " ms · Rondas: " + tiempos.length;
document.getElementById("historial").textContent =
"Últimos tiempos: " + tiempos.slice(-10).join(" · ") + " ms";
}
/* ============================================================
PARTE 2 · EL BLUETOOTH (casi igual que en el chisme 31; no hace falta tocarlo)
============================================================ */
const SERVICIO = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
const UUID_RX = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"; // aquí ESCRIBIMOS las órdenes
const UUID_TX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; // por aquí RECIBIMOS los avisos
let dispositivo, canalOrdenes;
const estado = document.getElementById("estado");
const espera = ms => new Promise(r => setTimeout(r, ms));
async function enviarOrden(orden) {
const datos = new TextEncoder().encode(orden);
try {
// "sin respuesta" es más rápido: no esperamos a que la placa confirme que lo ha recibido
if (canalOrdenes.writeValueWithoutResponse) await canalOrdenes.writeValueWithoutResponse(datos);
else await canalOrdenes.writeValue(datos);
} catch (e) { estado.textContent = "No se pudo enviar: " + e.message; }
}
async function abrirCanales() {
for (let intento = 1; intento <= 3; intento++) { // a veces falla la primera vez: reintentamos
try {
const servidor = await dispositivo.gatt.connect();
await espera(600);
const servicio = await servidor.getPrimaryService(SERVICIO);
canalOrdenes = await servicio.getCharacteristic(UUID_RX);
const canalAvisos = await servicio.getCharacteristic(UUID_TX);
canalAvisos.addEventListener("characteristicvaluechanged", e => alRecibirAviso(new TextDecoder().decode(e.target.value)));
await canalAvisos.startNotifications();
estado.textContent = "Conectada a " + dispositivo.name + ".";
document.getElementById("botonEmpezar").disabled = false;
document.getElementById("botonPulsar").disabled = false;
return;
} catch (e) {
if (intento === 3) throw e;
await espera(800);
}
}
}
document.getElementById("botonConectar").onclick = async function () {
if (!navigator.bluetooth) { estado.textContent = "Este navegador no permite Bluetooth. Usa Chrome."; return; }
try {
estado.textContent = "Buscando la placa...";
dispositivo = await navigator.bluetooth.requestDevice({ acceptAllDevices: true, optionalServices: [SERVICIO] });
dispositivo.addEventListener("gattserverdisconnected", () => {
estado.textContent = "Conexión perdida. Pulsa «Conectar la placa».";
document.getElementById("botonEmpezar").disabled = true;
document.getElementById("botonPulsar").disabled = true;
});
await abrirCanales();
} catch (e) {
estado.textContent = "Error: " + e.message + " (elige «Heltec-Reflejos» en la lista).";
}
};
</script>
</body>
</html>
Lee y predice
- En
@keyframes pasa, ¿qué pasa si cambias.7spor.2s? ¿Y por3s? - ¿Por qué el botón usa
onpointerdowny noonclick? - Si haces tres rondas con 250, 300 y 200 ms, ¿qué mejor y qué media saldrán?
Soluciones: 1) Con .2s Repálago cruza casi sin verse; con 3s casi se queda de paseo. 2) onclick espera a que levantes el dedo; onpointerdown reacciona al tocar, unas decenas de milisegundos antes. 3) Mejor: 200 ms. Media: 250 ms.
Cómo probar el juego de reflejos
- Enciende la placa. La pantalla debe decir «Listo?».
- Abre
chisme-34-reflejos.htmlen Chrome o Edge (en el móvil, desde la carpeta donde lo hayas guardado, o subido a tu web con https). - Pulsa «Conectar la placa» y elige Heltec-Reflejos en la lista.
- Cuando ponga «Conectada», pulsa «Empezar ronda».
- Mira la pantalla de la placa, no la del móvil. Cuando salga el «YA!» blanco, pulsa el botón amarillo.
Te saldrá tu tiempo en milisegundos y Repálago cruzará la pantalla. Haz 10 rondas y mira tu mejor marca y tu media.
Si algo no va
- No aparece la placa en la lista: reinicia la placa y vuelve a pulsar «Conectar la placa».
- Los botones siguen apagados: aún no está conectada. Mira el mensaje de estado.
- Siempre sale «Demasiado pronto»: estás pulsando antes de que salga el YA. Espera de verdad.
- Repálago no sale: comprueba que
repalago.pngestá en la misma carpeta que el HTML.
Qué estamos midiendo realmente en el juego de reflejos
La pantalla dice «243 ms». Pero medir no significa medir bien. ¿Qué hay dentro de esos 243 ms?
Tu tiempo de reacción es la suma de varias cosas: la luz del «YA!» llega al ojo, el cerebro decide, el dedo se mueve, la pantalla táctil detecta el toque, el móvil lo manda por Bluetooth y la placa lo recibe.
Solo la primera parte es «tú». El resto es tecnología, y suma retrasos de unas decenas de milisegundos que no sabemos cuánto valen exactamente.
Por eso el resultado es una medida del conjunto, no el tiempo puro de tu cerebro. Si cambias de móvil, el resultado puede cambiar aunque tú reacciones igual.
Una vez no es un dato
Una sola ronda no demuestra nada: puedes tener un buen o un mal momento. Por eso la página calcula el mejor tiempo y la media.
El mejor te dice qué eres capaz de hacer en tu mejor momento. La media te dice qué haces normalmente. Son dos preguntas distintas.
Con más rondas, la media es más fiable. Con pocas, un solo tiempo raro la desvía mucho.
La falsa salida
En atletismo, quien sale antes de oír el disparo es descalificado. Se considera que ningún ser humano puede reaccionar en menos de unos 100 ms, así que quien lo hace está adivinando.
Aquí pasa igual: si pulsas antes del YA, la placa manda una F y no cuenta tu tiempo.
Por qué el YA sale al azar
Si la espera fuera siempre de 3 segundos, aprenderías el ritmo y pulsarías a la vez que el YA. El tiempo saldría ridiculamente bajo y no medirías reacción, sino anticipación.
El azar (entre 2 y 5 segundos) obliga a reaccionar, no a adivinar.
¿Y Repálago?
La luz viaja a 299 792 km por segundo. La Tierra mide unos 40 075 km alrededor, así que en un segundo la luz le da unas 7,5 vueltas.
Si tardas 250 ms, la luz ha dado casi 1,9 vueltas a la Tierra mientras tú reaccionabas. El Lince puede intentarlo, pero la física no está de su parte.
Privacidad
Los tiempos solo viven en la memoria de la página. No se guardan ni se envían a ningún servidor. Si cierras la pestaña, desaparecen.
Para el aula
Este chisme cabe en una sesión de 50 minutos si las placas ya están programadas. Lo importante no es jugar: es diseñar un experimento.
Preguntas para empezar
- ¿Qué variable estamos midiendo? ¿En qué unidad?
- ¿Qué retrasos tiene la medida que no son culpa de tu cerebro?
- ¿Por qué una sola ronda no sirve para sacar conclusiones?
- ¿Qué pasaría si el YA saliera siempre a los 3 segundos?
Cuatro experimentos
- El efecto del azar. Cambia la espera para que sea siempre de 3 segundos. Compara 10 rondas con espera fija y 10 con espera al azar. ¿Qué media sale en cada caso? ¿Por qué?
- Veinte rondas. Cada alumno hace 20 rondas y apunta mejor, media y el tiempo más alto. ¿Quién es más constante? Constante no es lo mismo que rápido.
- Dos móviles. Que la misma persona juegue 10 rondas con un móvil y 10 con otro. Si los resultados difieren, ¿de quién es la culpa: de la persona o del aparato?
- La práctica. Haz 30 rondas seguidas. ¿Mejoras? ¿En qué ronda empiezas a cansarte?

Para pensar
¿Podemos decir que un alumno es «más rápido» que otro porque su media es 20 ms menor? ¿Cuántas rondas necesitaríamos para estar seguros? ¿Es una conclusión o solo una sospecha?
Pista: si tu tiempo varía entre 220 y 320 ms de una ronda a otra, una diferencia de 20 ms entre dos personas no demuestra nada.
Retos
- Haz que funcione el juego de reflejos. Sube el código, conecta y consigue tu primer tiempo.
- Modifica algo. Cambia la espera (por ejemplo, de 1 a 3 segundos) o los colores de la página.
- Cambia el castigo. Ahora mismo, pulsar antes de tiempo no cuenta. Haz que la página lo apunte y muestre cuántas falsas salidas llevas.
- Guarda los datos. Añade un botón que descargue tus tiempos en un archivo CSV para analizarlos en una hoja de cálculo.
- Representa los datos. Dibuja una gráfica con los últimos 20 tiempos y mira si mejoras con la práctica.
- Añade una señal. Que además del YA en la pantalla la placa encienda un LED (como en el chisme 31) y compara si reaccionas igual a la luz que a la pantalla.
- Haz que otro dispositivo participe. Dos placas, dos móviles y un duelo: gana quien pulse antes.
- Conviértelo en investigación. Pregunta a 20 compañeros, con permiso, cuál es su media. Compara por edad, por hora del día o por si han dormido bien. Con cuidado: correlación no es causalidad.
Qué hemos aprendido
Hemos construido un juego de reflejos donde la placa lleva el reloj y el móvil es solo el dedo.
Hemos aprendido que el tiempo se mide donde ocurre el suceso, que una medida incluye retrasos que no son tuyos, y que una sola ronda no es un dato: hacen falta muchas, con su mejor marca y su media.
También hemos visto que el azar no es un adorno: sin él, el juego mide la memoria y no los reflejos.
Y el Lince, ¿qué aprendió?
Hizo veinte rondas. Su mejor tiempo fue de 231 ms. Repálago, mientras tanto, había dado la vuelta a Sierra Bermeja, se había tomado el café y había vuelto a por más.
—Doscientos treinta y uno —dijo el Lince, orgulloso—. No está mal.
—Para un lince, no está mal —admitió la Gata.
—Para la luz, es una eternidad —añadió Repálago, pasando por allí.
El Lince guardó la placa, dejó la taza en la roca y murmuró, para que solo lo oyera él:
—Mañana, mañana la gano.
Para seguir investigando
- Todos los chismes de la serie están en la colección de Chismes del Lince.
- Si quieres otro chisme donde la placa avisa al móvil, mira el semáforo Bluetooth con Heltec (chisme 27).
- Para recordar cómo se conecta la placa por Bluetooth, empieza por El letrero del Lince (chisme 25).
- Si quieres medir algo más que reflejos, prueba el termómetro Bluetooth con Heltec y DHT22 (chisme 26).
- Para ver otras placas y documentación del fabricante, visita la página oficial de Heltec Automation.
Este es un prototipo educativo: sirve para aprender y comparar, no para medir reacciones con precisión científica ni clínica.


