Hola Habr
La
segunda parte examinó los aspectos prácticos del uso de SDR. En esta parte, veremos cómo recibir datos satelitales del clima NOAA utilizando Python y el receptor RTL-SDR económico ($ 30). El código considerado funcionará en todas partes: en Windows, OSX, Linux e incluso en Raspberry Pi.

A quién le importa, continuó bajo el corte.
SoapySDR
Hay bastantes fabricantes de varios dispositivos SDR, y sería muy inconveniente admitir cada uno por separado, y es costoso en términos de compra de hardware para pruebas. En principio, para el acceso unificado, hay dos bibliotecas que se han convertido esencialmente en el estándar. La primera es la interfaz
ExtIO DLL bastante antigua, que probablemente no tenga menos de 10 años, la segunda es la biblioteca
SoapySDR más moderna, que examinaremos.
SoapySDR es un conjunto de bibliotecas multiplataforma escritas en C ++ que proporcionan acceso unificado a dispositivos SDR, tanto receptores como transceptores. Si el fabricante crea una interfaz de este tipo, su dispositivo funcionará automáticamente con un número bastante grande de programas populares (GQRX, Radio GNU, CubicSDR, etc.). Casi todos los fabricantes adecuados, excepto algunos,
(aprovechando esta oportunidad, le envío mis saludos a EE) tienen soporte SoapySDR, puede encontrar una lista de dispositivos compatibles
en la página del proyecto . Como puede ver, es bastante grande e incluye HackRF, USRP, SDRPlay, LimeSDR, RTL-SDR, Red Pitaya y muchos otros.
La biblioteca SoapySDR es multiplataforma, es decir. el código escrito para él funcionará en Windows, OSX, Linux e incluso en Raspberry Pi. Para Windows, las bibliotecas requeridas son parte del paquete
PothosSDR ; para otras plataformas, SoapySDR deberá compilarse de forma independiente. Es necesario compilar dos partes: la
biblioteca en sí y el "complemento" para el receptor deseado, en nuestro caso será
SoapyRTLSDR (en Windows, la biblioteca también se puede ensamblar desde la fuente, para esto necesita Visual Studio, Cmake y SWIG). Ahora todo está listo y puedes escribir código.
Importamos la biblioteca y obtenemos una lista de receptores:
from __future__ import print_function import SoapySDR
Conectamos el receptor, ejecutamos el código y vemos una lista de dispositivos, entre los cuales está nuestro rtlsdr.

El resto de los dispositivos son tarjetas de sonido, como recordamos, históricamente los primeros SDR funcionaban con precisión a través de la entrada lineal de la PC, y la biblioteca también los admite. Obtenemos información sobre el dispositivo: la cantidad de canales disponibles, el rango de frecuencia, etc.
soapy_device = "rtlsdr" device = SoapySDR.Device(dict(driver = soapy_device)) channels = list(range(device.getNumChannels(SoapySDR.SOAPY_SDR_RX))) print("Channels:", channels) ch = channels[0] sample_rates = device.listSampleRates(SoapySDR.SOAPY_SDR_RX, ch) print("Sample rates:\n", sample_rates) bandwidths = list(map(lambda r: int(r.maximum()), device.getBandwidthRange(SoapySDR.SOAPY_SDR_RX, ch))) print("Bandwidths:\n", bandwidths) print("Gain controls:") for gain in device.listGains(SoapySDR.SOAPY_SDR_RX, ch): print(" %s: %s" % (gain, device.getGainRange(SoapySDR.SOAPY_SDR_RX, ch, gain))) frequencies = device.listFrequencies(SoapySDR.SOAPY_SDR_RX, ch) print("Frequencies names:", frequencies) frequency_name = frequencies[0] print("Frequency channel name:", frequency_name) print("Frequency range:", device.getFrequencyRange(SoapySDR.SOAPY_SDR_RX, ch, frequency_name)[0])
Iniciamos el programa y vemos información sobre el receptor:

Vemos que el receptor tiene un canal de entrada con el nombre "RF", las posibles frecuencias de muestreo [250000.0, 1024000.0, 1536000.0, 1792000.0, 1920000.0, 2048000.0, 2160000.0, 2560000.0, 2880000.0, 3200000.0] y el rango de frecuencia de 24 MHz-1.7 GHz.
Hack de vida: los mismos datos también se pueden obtener de la línea de comando escribiendo el comando
SoapySDRUtil --probe = "driver = rtlsdr" .
Sabiendo esto, podemos grabar el flujo de datos en WAV. Como se mencionó en la parte anterior, los datos del SDR están representados por un flujo de señales llamadas I y Q, que son muestras del ADC, aproximadamente se pueden representar como datos RAW de la cámara. Cualquier persona interesada en más detalles puede leer, por ejemplo,
aquí . Es suficiente para nosotros saber que podemos escribir estos datos, y otros programas SDR pueden trabajar con ellos.
El registro en sí es bastante simple: la función readStream llena el búfer si hay datos, si aún no hay datos, se devolverá -1. A continuación se muestra un código de registro de 10 muestras (se omiten partes no esenciales del código).
device.setFrequency(SoapySDR.SOAPY_SDR_RX, channel, "RF", frequency) device.setGain(SoapySDR.SOAPY_SDR_RX, channel, "TUNER", gain) device.setGainMode(SoapySDR.SOAPY_SDR_RX, channel, False) device.setSampleRate(SoapySDR.SOAPY_SDR_RX, channel, sample_rate)
El resultado en la captura de pantalla:

