sirensense.es unidad de techo unidad de cabina transpondedor cómo detecta el problema del I2S
SIRENSENSE / notas de construcción rev 3 — última edición abril 2026

Cómo funciona
de verdad esto

lee esto antes de preguntarme cómo detecta las sirenas

Este es el informe técnico de verdad — cada número salió de mis propios esquemáticos, firmware y pruebas de banco. Sin marketing. Si algo parece raro, probablemente es porque primero probé la forma limpia y no funcionó.

1 · la unidad de techo (Nodo 1)

se encarga de escuchar

Cuatro micrófonos, un ESP32-S3, su propia batería. Va en el techo como un GPS gordo. Todo lo acústico pasa aquí arriba — la captura, la IA que decide "¿es esto una sirena?", y la matemática que calcula de qué dirección vino. Luego solo radia la respuesta a la pantalla dentro del coche.

dome render
la cúpula en Blender. los ejes aún visibles
porque olvidé ocultarlos jaja
dome on car
en el techo — misma huella
que una antena de aleta

placa principal

cerebroESP32-S3-WROOM-1-N16R8 — 16MB flash, 8MB PSRAM
placa90×90mm, 1.6mm, ENIG (la dorada)
I2S0 (maestro)BCLK=G6, WS=G5, DIN=G4 — lo comparten Este+Oeste
I2S1 (esclavo)DIN=G14 — Norte+Sur. reloj cableado a mano (ver §5)
pin de calib.GPIO10
tempDS18B20 en el brazo este
frec. muestreo44.1kHz, 32-bit, 4 canales
node 1 KiCad
el PCB del nodo 1 recién salido de KiCad. sí, el logo TB está en la serigrafía.

el truco de los micrófonos

Los 4 micros forman una cruz — dos en la línea Este/Oeste, dos en Norte/Sur. Cada uno va en su propia placa redonda de 14mm (los discos dorados de abajo) conectado con un cable plano fino. Aquí va lo que me enorgullece: en vez de necesitar cuatro buses de audio separados, puse dos micros en un bus asignando uno al canal izquierdo y otro al derecho. Truco de estéreo puro. Hecho en cobre, no en código — el pin de selección del micro izquierdo a masa, el del derecho a alto.

mic pcb back
placa de micro — ese agujero central es
el puerto acústico de Ø1mm
mic pcb front
el otro lado. "lft5" = micro izq #5,
mi propio etiquetado

Los dos micros opuestos están a 190mm. Ese hueco es la razón de que la localización de dirección funcione — el sonido llega a un micro un pelín antes que al otro y mido ese pelín (cómo, en §4).

placa micro14×14mm, 1.0mm, ENIG
agujero acústicoØ1.0mm justo en el centro, Ø4mm de keepout alrededor
impermeabledisco de GoreTex de Ø5mm pegado bajo el agujero — IP67
distancia base190mm entre micros opuestos, ambos ejes
resolución angular2.3° en bruto → 0.29° tras interpolación 8×
la textura geodésica de la cúpula no es decoración — el PETG plano así de fino flexa y el viento silba a 120km/h. los triángulos lo rigidizan.

2 · la unidad de cabina (Nodo 2)

la parte que de verdad miras

Va en el salpicadero. Recibe el ángulo del techo por un enlace 2.4GHz de corto alcance (ESP-NOW), dibuja una flecha en una pantallita, te pita, y también vigila la radio LoRa por si hay ambulancias emitiendo desde hasta 2km. Registra cada evento en una tarjeta SD con GPS + hora, por si algún día necesitas las pruebas.

node 2 KiCad
placa del nodo 2 — ese texto "THIS IS FOR THE RECORD" + "b.m.s" es mío. no juzgues.
cerebroESP32-S3-DevKitC
pantalla2.8" ILI9341 TFT por SPI — flecha + grados + etiqueta
radio largo alcanceSX1278 LoRa 433MHz, AES-128, ~2km
GPSBN-880, 10Hz
almacenamientomicroSD — registra cada detección con posición
sonidoMAX98357A amp → altavocito
alimentación12V del coche (USB u OBD)
LoRa y la tarjeta SD comparten un bus SPI para ahorrar pines. bien mientras no pongas ambos chip-select en bajo a la vez. el firmware nunca lo hace, así que — bien.

