Visión general#

Qué es esto#

esp32idf_APRS es un proyecto ESP-IDF v6.x (probado y fijado en IDF 6.1) que convierte una placa ESP32 DevKit desnuda más una interfaz de audio económica en una estación APRS completa y autónoma. Todo se ejecuta en el propio ESP32 — no hay núcleo Arduino, ni String, ni PlatformIO, ni biblioteca DSP externa. Toda la cadena de señal, desde el demodulador por correlación pasando por la recuperación de bits con DPLL, NRZI, el ensamblador HDLC, el códec AX.25 y la corrección de errores hacia adelante Reed–Solomon FX.25, se ejecuta en el microcontrolador usando únicamente el SAR-ADC en modo continuo/DMA, el DAC y un temporizador de propósito general.

En una frase: el firmware

  • demodula audio AFSK/FSK desde la salida de altavoz o discriminador de una radio en el ADC1,

  • decodifica tramas HDLC/AX.25 (opcionalmente con corrección de errores FX.25),

  • las enruta (gate) hacia APRS-IS por Wi-Fi (qAR/qAO),

  • las repite (digipeat) de vuelta por RF (WIDEn-N, mediante una tabla de alias configurable por el operador),

  • baliza su propia posición, meteorología y telemetría,

  • modula y transmite tramas de vuelta a través del DAC de 8 bits del ESP32, activando la radio mediante un GPIO de PTT,

  • y se configura enteramente a través de una administración web HTTP servida por el propio dispositivo — sin consola serie, sin recompilar para ajustes ordinarios.

Matriz de funciones#

Área

Estado

Notas

AFSK 1200 Bd Bell 202 (APRS estándar)

✅

hasta tres demoduladores en paralelo, perfil por defecto

AFSK 1200 Bd ITU V.23 (1300/2100 Hz)

✅

AFSK 300 Bd (1600/1800 Hz)

✅

estilo HF

G3RUH FSK 9600 Bd

✅

necesita audio plano/de discriminador

Trama UI HDLC / AX.25 RX+TX

✅

AX25_FRAME_MAX_SIZE = 329

FX.25 (FEC RS sobre AX.25)

✅

modos solo-RX / RX+TX

Activación de PTT (GPIO y polaridad en compilación)

✅

GPIO validado; tiempo mínimo de des-activación en ejecución

CSMA / ranura de tiempo TX / p-persistencia / preámbulo TXDelay / cola TXTail

✅

preamble, tx_tail, tx_timeslot, csma_persist, csma_slot_ms, csma_busy_max_s

DCD (detección de portadora de datos)

✅

derivado del demodulador; sin entrada de squelch por hardware

IGate APRS-IS RF→INET

✅

filtros, deduplicación, qAR/qAO

IGate APRS-IS INET→RF

✅

filtro por tipo + budlist + opción de desempaquetado de terceros

Interconexión APRS con BrandMeister (sin enlace DMR)

✅

reconocimiento, filtrado y ruteo de mensajes sobre la sesión APRS-IS existente; página propia, apagada por defecto

Filtro local de rango y prefijo RF→INET

✅

distancia haversine + lista blanca de prefijos de indicativo

Lista blanca / negra de indicativos (budlist)

✅

por dirección, se compone (AND) con los filtros por tipo

Lista de satélites digipetidores (ISS)

✅

hasta 8 entradas, configurable desde la web (página IGate), sin recompilar

Interruptor, tamaño y ventana de la caché de supresión de duplicados

✅

configurable desde la web (página IGate), compartido por IGate y Digipeater

Digipeater

✅

WIDEn-N mediante tabla de alias configurable, supresión de duplicados; los alias heredados RELAY/ECHO/GATE/TRACEn-N no vienen incorporados, pero pueden añadirse como filas de alias ordinarias

Objetos / Ítems APRS propios

✅

hasta 5, RF y/o INET, decaimiento de intervalo + repeticiones de kill

Boletines APRS (BLN1..BLN5)

✅

hasta 5, RF y/o INET, caducidad por boletín

UI de chat de mensajes APRS (/msgchat)

✅

página de bandeja/redacción sobre el motor de mensajería

Respondedor de consultas APRS (APRS101 cap.15)

✅

generales ?APRS?/?WX?/?IGATE?/?QRU? + el conjunto dirigido (?APRSD/?APRSH/?APRSM/?APRSO/?APRSP/?APRSS/ ?APRST/?PING?), con límites de tasa por tipo y por origen

Balizas de posición fija (tracker / igate / digi)

✅

una tarea planificadora de balizas compartida

Receptor GNSS NMEA (UART propia) + página de vista en vivo

✅

interruptor maestro; RMC/GGA/GSA/GSV/VTG, multiconstelación, vista web a 1 Hz

Rastreo GPS en vivo + SmartBeaconing

✅

solo baliza Tracker; intervalo adaptativo por velocidad y corner-pegging

Mensajería APRS + ack/reintento

✅

RF y/o INET

Administración web (autenticación HTTP Basic)

✅

22 páginas de la barra lateral + selector de símbolo, panel en vivo

Registro de tráfico en vivo (panel) + feed de últimos escuchados