Como puede ver, obtenemos bloques de datos del dispositivo, el tamaño de un bloque es de 131072 bytes, que a una frecuencia de muestreo de 250,000 nos da una duración de aproximadamente medio segundo. En general, aquellos que trabajaron previamente con tarjetas de sonido en Windows encontrarán mucho en común.
Para la prueba, escriba el archivo y verifique que todo esté bien; se puede reproducir en SDR #. Hay otro truco aquí: para que SDR # muestre correctamente las frecuencias de las estaciones, el nombre del archivo debe estar escrito en un formato compatible con HDSDR, en la forma "HDSDR_20190518_115500Z_101000kHz_RF.wav" (como puede adivinar, la fecha y la hora están en GMT al principio, luego la frecuencia en kilohercios) . Esto es fácil de escribir en Python:
frequency = 101000000 file_name = "HDSDR_%s_%dkHz_RF.wav" % (datetime.datetime.utcnow().strftime("%Y%m%d_%H%M%SZ"), frequency/1000)
Primero, verifique la banda de FM. Todo está bien, la estación es visible, se está reproduciendo música, RDS está funcionando.

Puede comenzar a grabar NOAA.
Ingesta de NOAA
Entonces, tenemos un receptor y un programa de grabación. Nos interesarán los satélites meteorológicos NOAA 15, NOAA 18 y NOAA 19 que transmiten imágenes de la superficie de la Tierra a frecuencias de 137.620, 137.9125 y 137.100 MHz. La principal dificultad aquí es que necesitas "atrapar" el momento en que el satélite vuela sobre nosotros. Puede averiguar el tiempo de vuelo en línea en
https://www.n2yo.com/passes/?s=25338 ,
https://www.n2yo.com/passes/?s=28654 y
https://www.n2yo.com / pasa /? s = 33591 respectivamente.

Para no sentarse en la computadora, agregue al programa la espera del momento adecuado. Esto también le permitirá ejecutar el programa en la Raspberry Pi, sin pantalla ni teclado.
import datetime def wait_for_start(dt):
Por cierto, para ejecutar el script en Raspberry Pi y dejarlo funcionando después de cerrar la consola, debe ingresar el comando "nohup python recorder.py &".
Todo está listo, ejecuta el script y puede hacer otras cosas, la grabación dura unos 20 minutos. En paralelo, puede surgir la pregunta: ¿es posible ver el paso del satélite a simple vista? Según la tabla, su brillo máximo es de aproximadamente 5,5 m de
magnitud , el límite del ojo humano en condiciones ideales es de 6 m. Es decir En un cielo realmente oscuro, más allá de la ciudad, el paso del satélite NOAA se puede notar teóricamente, en la ciudad, por supuesto, no hay posibilidad (como
escribieron en Habré , una generación de personas que nunca han visto la
Vía Láctea en su vida ya ha crecido).
El resultado del script es un archivo wav grabado, su espectro se muestra en la captura de pantalla.

Vemos una señal completamente distinguible, aunque, por supuesto, con una
antena especial para recibir NOAA, la calidad sería mucho mejor. El formato de la señal se llama APT (
transmisión automática de imágenes ), de él puede obtener una imagen de la superficie de la tierra, si alguien está interesado, puede considerar por separado su decodificación. Pero, por supuesto, hay programas listos para usar, puede decodificar tales señales usando WxToImg o MultiPSK.
Es interesante ver el cambio Doppler en el espectro, que ocurre porque el satélite vuela más allá de nosotros. Probablemente, no es difícil calcular su velocidad, conociendo el cambio de tiempo y frecuencia en hercios.
Por supuesto, el programa se puede usar no solo para grabar NOAA, sino que se puede especificar cualquier ancho de banda y frecuencia en la configuración. Para aquellos que quieran experimentar con SoapySDR, el código del programa se encuentra completamente debajo del spoiler.
Código fuente from __future__ import print_function import SoapySDR import numpy as np import struct import sys import time import datetime def wait_for_start(dt):
SoapySDR plus es que el mismo programa con cambios mínimos funcionará con otros receptores, por ejemplo con SDRPlay o HackRF. Bueno, también se ha mencionado la multiplataforma.
Si los lectores aún tienen interés en el tema de la recepción de radio, puede considerar un ejemplo de uso de SDR con Radio GNU creando varios receptores virtuales basados en un hardware.