
Chisme 43 · El Lince nota lo raro
La tarde caía sobre Sierra Bermeja. El Lince de la Noche había dejado la Heltec sobre una piedra, con el router de la cueva al fondo, y presumía de invento.
—Lo he llamado el Detector de lo Raro. Aprende cómo es la señal wifi cuando no pasa nada y avisa si algo se cruza. No se me escapa ni una mosca.
—¿Ni una mosca? —preguntó la Gata Montesa, sin levantar la vista del móvil.
Hubo un destello. Sobre la piedra, justo al lado de la placa, apareció Repálago, la luciérnaga más rápida de la sierra.
—Eso lo dudo —dijo—. Yo no cruzo el monte: estoy aquí y, al siguiente momento, allí. Mis propiedades desaparecen de un sitio y se reconstruyen en otro, como un teletransporte cuántico. Soy más rápida que tu wifi.
—Apuesto a que mi placa no te detecta —dijo el Lince.
—Dos cosas —intervino la Gata—. Una: eso de ser más rápida que la wifi lo miramos luego, porque tengo mis dudas. Dos: a la placa no le importa lo rápida que seas. Le importa si tapas la señal.
Repálago desapareció y volvió a aparecer, esta vez justo en medio, entre el router y la placa. La pantalla se invirtió y el móvil dijo en voz alta: «Algo se mueve».
—Vale, me ha pillado —admitió Repálago—. Pero no por velocidad, sino por mi sombra.
—Que conste que yo ya lo sabía —dijo el Lince.
—Tanto lo sabías que apostaste —dijo la Gata—. Vamos a construirlo, y de paso a averiguar si Repálago le gana de verdad a la wifi.
Introducción
Vamos a construir un detector de presencia wifi. La Heltec mide la intensidad de la señal de tu router, aprende cuál es su valor normal y avisa cuando algo cambia, por ejemplo una mano o una persona que se cruza.
No hace falta ningún sensor extra: la propia señal wifi hace de sensor. El cuerpo humano es sobre todo agua y absorbe parte de las ondas, así que deja una «sombra» en la señal.
La «IA» de este chisme es muy sencilla y se ejecuta dentro de la placa. Al móvil solo llegan números.
Cómo funciona el detector de presencia wifi
- Mide. La placa escucha a tu router y mide el RSSI, la intensidad de la señal en dBm. Son números negativos: −45 es una señal fuerte y −75 una floja.
- Aprende lo normal. Durante 15 lecturas calcula la media y la desviación, que dice cuánto se separan las lecturas de la media.
- Compara. Si una lectura se aleja de la media más de 3 desviaciones (y nunca menos de 4 dB), avisa.
En una prueba real: sin nadie delante la señal ronda −53 y oscila ±3. Con la mano encima baja a −59, −63 o −64, es decir, de 6 a 11 dB. Por eso un margen de 4 dB separa el ruido de la mano.
Esto se llama detección de anomalías: aprender lo normal y marcar lo que se sale. El modelo son dos números (media y desviación) y no es magia.
Recibe lecturas de RSSI, devuelve «normal» o «aviso» y corre en la placa, así que los datos no salen de ella. Puede equivocarse si cambias el router de sitio, si alguien enciende el microondas (usa los 2,4 GHz) o si pasa algo grande y no una persona.
¿Es Repálago más rápida que la wifi?
Repálago no corre: se teletransporta. En física, el teletransporte cuántico no mueve materia. Lo que viaja es el estado de una partícula (sus propiedades), que se reconstruye en otra partícula lejana. La original se destruye al medirla, por eso Repálago está aquí y, al siguiente momento, allí.
Para hacerlo se usa un par de partículas entrelazadas, que quedan conectadas aunque estén muy lejos.
¿Es instantáneo? La parte cuántica lo parece: un experimento de 2013 concluyó que, si entre dos partículas entrelazadas hubiera que mandar algo, tendría que ir al menos 10 000 veces más rápido que la luz. Pero eso no sirve para enviar información.
Para reconstruir el estado hace falta, además, un mensaje normal con el resultado de la medida. Ese mensaje viaja como mucho a la velocidad de la luz. Sin él, lo que aparece al otro lado es basura aleatoria.
La wifi son ondas de radio, y las ondas de radio viajan a la velocidad de la luz: unos 300 000 km/s. A 5 metros tardan unos 17 nanosegundos (0,000000017 s). El teletransporte de Repálago tiene el mismo mínimo, así que empatan. Para 1 400 km, la distancia del récord de teletransporte entre la Tierra y un satélite (2017), el mínimo sería de unos 4,7 milisegundos.
Conclusión de la Gata: Repálago no le gana a la wifi, empata con la luz. Nada que lleve información va más rápido. Además, los experimentos reales teletransportan el estado de una partícula, no de una luciérnaga: Repálago es ficción.