✅

tabla de tráfico por long-poll JSON (?since=<seq>); la tabla de últimos escuchados por estación es un feed JSON (/lastheard) y la fuente que leen la compuerta de mensajes y las respuestas ?APRSD/?APRSH

Almacenamiento LittleFS, subir/descargar/borrar/formatear

✅

partición de 512 KB

Sincronización horaria SNTP (3 hosts)

✅

reloj siempre en UTC

Control de frecuencia de CPU (80/160/240 MHz)

✅

esp_pm_configure()

Wi-Fi AP / STA / AP+STA, escaneo, potencia TX

✅

5 ranuras STA (se usa la primera habilitada)

Localización (EN / ES / IT)

✅

en compilación, un idioma por imagen

Actualización OTA

✅

ranuras ota_0/ota_1, reversión automática si falla el arranque

Informe meteorológico APRS propio

✅

refresco de sensores a 1 Hz, promediado opcional, baliza WX al aire

Marco de controladores de sensores locales (sensors_local)

✅

registro dinámico en ejecución, controladores autorregistrados

Codificación/baliza de telemetría APRS al aire

✅

analógicos A1–A5 + digitales B1–B8, informe T#nnn + metadatos

Correo por radio Winlink (APRSLink)

✅

buzón propio INDICATIVO@winlink.org sobre WLNK-1, más una pasarela opcional para la sesión propia de una estación vecina; página propia, deshabilitado por defecto

Puente con bot de Telegram

✅

opcional; long polling sobre HTTPS, autorización por usuario y por chat, reenvío de mensajes de estación y boletines, respuestas /status y /sensors; página y archivo de ajustes propios, deshabilitado por defecto

Visor de registro de consola

✅

copia bajo demanda de la consola serie al navegador (página Registros), sin cable y sin escribir nada en flash

Filosofía de diseño#

Varias decisiones arquitectónicas deliberadas se repiten a lo largo del código y conviene interiorizarlas de antemano:

Una configuración residente, una copia viva.

Una única instancia app_config_t g_config es la fuente de verdad que lee cada subsistema. Persiste en un archivo por funcionalidad de la administración web bajo /storage. Los subsistemas nunca duplican el estado de configuración; leen g_config directamente. Los subsistemas que necesitan un estado propio más grande y específico de página lo guardan en archivos LittleFS separados en lugar de inflar g_config: telemetría (/storage/telemetry.json), boletines (/storage/bulletins.json), objetos/ítems (/storage/objitems.json), el bot de Telegram (/storage/telegram.json, que guarda toda la configuración de esa página) y el buzón Winlink (/storage/winlink.json, las respuestas que el servicio ha devuelto).

Cableado de placa en compilación, todo lo demás en ejecución.

Los tres pines de audio (ADC, DAC, PTT), la polaridad de PTT, la atenuación del ADC y las tasas de muestreo son constantes de compilación definidas en el CMakeLists.txt de nivel superior. Son decisiones de cableado físico, por lo que no se exponen en la administración web. Todo lo que un operador ajusta legítimamente sin recablear — perfil de modulación, preámbulo, ranura de tiempo, modo FX.25, filtros, indicativos, intervalos — es editable en ejecución y, en la mayoría de los casos, se aplica en vivo sin reiniciar.

Estadísticas que reflejan la realidad, no la configuración.

Los contadores del panel (RF RX/TX, RF→INET, INET→RF, digi, descartes, errores) se rastrean en los puntos donde las tramas fluyen realmente, independientemente de si las funciones de IGate o digipeater están habilitadas — de modo que una configuración de monitor solo-RX sigue mostrando actividad de decodificación real en lugar de un muro de ceros.

Fallar de forma ruidosa, fallar de forma segura.

La ruta de arranque de Wi-Fi está muy instrumentada: los códigos de razón de desconexión se registran, un dispositivo solo-STA sin nada a lo que unirse recurre a AP+STA para que la administración web siga accesible, y las reconexiones usan un retroceso creciente armado en un temporizador en lugar de una espera bloqueante dentro del bucle de eventos.

Linaje y créditos#

El proyecto y su componente de módem son de Emiliano Augusto González (LU3VEA). El linaje DSP del módem por software procede de tres proyectos anteriores: VP-Digi (SQ8VPS), ESP32APRS_Audio (nakhonthai) y LibAPRS (Mark Qvist). El esquema de configuración, la disposición de la administración web y la semántica del panel siguen el proyecto de referencia ESP32APRS para que los nombres de clave JSON y las expectativas del operador se mantengan. Véase Créditos y licencia para la atribución y la licencia completas.

El firmware se distribuye bajo la Licencia Pública General GNU v3.0.

Advertencia

Aviso legal de radioafición. Transmitir en frecuencias de radioafición requiere una licencia válida para tu país y banda. Establece un indicativo real — el valor por defecto es NOCALL — usa un passcode legítimo de APRS-IS, respeta el plan de bandas local y las convenciones de digipeating (WIDE1-1,WIDE2-1 no siempre es apropiado), y no enrutes tráfico NOGATE/RFONLY. Eres responsable de todo lo que transmita este dispositivo.