3 · el transpondedor

va en la ambulancia

Dispositivo súper simple. Va en un vehículo de emergencia y grita su posición GPS por LoRa, cifrada, sin parar. Cualquier coche con un Copilot a 2km lo oye y avisa al conductor 30–60 segundos antes de que la ambulancia se vea o se oiga. €149, para flotas.

cerebroESP32-S3-WROOM-1-N16R8
radioSX1278 LoRa 433MHz, payload AES-128
GPSBN-880
paqueteID de vehículo + lat/lon + hora UTC + tipo de evento
cuándo emitecada 800–1500ms, aleatorio (ALOHA)
alcance1–2km en ciudad

por qué 433MHz y no las bandas más sofisticadas

La frecuencia más baja rodea mejor los edificios. Las ambulancias trabajan justo en los peores entornos RF — calles estrechas, camiones aparcados, pasos subterráneos. 433MHz a 100mW me da 2km a través de ese lío. Sin SIM, sin servidor, sin cuota mensual. Esa es toda la idea: funciona en el túnel donde tu móvil no.

por qué el temporizado aleatorio

Si diez ambulancias lanzan un paquete en un horario fijo, chocan en el aire siempre y no oyes nada. Variar el intervalo de cada una a un aleatorio 0.8–1.5s baja la probabilidad de colisión a básicamente cero incluso con una flota apiñada en un cruce. Truco viejo (se llama literalmente ALOHA, de los 70), sigue siendo el correcto.

sin handshake, sin ACK. cada paquete va solo con el estado completo del vehículo. si pierdes uno, el siguiente está a ~1s. dispara y olvida.

4 · cómo funciona de verdad la detección de sirenas

la parte buena

Dos etapas. Primero una red neuronal diminuta corre todo el rato, solo preguntando "sirena: sí/no". Solo cuando dice sí arranco la matemática pesada de localización. Mantiene el chip frío y la batería viva mientras solo conduces.

  1. capturar audio — 44.1kHz, los 4 micros Los dos buses I2S vuelcan a memoria sin parar. Divido cada buffer estéreo en 4 flujos mono separados. ~23ms por trozo
  2. convertir 1 segundo de sonido en 40 números (MFE) Energía de banco de filtros Mel — básicamente "cuánta energía en cada banda de tono, ponderada como oye el oído". Las sirenas tienen un aullido muy concreto de 700–1800Hz que enciende esto en un patrón reconocible. ventana de 1s, desliza cada 0.5s
  3. la red neuronal adivina Esos 40 números entran en una pequeña red Conv1D que entrené en Edge Impulse. Cuatro respuestas posibles: sirena / fondo / motor / claxon. Solo importa "sirena"; las otras tres existen para no dar falsa alarma con un taxi pitando. ~50ms, 90% de acierto en mi set de prueba
  4. calcular la dirección (GCC-PHAT) Ahora entra la matemática. Mido cuánto más tarde llegó el sonido al micro lejano frente al cercano, en ambos ejes, y la trigonometría da el ángulo. Detalle abajo. corre ~10× por segundo una vez disparado
  5. suavizar y enviar la flecha El ángulo en bruto baila ±2°, así que promedio las últimas 5 lecturas (con cuidado, para que 359° y 1° no promedien a 180°). Luego ESP-NOW dispara el ángulo final a la unidad del salpicadero. todo, sirena→flecha, en menos de medio segundo

la matemática de dirección, en serio

El sonido desde tu izquierda llega al micro Este antes que al Oeste. El desfase es minúsculo — microsegundos — pero a 44.1kHz lo mido hasta una fracción de muestra. Multiplica ese desfase por la velocidad del sonido y obtienes la diferencia de distancia, que con la separación de 190mm da el ángulo. Hazlo en ambos ejes, mete los dos en atan2, y obtienes los 360° completos.

