Radio FM con Python + Algoritmo Genético: tu SDR que se sintoniza sola
Inicia sesión para descargarEn este tutorial vas a construir una radio FM en Python que no solo escucha el aire: usará un Algoritmo Genético para “evolucionar” y encontrar, por sí sola, la mejor configuración de …
Contenido del tutorial ⌄
¿Alguna vez giraste el dial de una radio antigua buscando esa frecuencia perfecta entre ruido y estática? Requiere paciencia y buena puntería. Ahora imagina enseñarle al computador a hacerlo por ti usando los principios de la evolución de Charles Darwin.
En este tutorial construiremos una radio FM en Python que no solo capta señales del aire, sino que utiliza un algoritmo genético para “evolucionar” hasta dar con la configuración que ofrece una recepción limpia. Vamos a mezclar hardware, procesamiento de señales y un toque de IA para crear una radio que se sintoniza sola.
Los ingredientes para esta aventura 📻
Antes de escribir una sola línea de código, asegúrate de tener lo necesario. Este proyecto combina hardware y software.
Vas a necesitar un dongle USB RTL-SDR como base de hardware y Python 3 instalado. Luego, abre tu terminal e instala las librerías con: pip install numpy scipy sounddevice pyrtlsdr.
Anatomía del código: el ADN de nuestra radio inteligente
Todo buen script arranca con una breve documentación: qué hace, de qué depende y cómo se ejecuta. Luego importamos las herramientas —nuestros “genes”— que darán vida al programa: numpy para cálculos, scipy para señales, sounddevice para audio, rtlsdr para hablar con el hardware y algunas utilidades de Python.
Encabezado e importaciones del script
import numpy as np
import random
from scipy.signal import decimate, resample_poly
import sounddevice as sd
from rtlsdr import RtlSdr
from threading import Thread
import queue
import argparse
El traductor: de ondas a sonido básico
La señal que llega del SDR está modulada en frecuencia (FM), así que no es audio listo para escuchar. La función fm_demodulate hace la traducción: toma las muestras complejas y las convierte en una señal que ya representa el audio original.
Función fm_demodulate
def fm_demodulate(samples):
"""Demodula una señal FM usando la derivada de fase."""
return np.angle(samples[1:] * np.conj(samples[:-1]))
La voz: reproducción fluida en segundo plano
Para evitar cortes cuando el procesador está ocupado, dedicamos un hilo (Thread) solo a reproducir. La función audio_stream corre en paralelo, recibe bloques por una cola (Queue) y los envía al dispositivo de audio sin interrupciones.
Función audio_stream
def audio_stream(q, sample_rate):
"""Reproduce audio desde una cola."""
with sd.OutputStream(channels=1, samplerate=int(sample_rate), dtype='float32') as stream:
while True:
data = q.get()
if data is None: # Señal para terminar el hilo
break
stream.write(data)
El juez: la función de aptitud (fitness)
Esta función decide qué tan buena es cada configuración. Sintoniza con una frecuencia, ganancia y tasa de muestreo, escucha un instante y calcula una medida de “energía” de la señal. Una emisora clara tiene más energía; el ruido, menos.
💡 Analogía evolutiva: get_signal_quality es el “ambiente”. Las configuraciones con más puntuación “sobreviven”; las que rinden mal, desaparecen.
Función get_signal_quality
def get_signal_quality(sdr, frequency, gain, sample_rate):
"""Obtiene una métrica de calidad de la señal para una frecuencia, ganancia y tasa de muestreo dadas."""
try:
sdr.center_freq = frequency
sdr.gain = gain
sdr.sample_rate = sample_rate
samples = sdr.read_samples(256 * 1024)
demodulated = fm_demodulate(samples)
signal_energy = np.sum(np.abs(demodulated) ** 2)
return signal_energy
except Exception as e:
print(f"Error al obtener la calidad de la señal: {e}")
return -np.inf # Devolver un valor muy bajo si hay error
El motor evolutivo: el ciclo de la vida
Aquí es donde ocurre la magia. optimize_parameters_ga crea una población inicial al azar y, durante varias generaciones, evalúa individuos, selecciona a los mejores y genera descendencia mediante cruzamiento y mutación. Con cada ciclo, la población mejora y nos acercamos a la mejor configuración.
Función optimize_parameters_ga
Comentarios y valoraciones
No hay comentarios aún. ¡Sé el primero en opinar!