Qué necesitamos
- Una placa Heltec / TTGO LoRa32 con pantalla OLED, sin sensores ni cables extra.
- Arduino IDE con las librerías Adafruit SSD1306 y Adafruit GFX, y la placa «ESP32 Dev Module».
- Un móvil Android con Chrome (en iPhone no funciona el Bluetooth del navegador).
- Un router que emita en 2,4 GHz, y el nombre exacto de tu wifi.
Importante: el programa usa wifi y Bluetooth a la vez y es grande. Elige en Herramientas → Partition Scheme la opción «Huge APP (3MB No OTA/1MB SPIFFS)», o saldrá «Sketch too big».
El código de la placa
Copia el programa entero. Solo tienes que cambiar una cosa: el nombre de tu wifi en RED, dentro del cuadro «PARTE 1». Las partes 2 y 3 (pantalla y Bluetooth) no hace falta entenderlas para ver cómo aprende la placa.
// Chisme 43 - El Lince nota lo raro
// La Heltec mide la senal Wi-Fi (RSSI) de TU router, aprende lo que es "normal"
// y avisa cuando algo cambia (una mano, una persona que cruza...).
// La "IA" (media y desviacion) corre DENTRO de la placa. Al movil solo van numeros.
//
// Librerias: Adafruit SSD1306 y Adafruit GFX. Placa: "ESP32 Dev Module".
// Si sale "Sketch too big": Tools > Partition Scheme > "Huge APP (3MB No OTA/1MB SPIFFS)".
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// ============================================================================
// PARTE 1 - LO IMPORTANTE (la parte que aprende)
// ============================================================================
const char* RED = "PON_AQUI_EL_NOMBRE_DE_TU_WIFI"; // <-- cambia esto
const int VENTANA = 15; // lecturas para aprender lo normal (unos 25 s)
const float MIN_UMBRAL = 4.0; // margen minimo en dB (el ruido normal es de +-3)
float K = 3.0; // cuantas desviaciones se toleran (la pagina lo cambia)
int muestras[VENTANA];
int nMuestras = 0;
bool aprendido = false;
float media = 0; // lo "normal"
float desviacion = 0; // cuanto varia normalmente
// Calcula la media y la desviacion de las lecturas aprendidas
void aprenderLoNormal() {
float suma = 0;
for (int i = 0; i < VENTANA; i++) suma += muestras[i];
media = suma / VENTANA;
float sc = 0;
for (int i = 0; i < VENTANA; i++) sc += (muestras[i] - media) * (muestras[i] - media);
desviacion = sqrt(sc / VENTANA);
aprendido = true;
}
// Mide el RSSI de nuestra red. Devuelve 0 si no la ve.
// (El nombre de la red solo se compara aqui dentro, nunca se envia.)
int medirRSSI() {
int n = WiFi.scanNetworks(false, false, true, 120); // escaneo pasivo
int rssi = 0;
for (int i = 0; i < n; i++) {
if (WiFi.SSID(i) == RED) rssi = WiFi.RSSI(i);
}
WiFi.scanDelete();
return rssi;
}
// Mensajes que llegan desde la pagina: "L" = aprender otra vez, "K3.5" = margen
bool pedirReaprender = false;
void atenderMensaje(String m) {
m.trim();
if (m.length() == 0) return;
if (m[0] == 'L') pedirReaprender = true;
if (m[0] == 'K') K = constrain(m.substring(1).toFloat(), 1.0, 8.0);
}
// ============================================================================
// PARTE 2 - LA PANTALLA (NO ES NECESARIA para entender la IA)
// ============================================================================
Adafruit_SSD1306 oled(128, 64, &Wire, 16); // SDA 21, SCL 22, RST 16
void pantallaTexto(const char* a, const char* b, const char* c) {
oled.invertDisplay(false);
oled.clearDisplay();
oled.setTextColor(SSD1306_WHITE);
oled.setTextSize(1);
oled.setCursor(0, 0); oled.println(a);
oled.setCursor(0, 16); oled.println(b);
oled.setCursor(0, 32); oled.println(c);
oled.display();
}
void pantallaAprendiendo() {
oled.invertDisplay(false);
oled.clearDisplay();
oled.setTextColor(SSD1306_WHITE);
oled.setTextSize(1);
oled.setCursor(0, 0); oled.println("Aprendiendo lo normal");
oled.setCursor(0, 12); oled.println("No toques la placa");
oled.drawRect(0, 40, 128, 12, SSD1306_WHITE);
oled.fillRect(2, 42, (124 * nMuestras) / VENTANA, 8, SSD1306_WHITE);
oled.display();
}
void pantallaVigilando(int rssi, float umbral, bool alerta) {
oled.invertDisplay(alerta);
oled.clearDisplay();
oled.setTextColor(SSD1306_WHITE);
oled.setTextSize(2);
oled.setCursor(0, 4);
oled.println(alerta ? "ALGO PASA!" : "Normal");
oled.setTextSize(1);
oled.setCursor(0, 32); oled.print("senal "); oled.print(rssi);
oled.print(" dBm");
oled.setCursor(0, 44); oled.print("normal "); oled.print(media, 0);
oled.print(" margen "); oled.print(umbral, 1);
oled.display();
}
// ============================================================================
// PARTE 3 - EL BLUETOOTH (NO ES NECESARIA, igual en todos los chismes)
// ============================================================================
#define SERVICE_UUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
#define RX_UUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e" // la pagina escribe aqui
#define TX_UUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e" // la placa avisa aqui
BLECharacteristic* txChar;
bool conectado = false;
bool reanunciar = false;
class AlConectar : public BLEServerCallbacks {
void onConnect(BLEServer*) { conectado = true; }
void onDisconnect(BLEServer*) { conectado = false; reanunciar = true; }
};
class AlRecibir : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* c) {
auto v = c->getValue(); // 'auto' vale para cualquier version de la placa
atenderMensaje(String(v.c_str()));
}
};
void enviar(const char* linea) {
if (!conectado) return;
txChar->setValue((uint8_t*)linea, strlen(linea));
txChar->notify();
delay(30);
}
void iniciarBluetooth() {
BLEDevice::init("Heltec-Lince");
BLEServer* servidor = BLEDevice::createServer();
servidor->setCallbacks(new AlConectar());
BLEService* servicio = servidor->createService(SERVICE_UUID);
txChar = servicio->createCharacteristic(TX_UUID, BLECharacteristic::PROPERTY_NOTIFY);
txChar->addDescriptor(new BLE2902());
BLECharacteristic* rx = servicio->createCharacteristic(
RX_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR);
rx->setCallbacks(new AlRecibir());
servicio->start();
BLEDevice::getAdvertising()->addServiceUUID(SERVICE_UUID);
BLEDevice::startAdvertising();
}
// ============================================================================
// setup y loop
// ============================================================================
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
iniciarBluetooth();
pantallaTexto("Lince nota lo raro", "Midiendo la senal...", "No toques la placa");
}
void loop() {
if (reanunciar) { delay(300); BLEDevice::startAdvertising(); reanunciar = false; }
if (pedirReaprender) { nMuestras = 0; aprendido = false; pedirReaprender = false; }
int rssi = medirRSSI();
if (rssi == 0) {
pantallaTexto("No veo la red:", RED, "Revisa el nombre");
enviar("N\n");
return;
}
char linea[24];
// 1) Primero aprende lo que es normal
if (!aprendido) {
muestras[nMuestras++] = rssi;
if (nMuestras == VENTANA) aprenderLoNormal();
snprintf(linea, sizeof(linea), "A%d,%d\n", nMuestras, VENTANA);
enviar(linea);
pantallaAprendiendo();
return;
}
// 2) Despues compara cada lectura con lo normal
float umbral = max(K * desviacion, MIN_UMBRAL);
bool alerta = fabs(rssi - media) > umbral;
snprintf(linea, sizeof(linea), "D%d,%.1f,%.1f,%d\n", rssi, media, umbral, alerta ? 1 : 0);
enviar(linea);
pantallaVigilando(rssi, umbral, alerta);
Serial.println(linea);
}
La página web
Guárdala como chisme43-lince-nota-lo-raro.html y ábrela con Chrome en el móvil. No hay que cambiar nada. La parte importante es la PARTE 1, que lee los mensajes de la placa y dibuja la gráfica.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chisme 43 · El Lince nota lo raro</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; background: #f6f8f5; color: #1e2b22; }
.tira { height: 8px; background: linear-gradient(90deg, #2f7d4f, #e0a02f, #d4552f); }
main { max-width: 520px; margin: 0 auto; padding: 14px; }
h1 { font-size: 1.3rem; margin: 6px 0 12px; }
.tarjeta { background: #fff; border-radius: 12px; padding: 12px; margin-bottom: 12px; box-shadow: 0 1px 4px #0002; }
#estado { font-size: 1.6rem; font-weight: 700; text-align: center; padding: 18px 8px; border-radius: 12px; background: #e3e8e4; }
#estado.ok { background: #d5ecdc; color: #17512f; }
#estado.alerta { background: #f6d2c8; color: #8a2a12; }
#detalle { text-align: center; margin: 8px 0 0; font-size: .95rem; }
canvas { width: 100%; height: 190px; display: block; }
button { font-size: 1rem; padding: 10px 14px; margin: 4px 4px 4px 0; border: 0; border-radius: 8px; background: #2f7d4f; color: #fff; }
button:disabled { background: #9aa89f; }
label { display: block; margin: 8px 0; }
.pequeno { font-size: .85rem; color: #4b5a50; }
</style>
</head>
<body>
<div class="tira"></div>
<main>
<h1>El Lince nota lo raro</h1>
<div id="estado">Sin conexión</div>
<p id="detalle">Conecta la Heltec para empezar.</p>
<div class="tarjeta">
<canvas id="grafica"></canvas>
<p class="pequeno">Línea azul: la señal Wi-Fi. Banda verde: lo normal. Puntos rojos: aviso.</p>
</div>
<div class="tarjeta">
<button id="btnConectar">Conectar Heltec</button>
<button id="btnAprender" disabled>Aprender lo normal otra vez</button>
<label>Margen de aviso: <b id="sensVal">3</b> desviaciones
<input type="range" id="sens" min="1.5" max="5" step="0.5" value="3" style="width:100%">
</label>
<label><input type="checkbox" id="voz" checked> Avisar con voz</label>
</div>
<details class="tarjeta">
<summary>Probar sin placa (simulación)</summary>
<p class="pequeno">Genera datos falsos para ver cómo funciona la página.</p>
<button id="btnSim">Simular</button>
</details>
<p class="pequeno">Privacidad: la placa mide la señal y calcula todo ella
sola. A este móvil solo llegan números (intensidad, media y margen). No se envía el nombre de tu Wi-Fi y no se guarda nada.</p>
</main>
<script>
// ============================================================================
// PARTE 1 · LO IMPORTANTE: leer lo que dice la placa y mostrarlo
// ============================================================================
let historial = []; // últimas lecturas: {r: señal, a: 0/1}
const MAX_PUNTOS = 60;
let media = null, umbral = null, alertaAntes = 0;
// La placa manda líneas de texto:
// "A5,15" -> aprendiendo, lectura 5 de 15
// "D-63,-53.1,4.5,1" -> señal, media, margen, aviso (0 o 1)
// "N" -> no ve la red
function procesarLinea(l) {
l = l.trim();
if (!l) return;
const estado = document.getElementById('estado');
const detalle = document.getElementById('detalle');
if (l[0] === 'A') {
const [n, total] = l.slice(1).split(',').map(Number);
estado.className = '';
estado.textContent = 'Aprendiendo lo normal…';
detalle.textContent = 'Lectura ' + n + ' de ' + total + '. No toques la placa.';
historial = []; media = null; umbral = null;
} else if (l[0] === 'D') {
const [r, m, u, a] = l.slice(1).split(',').map(Number);
media = m; umbral = u;
historial.push({ r: r, a: a });
if (historial.length > MAX_PUNTOS) historial.shift();
estado.className = a ? 'alerta' : 'ok';
estado.textContent = a ? '¡Algo pasa!' : 'Todo normal';
detalle.textContent = 'Señal ' + r + ' dBm · normal ' + m.toFixed(1) + ' · margen ±' + u.toFixed(1) + ' dB';
if (a && !alertaAntes && document.getElementById('voz').checked) hablar('Algo se mueve');
alertaAntes = a;
} else if (l[0] === 'N') {
estado.className = '';
estado.textContent = 'No veo tu Wi-Fi';
detalle.textContent = 'Revisa el nombre de la red en el programa de la placa.';
}
dibujar();
}
// Dibuja la gráfica: señal de -90 (abajo) a -30 dBm (arriba)
function dibujar() {
const c = document.getElementById('grafica');
const dpr = window.devicePixelRatio || 1;
c.width = c.clientWidth * dpr; c.height = c.clientHeight * dpr;
const g = c.getContext('2d');
g.scale(dpr, dpr);
const W = c.clientWidth, H = c.clientHeight;
const y = v => H - ((Math.min(-30, Math.max(-90, v)) + 90) / 60) * H;
g.clearRect(0, 0, W, H);
if (media !== null) { // banda de "lo normal"
g.fillStyle = '#2f7d4f33';
g.fillRect(0, y(media + umbral), W, y(media - umbral) - y(media + umbral));
}
const dx = W / (MAX_PUNTOS - 1);
g.strokeStyle = '#2b6cb0'; g.lineWidth = 2; g.beginPath();
historial.forEach((p, i) => { i ? g.lineTo(i * dx, y(p.r)) : g.moveTo(i * dx, y(p.r)); });
g.stroke();
historial.forEach((p, i) => {
if (p.a) { g.fillStyle = '#d4552f'; g.beginPath(); g.arc(i * dx, y(p.r), 4, 0, 7); g.fill(); }
});
}
function hablar(texto) {
try {
const v = new SpeechSynthesisUtterance(texto);
v.lang = 'es-ES';
speechSynthesis.speak(v);
} catch (e) {}
}
// ============================================================================
// PARTE 2 · EL BLUETOOTH (NO ES NECESARIA, igual en todos los chismes)
// ============================================================================
const SERVICIO = '6e400001-b5a3-f393-e0a9-e50e24dcca9e';
const RX = '6e400002-b5a3-f393-e0a9-e50e24dcca9e'; // la página escribe aquí
const TX = '6e400003-b5a3-f393-e0a9-e50e24dcca9e'; // la placa avisa aquí
let rx = null, buffer = '';
function enviar(texto) {
if (rx) rx.writeValue(new TextEncoder().encode(texto + '\n')).catch(() => {});
}
document.getElementById('btnConectar').onclick = async () => {
try {
const dispositivo = await navigator.bluetooth.requestDevice({
filters: [{ namePrefix: 'Heltec-Lince' }],
optionalServices: [SERVICIO]
});
const servidor = await dispositivo.gatt.connect();
const servicio = await servidor.getPrimaryService(SERVICIO);
rx = await servicio.getCharacteristic(RX);
const tx = await servicio.getCharacteristic(TX);
await tx.startNotifications();
tx.addEventListener('characteristicvaluechanged', e => {
buffer += new TextDecoder().decode(e.target.value);
let i;
while ((i = buffer.indexOf('\n')) >= 0) {
procesarLinea(buffer.slice(0, i));
buffer = buffer.slice(i + 1);
}
});
dispositivo.addEventListener('gattserverdisconnected', () => {
rx = null;
document.getElementById('btnAprender').disabled = true;
document.getElementById('estado').className = '';
document.getElementById('estado').textContent = 'Desconectado';
});
document.getElementById('btnAprender').disabled = false;
enviar('K' + document.getElementById('sens').value);
document.getElementById('estado').textContent = 'Conectado';
} catch (e) {
document.getElementById('detalle').textContent =
'No se pudo conectar. Usa Chrome en Android y comprueba que la Heltec está encendida.';
}
};
document.getElementById('btnAprender').onclick = () => enviar('L');
document.getElementById('sens').oninput = e => {
document.getElementById('sensVal').textContent = e.target.value;
enviar('K' + e.target.value);
};
// ============================================================================
// PARTE 3 · SIMULACIÓN SIN PLACA (NO ES NECESARIA)
// ============================================================================
document.getElementById('btnSim').onclick = () => {
let n = 0, t = 0;
const id = setInterval(() => {
if (n < 15) { n++; procesarLinea('A' + n + ',15'); return; }
t++;
const mano = (t % 12) > 8; // cada 12 lecturas, una "mano"
const r = Math.round(-53 + (Math.random() * 4 - 2) - (mano ? 9 : 0));
procesarLinea('D' + r + ',-53.0,4.5,' + (Math.abs(r + 53) > 4.5 ? 1 : 0));
if (t > 60) clearInterval(id);
}, 600);
};
window.addEventListener('resize', dibujar);
dibujar();
</script>
</body>
</html>
Cómo probarlo
- Cambia
REDpor el nombre de tu wifi, elige la partición «Huge APP» y sube el programa a la Heltec. - Abre la página en Chrome (Android), pulsa Conectar Heltec y elige «Heltec-Lince».
- Deja la placa quieta unos 25 segundos mientras aprende lo normal. Verás la barra avanzar en la pantalla.
- Pon la mano encima de la placa o cruza entre ella y el router. Debe salir «¡Algo pasa!».
Lee y predice. Antes de probar, di qué pasará si pones la mano a un metro de la placa en vez de encima, si cruzas muy deprisa o si cambias el router de sitio.
Cambios guiados. Baja el margen del deslizador de 3 a 1,5: verás avisos falsos. Cambia MIN_UMBRAL de 4 a 2, o VENTANA de 15 a 30, y comprueba qué mejora y qué empeora.
Qué estamos midiendo realmente
El dBm es una escala logarítmica: cada 10 dB la potencia se divide por 10. Una caída de 6 a 11 dB al poner la mano significa que llega unas 4 a 12 veces menos potencia.
La placa no mide personas, mide cambios en la señal. No sabe si el cambio lo ha hecho una mano, un microondas o una pared nueva. Un aviso no demuestra que haya alguien: es un dato, no una conclusión.
También importa cada cuánto mide. Cada lectura tarda alrededor de un segundo y medio, y lo que ocurre entre dos lecturas no se ve. Un destello de Repálago que cruce y se vaya antes de la siguiente lectura se colaría sin que la placa se entere.
Además, «lo normal» es solo lo que pasó durante esos 25 segundos de aprendizaje. Si alguien se mueve mientras aprende, la placa aprende mal.
Detectar presencia con wifi es una técnica potente. Úsala solo en tu casa o en el aula, y con el permiso de las personas que están.
Para el aula y retos
Actividad 1: la sombra de la mano. Mide el RSSI con la mano a 10, 30 y 60 cm de la placa y anota los valores en una tabla. ¿Cómo cambia la caída con la distancia? Repite cada medida cinco veces y calcula la media.
Actividad 2: cuánto ruido hay. Deja la placa quieta dos minutos y anota la media y la desviación. Compara con otro grupo o con otra placa: ¿dan lo mismo?
Actividad 3: Repálago contra la wifi. En un ordenador, haz un ping a tu router y mira cuántos milisegundos tarda. Compáralo con los 17 nanosegundos que tarda la luz en 5 metros. ¿Por qué la wifi real es tanto más lenta que su límite físico?
- Reto 1. Haz que funcione y que avise con la mano.
- Reto 2. Cambia
MIN_UMBRALyVENTANAy busca los valores que dan menos falsas alarmas. - Reto 3. Haz que la placa cuente cuántos avisos ha habido.
- Reto 4. Guarda en la página las lecturas y dibújalas en una hoja de cálculo.
- Reto 5. Haz que «lo normal» se actualice despacio con las lecturas sin aviso, para que la placa no se quede anticuada.
- Reto 6. Diseña una pequeña investigación: ¿se nota igual una mano, una persona entera o una mochila con agua?
Qué hemos aprendido
Una placa puede detectar presencia wifi sin ningún sensor extra: mide la señal, aprende lo normal con una media y una desviación, y avisa cuando algo se sale. La IA corre en la placa y ningún dato sale de ella.
Hemos visto que medir no es medir bien: el ruido de ±3 dB y el tiempo entre lecturas limitan lo que podemos afirmar. Y Repálago aprendió que ni el teletransporte cuántico le gana a la luz: empata con la wifi.
Para seguir investigando:
- Vigilante del ruido (Chisme 5): la misma idea de avisar cuando algo supera un umbral, pero con el micrófono.
- Termómetro Bluetooth con Heltec y DHT22 (Chisme 26): otra medida que viaja de la Heltec al móvil.
- El letrero del Lince (Chisme 25): tu primer contacto con la Heltec y el Bluetooth.
- Teletransporte cuántico en Wikipedia (en inglés) y el artículo científico de 2013 sobre la velocidad del entrelazamiento.