// este/oeste en el mismo bus, ya están sincronizados tdoa_EW = gcc_phat_lag(east, west, N) / Fs; // norte/sur necesitan quitar el offset medido en arranque (ver §5) tdoa_NS = (gcc_phat_lag(north, south, N) - pipeline_offset) / Fs; c = 331.3 + 0.606 * temp; // velocidad del sonido, corregida por temp. angle = atan2f(tdoa_EW*c, tdoa_NS*c) * 180/PI; if (angle < 0) angle += 360;

Por qué GCC-PHAT y no correlación normal: los ecos. Dentro de un coche, en paredes, en furgonetas aparcadas — la correlación cruzada normal se engaña con los reflejos y apunta la flecha a una pared. PHAT blanquea la señal primero para que el pico real siga nítido y los picos de eco se aplanen. Movimiento estándar para esto, pero hay que saber hacerlo.

la corrección de temperatura importa más de lo que crees — la velocidad del sonido cambia ~12% entre una mañana de invierno y una tarde de verano. ignórala y tu flecha se desvía varios grados en un día caluroso. para eso está el DS18B20.

5 · el problema del I2S que se comió dos semanas

si vas a clonar esto, LEE

Este es el bug que casi mata el proyecto. Los dos buses de audio no arrancan en el mismo instante exacto — se desfasan una muestra o dos. Para el par Este/Oeste no importa (mismo bus). Para Norte/Sur es un error fijo permanente metido en cada ángulo. La flecha está mal, siempre, y no ves por qué.

arreglo parte 1 — cablea el reloj del esclavo A MANO

El segundo bus es esclavo; necesita el reloj del maestro. Poner los pines en "unused" no los conecta solos como sugiere la documentación. Tienes que cablear la matriz GPIO explícitamente o el esclavo se queda ahí produciendo silencio y pierdes un día pensando que el micro está muerto.

// sin estas dos líneas, bus 2 = silencio. pregúntame cómo lo sé. esp_rom_gpio_connect_in_signal(BCLK, i2s_periph_signal[1].s_rx_bck_sig, false); esp_rom_gpio_connect_in_signal(WS, i2s_periph_signal[1].s_rx_ws_sig, false);
esos nombres de campo (s_rx_bck_sig etc) cambian entre versiones de ESP-IDF. revisa tu propio soc/i2s_periph.h antes de flashear o ni siquiera compilará.

arreglo parte 2 — habilita el esclavo primero, el maestro después

El esclavo tiene que estar en su estado de espera antes de que llegue el primer flanco de reloj, o se pierde el arranque y el offset se hace mayor y aleatorio. Haz los dos enables dentro de una sección crítica para que nada interrumpa entre ellos.

taskENTER_CRITICAL(&i2s_mux); i2s_channel_enable(rx1); // esclavo primero, espera el reloj i2s_channel_enable(rx0); // maestro después, su primer tick despierta al esclavo taskEXIT_CRITICAL(&i2s_mux);

arreglo parte 3 — mide el offset restante en cada arranque

Aun con todo eso, quedan 0, 1 o 2 muestras de holgura, y puede ser distinta en cada encendido. Así que en cada arranque meto un pulso de 100µs en ambos buses a la vez por GPIO10, correlaciono las dos grabaciones, y eso me dice el offset exacto. Lo guardo, lo resto de cada lectura Norte/Sur para siempre. Nunca lo hardcodees — cambia entre arranques.

// pulso ambas entradas, releo, correlaciono pipeline_offset = gcc_phat_lag(s0, s1, 512); // debería volver 0, 1 o 2 — y el MISMO número 10 arranques seguidos. // si salta, tu orden de enable está mal. vuelve a la parte 2.
dos semanas en esto. el arreglo final son ~6 líneas. así es lo embebido, amigo.

resumen rápido — la cadena de radio

unidad de techo ──ESP-NOW 2.4GHz, ~1ms──▶ unidad salpicadero ◀──LoRa 433MHz, ~2km── transpondedor ambulancia

Tres saltos, tres radios, cada una elegida para su tarea: ESP-NOW porque es instantánea y no necesita router; LoRa porque llega a 2km por una ciudad sin infraestructura; y todo funciona sin nada de internet porque el túnel es justo donde más lo necesitas.