RTL-SDR Blog V4
Receptor SDR encargado de entregar las muestras complejas I/Q del espectro alrededor de 144.390 MHz.
- Recepción únicamente
- Antena VHF de 2 metros
- Futuras pruebas con filtros y LNA
Receptor APRS experimental con SDR de bajo costo, procesamiento completo en GNU Radio, captura reproducible de muestras I/Q y análisis histórico del nivel de señal.
Hitos, ensayos y decisiones técnicas en orden cronológico. Seleccioná una entrada para abrir o cerrar su contenido.
La meta no es solamente decodificar paquetes: queremos conservar acceso a la señal desde RF y comprender, medir y modificar cada etapa hasta extraer el contenido APRS.
El acceso a las primeras etapas permitirá comparar filtros, anchos de banda, ganancias, algoritmos de demodulación y decodificadores propios.
Un laboratorio deliberadamente simple y reproducible, construido con hardware disponible y herramientas abiertas.
Receptor SDR encargado de entregar las muestras complejas I/Q del espectro alrededor de 144.390 MHz.
Plataforma de DSP, visualización, decodificación y extracción progresiva de métricas.
Primera comprobación visual y auditiva de actividad APRS mediante waterfall y demodulación NFM.
GNU Radio irá incorporando todo el camino de señal junto con puntos de observación para inspeccionar cada transformación.
RTL-SDR SOURCE
↓
CHANNEL FILTER / FREQUENCY TRANSLATION ───→ FFT + WATERFALL
↓
NFM DEMODULATOR ─────────────────────────→ NIVEL / RSSI / SNR
↓
AUDIO FILTER ─────────────────────────────→ AUDIO + FORMA DE ONDA
↓
AFSK 1200 DECODER
↓
BIT RECOVERY → AX.25 → APRS → REGISTROLas transmisiones reales son irrepetibles. Guardar muestras I/Q permite convertirlas en casos de prueba idénticos para todas las versiones del receptor.
Fragmentos reales del espectro, incluyendo paquetes APRS, ruido, interferencias y condiciones concretas de propagación.
El mismo archivo alimenta sucesivas versiones del flowgraph para comparar cambios sin que varíe la señal de entrada.
Cada trama se asociará con las métricas disponibles al momento de la recepción para formar un historial por estación.
Las estaciones conocidas y relativamente fijas servirán como referencias del mundo real. Las conclusiones se obtendrán estadísticamente, acumulando muestras y considerando propagación, potencia, antenas y demás variables.
Cada bloque se validará de forma independiente antes de cerrar la cadena completa.
Confirmar actividad APRS real en 144.390 MHz.
Construir el primer conjunto de transmisiones de referencia.
Recuperar correctamente el audio AFSK desde GNU Radio.
Observar tonos en frecuencia y dominio temporal.
Recuperar tramas digitales sin errores.
Extraer callsign, posición, ruta, comentarios y telemetría.
Asociar paquetes y métricas de recepción.
El sistema terminado deberá producir evidencia para responder preguntas concretas sobre recepción y rendimiento.
¿Qué estaciones APRS recibimos y desde qué distancia?
¿Con qué nivel y frecuencia llegan?
¿Cuál es el nivel mínimo que conseguimos decodificar?
¿Qué configuración de filtrado obtiene mejores resultados?
¿Una nueva versión funciona realmente mejor?
¿Qué paquetes recibe una versión y pierde otra?
Secuencia inicial desde la instalación hasta el análisis histórico por estación.
A largo plazo, APRS será el primer caso de estudio de un laboratorio más amplio de RF y DSP: bloques propios, otras modulaciones y eventualmente hardware SDR desarrollado en casa.
Se calibró el detector de RSSI implementado en GNU Radio para el receptor SDR del sistema APRS en 144,390 MHz.
Se utilizaron cables cortos y conexiones razonablemente confiables. Un adaptador BNC tipo “T” introducía una atenuación significativa y fue descartado. Desde entonces, la referencia se verificó con el osciloscopio y el generador se conectó directamente al SDR.
El generador se configuró con carga de 50 Ω sobre 144,390 MHz.
Se ensayaron distintas amplitudes y ganancias, observándose buena correspondencia entre las variaciones esperadas en dB y las lecturas.
También se verificó aproximadamente 1 mVpp, equivalente a unos −56 dBm, obteniéndose nuevamente una lectura consistente.
La salida puede interpretarse como una estimación de RSSI en dBm siempre que no cambien la ganancia del SDR ni los bloques de medición.
Con el generador desconectado se observaron aproximadamente −102 dBm. Este valor del banco se comparará luego con el piso real del sitio de operación.
Alcance: no es una calibración metrológica trazable. Su consistencia es suficiente para asociar a cada trama APRS una estimación reproducible de RSSI y usarla en estadísticas, comparación entre estaciones y evaluación del receptor.
Se construyó y ajustó un filtro pasabanda de tres etapas buscando una respuesta lo más estrecha posible y centrada en la frecuencia APRS de 144,390 MHz.


La implementación física sigue el esquema de tres resonadores acoplados y fue realizada como prototipo ajustable de laboratorio.

El prototipo se realizó con los componentes disponibles en el laboratorio. Los capacitores utilizados no son de la mejor calidad para esta aplicación, pero permitieron obtener una primera implementación funcional y ajustable.
Las tres etapas resonantes se calibraron individualmente y luego como conjunto para desplazar y conformar la banda de paso alrededor de la frecuencia objetivo.
La respuesta se verificó con el analizador de espectro trabajando con su tracking generator. Después de un ajuste fino se obtuvo una pérdida aproximada de 5 dB en el área de operación, con curvas razonablemente limpias para este prototipo.
El resultado es alentador considerando la disponibilidad y calidad de los componentes empleados.
El principal inconveniente es la sensibilidad mecánica del conjunto: golpes, movimientos o pequeñas deformaciones modifican la sintonía y el filtro se descalibra rápidamente. En su estado actual funciona como prueba de concepto de laboratorio, pero todavía no es adecuado para una instalación permanente.
Resolver este punto es importante porque la entrada del SDR puede saturarse ante señales intensas fuera de banda y dejar al receptor prácticamente “sordo”. La etapa definitiva deberá combinar una banda suficientemente estrecha, alto Q, pérdida de inserción aceptable y una construcción rígida que mantenga la calibración.
Próxima iteración: mejorar la calidad de los capacitores, rigidizar inductores y conexiones, estudiar un blindaje/caja estable y repetir la caracterización después de someter el conjunto a movimientos y pequeños impactos controlados.
Se implementó dentro del flowgraph de GNU Radio un mecanismo para medir y registrar el nivel de señal durante cada evento de RF. El resultado es una serie temporal calibrada en dBm, preparada para correlacionarse posteriormente con las tramas APRS decodificadas.
La recepción se realiza con un RTL-SDR Blog V4 a 2,4 Msps. Un Frequency Xlating FIR Filter selecciona el canal APRS de 144,390 MHz y entrega una señal compleja a 48 kS/s.
La potencia instantánea se obtiene como I² + Q². Sobre ella se aplica un promedio móvil de 480 muestras, equivalente a una ventana de 10 ms a 48 kS/s.
La conversión final utiliza:
RSSI[dBm] = 10·log10(P) + rssi_cal rssi_cal ≈ −48,77 dB
El valor de calibración debe mantenerse fijo mientras no cambien la ganancia ni los parámetros que afectan la cadena de recepción.
Esta resolución permite obtener decenas de mediciones durante una transmisión APRS AFSK de 1200 baud y observar no sólo su máximo, sino la evolución del nivel durante toda la trama.
La escritura se habilita únicamente mientras el detector de portadora indica presencia de señal. Este detector sólo decide cuándo registrar RSSI: no interviene en la demodulación ni condiciona la recepción de Dire Wolf.
Así, los criterios de detección pueden ajustarse sin alterar la cadena principal de decodificación APRS.
Se creó un Embedded Python Block propio que recibe:
Una salida pasante conectada a un Null Sink garantiza que el scheduler de GNU Radio lo ejecute normalmente.
Mientras existe portadora, el bloque escribe una muestra cada 10 ms en /home/jack/sdr/logs/rssi.log, usando UTC y resolución de milisegundos.
UTC_TIMESTAMP,RSSI 2026-08-29T17:50:39.856Z,-73.35 2026-08-29T17:50:39.866Z,-73.42 2026-08-29T17:50:39.876Z,-73.28
Durante las pruebas, consultar el reloj del sistema en cada ejecución de work() produjo marcas repetidas o retrocesos temporales por la forma en que GNU Radio entrega los buffers. La solución utiliza un único anclaje UTC al inicio y un contador de muestras:
timestamp(n) = t0 + n × 10 ms
La serie resultante es estable, creciente e independiente del tamaño de los buffers. En pruebas prolongadas no se observó un drift que justifique resincronizaciones periódicas.
Las muestras se asociarán automáticamente a cada trama AX.25 o FX.25 decodificada. El registro final incluirá timestamp, origen, transmisor RF, modo, cantidad de bits, nivel de audio informado por Dire Wolf, RSSI en dBm y trama APRS completa.
La duración estimada será:
duración = bits / 1200
Por ejemplo, 1344 bits representan aproximadamente 1,120 segundos.
Para reducir transitorios del transmisor, retardos de filtros y diferencias temporales, se tomará el 60 % central de cada trama:
Origen y transmisor: en una ruta como LW5DIX-10>APDW14,LU3DRE-1*,WIDE2-1:..., el mensaje fue originado por LW5DIX-10, pero la señal recibida físicamente corresponde a LU3DRE-1. Para estudios de señal y cobertura, el RSSI se asociará siempre al transmisor RF escuchado.
La combinación de transmisor + RSSI + timestamp + modo + trama será la base para comparar sensibilidad y cobertura, y para medir objetivamente el efecto de cambios en ganancia, filtros y procesamiento del receptor sobre estaciones reales.
Se modificó Dire Wolf para emitir, de forma estructurada y con precisión temporal suficiente, toda la información necesaria para asociar en una etapa posterior cada trama APRS decodificada con las muestras de RSSI generadas por GNU Radio.
En esta instancia todavía no se calcula el RSSI de cada trama: el objetivo fue preparar una interfaz estable para el futuro correlacionador externo.
Se modificó src/dtime_now.c para incorporar el formato especial ISO8601MS. Dire Wolf puede ejecutarse con -T ISO8601MS y producir marcas como:
2026-09-03T03:05:18.868Z
La letra Z indica UTC. El formato coincide con el utilizado por el logger de GNU Radio, de modo que ambos sistemas comparten la misma referencia temporal.
Para AX.25 se obtiene la longitud real del bloque HDLC mediante:
rx_bits = rrbb_get_len(block) - 1
El dato incluye información, FCS y bit stuffing, pero excluye las flags. Para FX.25 se calcula:
rx_bits = 64 + 8 × (data_bytes + Reed-Solomon_bytes)
Así pueden aparecer longitudes AX.25 no múltiplos de ocho y bloques FX.25 de, por ejemplo, 1344 bits.
rx_bitsEl valor viaja desde los decodificadores HDLC y FX.25 hasta el punto en que Dire Wolf ya dispone de una trama válida. También se identifica el modo de recepción como AX25, FX25 o IL2P.
@RXFRAMESe agregó una línea destinada exclusivamente a procesos externos. El prefijo permite ignorar el resto de la salida humana de Dire Wolf y procesar únicamente las tramas válidas.
@RXFRAME {"ts":"2026-09-03T03:05:18.868Z",
"bits":649,"mode":"AX25",
"origin":"LW5DIX-10",
"transmitter":"LU3DRE-1",
"audio":{"rec":60,"mark":16,"space":16},
"frame":"LW5DIX-10>APDW14,LU3DRE-1*,WIDE2-1:..."}En operación real, cada objeto JSON se emite completo en una sola línea. La trama TNC2 pasa por una rutina de escape que protege comillas, barras y caracteres de control, permitiendo utilizar un parser JSON convencional.
El evento incluye los valores internos que Dire Wolf presenta tradicionalmente como audio level = 60(16/16):
"audio":{"rec":60,"mark":16,"space":16}No representan dBm, pero permitirán comparar el nivel de audio demodulado con el RSSI calibrado de GNU Radio y estudiar su relación con la capacidad de decodificación.
Dire Wolf utiliza su lógica interna ax25_get_heard() y ax25_get_addr_with_ssid() para informar ambos campos. En:
LW5DIX-10>APDW14,LU3DRE-1*,WIDE2-1:...
LW5DIX-10 es el origen del mensaje y LU3DRE-1 es quien transmitió la RF recibida. El RSSI deberá asociarse siempre al campo transmitter.
stdout como interfaz desacopladaEl correlacionador se conectará mediante un pipe: direwolf ... | rssi-correlator.py. Dire Wolf sólo emite el evento y continúa con la recepción, evitando llamadas bloqueantes como system(), fork() o exec() por cada trama.
El proceso externo permanecerá activo, conservará visible la salida normal y actuará únicamente sobre las líneas que comiencen con @RXFRAME.
Se comprobó en operación real la emisión de eventos estructurados tanto para AX.25 como para FX.25, incluyendo timestamp, bits, modo, origen, transmisor, nivel de audio y trama completa.
Dire Wolf ya entrega todos los datos requeridos por la siguiente etapa.
Se desarrollará rssi-correlator.py, que leerá los eventos desde la entrada estándar y buscará en rssi.log las muestras correspondientes a la ventana temporal de cada transmisión.
La duración aproximada se obtendrá mediante bits / 1200 para APRS AFSK 1200.
Registro final previsto: timestamp, origen, transmisor RF, modo, cantidad real de bits, nivel de audio de Dire Wolf, RSSI en dBm y trama APRS completa.
Esta integración formará la base para analizar cobertura, sensibilidad y rendimiento, además de comparar objetivamente el efecto de distintos filtros, niveles de ganancia y configuraciones de procesamiento.
Con GNU Radio generando una serie temporal en rssi.log y Dire Wolf emitiendo eventos estructurados @RXFRAME, se implementó un proceso externo que correlaciona ambas fuentes y obtiene un nivel de señal calibrado para cada trama APRS válida.
El proceso permanece conectado mediante direwolf ... | /home/jack/sdr/rssi-correlator.py. Reenvía a pantalla toda la salida normal de Dire Wolf y sólo activa la correlación cuando una línea comienza con @RXFRAME.
El JSON entrega directamente timestamp, cantidad real de bits, modo, origen, transmisor RF, nivel de audio y trama completa. La interpretación AX.25 permanece en Dire Wolf; el correlacionador no necesita analizar manualmente el path APRS.
ts · bits · mode · origin transmitter · audio · frame
El RSSI se asocia a transmitter, es decir, a la estación que físicamente emitió la RF escuchada.
Al recibir una trama válida, el correlacionador renombra en el mismo filesystem:
rssi.log → rssi.working
Como el bloque de GNU Radio abre el archivo por nombre en cada escritura, la siguiente muestra crea automáticamente un nuevo rssi.log. Así, GNU Radio continúa registrando mientras el correlacionador trabaja sobre una captura estable y no bloquea el flowgraph.
Para APRS AFSK 1200, la duración se obtiene a partir de la cantidad real de bits informada por Dire Wolf:
Tframe = bits / 1200 Tinicio = Tfin − Tframe Ejemplo: 649 / 1200 = 0,540833 s Tfin = 03:05:18.868 Tinicio ≈ 03:05:18.327
Se descarta el 20 % inicial y el 20 % final para evitar el ataque y caída del transmisor, transitorios de filtros, retardos del demodulador, colas de Dire Wolf y detección tardía de portadora.
margen = Tframe × 0,20 Trssi_inicio = Tinicio + margen Trssi_fin = Tfin − margen
El correlacionador selecciona las muestras de 10 ms comprendidas entre los límites de la ventana y calcula:
avg_dbm)Para una trama FX.25 de 1344 bits, el 60 % central dura 0,672 s: se esperan unas 67 muestras y en una recepción real se obtuvieron 68.
Una trama originada y transmitida directamente por LW3DHN-10 en modo FX.25, con 1344 bits, midió −78,78 dBm sobre 68 muestras. Pocos segundos después, la misma información repetida por LU7ERZ-3 en AX.25, con 761 bits, midió −64,66 dBm sobre 38 muestras.
La prueba confirmó que dos copias del mismo mensaje pueden tener RSSI muy diferentes porque proceden de transmisores físicos distintos y que la métrica debe vincularse al transmisor realmente escuchado.
Dos transmisiones consecutivas del mismo transmisor produjeron resultados prácticamente idénticos pese a tener longitudes diferentes.
649 bits · 32 muestras · −64,36 dBm 705 bits · 35 muestras · −64,33 dBm Diferencia: 0,03 dB
La repetibilidad observada valida el enfoque como herramienta comparativa: las ventanas temporales y cantidades de muestras cambiaron, pero el nivel calculado permaneció estable.
Cada correlación correcta produce una línea de lectura inmediata:
@RSSI 2026-09-03T02:37:37.647Z origin=LW3DHN-10 tx=LW3DHN-10 FX25 1344 bits −78.78 dBm (68 samples)
Cada resultado también se guarda como un objeto JSON por línea en:
/home/jack/sdr/logs/rx_frames.jsonl
El registro conserva los datos de la trama, audio de Dire Wolf y un bloque RSSI con duración, margen, muestras, estado, promedio, mediana, mínimo y máximo.
Datos reutilizables: el formato JSON Lines puede importarse directamente desde Python, PHP, MariaDB, SQLite, Pandas, Grafana y herramientas estadísticas, sin volver a procesar los archivos originales.
Cada recepción válida queda expresada como transmisor + RSSI calibrado + audio de Dire Wolf + modo + timestamp + trama. Esto permite reemplazar apreciaciones subjetivas por comparaciones estadísticas antes y después de modificar ganancia, filtros RF, ancho de banda, transición, promedio móvil, demodulación o filtrado de audio.
Se publicó la primera interfaz web del sistema para visualizar las estaciones APRS recibidas por LW2ERA junto con el nivel de señal RSSI registrado y correlacionado con cada recepción.
Esta integración materializa el objetivo central del proyecto: registrar el RSSI y correlacionarlo con la trama AX.25 recibida. Cada recepción deja de ser únicamente un paquete decodificado y pasa a constituir una observación técnica formada por transmisor RF, timestamp, trama APRS y nivel de señal calibrado.
Se creó una nueva vista pública accesible en lw2era.ar/aprs, titulada “Estaciones Escuchadas por LW2ERA”. Presenta la información de GNU Radio, Dire Wolf y el correlacionador RSSI sin recargar manualmente el navegador.
El diseño conserva la estética negra y verde de monitor CRT e incorpora un mapa interactivo y un panel analítico lateral.
La interfaz consulta:
/api/v1/locations?heard=1
La respuesta contiene transmisor, RSSI promedio, última recepción y, cuando existen, latitud y longitud. El navegador actualiza la información cada 60 segundos.
Cada registro con coordenadas válidas se representa mediante un marcador identificado con la distintiva. Al seleccionarlo se muestran el transmisor, el RSSI promedio y la fecha y hora simplificadas de la última recepción.
La estación experimental LW2ERA se señala mediante una torre roja fija, diferenciada de las estaciones recibidas.
Los transmisores sin latitud o longitud se presentan en la lista lateral “Estaciones sin location”, conservando distintiva, RSSI y última fecha de escucha.
Así se observa toda la actividad recibida aunque una trama no aporte una posición utilizable.
La actualización reconcilia la respuesta completa con la pantalla, evitando acumular estaciones obsoletas.
La versión web completa el recorrido desde la adquisición de muestras I/Q hasta una representación comprensible de estaciones reales, cobertura y niveles recibidos.
Este hito establece la base para visualizaciones históricas, análisis por estación y evaluación objetiva de cambios en filtros, ganancia y procesamiento del receptor.