别再只玩树莓派了!用USRP B210和GNU Radio搭建你的第一个FM收音机(附Python代码)

张开发
2026/4/21 18:18:38 15 分钟阅读

分享文章

别再只玩树莓派了!用USRP B210和GNU Radio搭建你的第一个FM收音机(附Python代码)
从科研到创客用USRP B210打造你的首个FM收音机系统当大多数人还在用树莓派做智能家居控制时一群硬件极客已经将价值上万元的科研设备变成了电子创客玩具。USRP B210搭配GNU Radio的组合正从实验室走向创客工作台让普通开发者也能体验软件定义无线电(SDR)的魅力。本文将带你用这套专业设备实现一个能实际收听的FM广播接收机过程中不仅会理解SDR的核心原理还能获得可直接复用的Python代码。1. 硬件准备与环境搭建1.1 USRP B210设备解析USRP B210是Ettus Research推出的全双工SDR设备其核心优势在于频率覆盖70MHz-6GHz的超宽频段轻松应对FM广播频段(87.5-108MHz)采样率最高61.44MS/s的采样能力接口USB 3.0超高速数据传输集成度内置FPGA可编程逻辑单元连接设备时需注意使用高质量USB 3.0线缆建议长度不超过1米外接合适的天线FM广播推荐使用VHF宽频天线确保主机供电充足可考虑使用带电源的USB Hub1.2 GNU Radio安装指南推荐使用Ubuntu 20.04 LTS系统安装步骤如下# 添加PPA源 sudo add-apt-repository ppa:gnuradio/gnuradio-releases sudo apt update # 安装完整套件 sudo apt install gnuradio python3-packaging python3-pyqt5 \ libuhd-dev uhd-host # 验证安装 gnuradio-companion --version安装完成后运行uhd_find_devices命令应能识别到连接的USRP设备。若遇到权限问题可执行sudo usermod -a -G usrp $USER sudo chmod 666 /dev/bus/usb/*2. FM接收机原理与GRC流图设计2.1 FM解调核心流程完整的FM接收链路包含以下关键环节射频接收天线捕获空中无线电波下变频将高频信号转换到基带滤波提取目标频段信号解调从载波中还原音频信号去加重补偿广播发射端的高频预加重音频输出驱动扬声器播放下表对比了传统收音机与SDR方案的差异模块传统方案SDR方案调谐可变电容/电感数字下变频滤波LC谐振电路FIR数字滤波解调鉴频器正交解调算法控制机械旋钮软件参数调节2.2 GRC流图搭建实战打开GNU Radio Companion(GRC)按以下步骤构建流图添加UHD: USRP Source模块设备参数typeb200中心频率98e6以98MHz为例采样率2e62MS/s添加QT GUI Range控件IDfreq范围87.5e6到108e6步进0.1e6连接Low Pass Filter截止频率75e3过渡带宽25e3添加Quadrature Demod模块增益参数1.0/75e3/3.14/2.0完整流图结构如下[USRP Source] - [Frequency Shift] - [Low Pass Filter] - [Quadrature Demod] - [Audio Sink]提示FM广播信号带宽通常为200kHz设置采样率时应至少为带宽的2倍3. 参数优化与性能调校3.1 关键参数配置技巧中心频率选择# 动态设置频率的Python代码示例 def set_frequency(uhd_src, freq): uhd_src.set_center_freq(freq, 0) print(fTuned to {freq/1e6} MHz)增益控制策略RF增益20-30dB避免前端过载IF增益自动增益控制(AGC)模式BB增益保持默认值采样率权衡较高采样率更好的信号质量较低采样率减少CPU负载3.2 常见问题排查无信号接收检查天线连接验证USRP电源指示灯运行uhd_usrp_probe诊断工具音频失真# 调整解调增益的公式 demod_gain samp_rate/(2*np.pi*deviation)其中deviation为FM频偏广播标准为75kHz高CPU占用降低采样率使用更简单的滤波器启用流图优化选项4. 从图形化到代码Python实现进阶4.1 GRC导出代码解析GRC生成的Python脚本主要包含以下结构class top_block(gr.top_block): def __init__(self): gr.top_block.__init__(self) # 模块初始化 self.uhd_usrp_source uhd.usrp_source( ,.join((, )), uhd.stream_args( cpu_formatfc32, channelsrange(1), ), ) # 参数设置 self.uhd_usrp_source.set_samp_rate(2e6) self.uhd_usrp_source.set_center_freq(98e6, 0) # 流图连接 self.connect((self.uhd_usrp_source, 0), (self.audio_sink, 0))4.2 自定义功能扩展实现频率扫描功能的代码示例import numpy as np from gnuradio import gr class freq_scanner(gr.sync_block): def __init__(self, scan_range[87.5e6, 108e6], step0.1e6): gr.sync_block.__init__( self, nameFrequency Scanner, in_sig[np.complex64], out_sigNone ) self.scan_range scan_range self.step step self.current_freq scan_range[0] def work(self, input_items, output_items): # 计算信号强度 power np.mean(np.abs(input_items[0])**2) # 存储扫描结果 if self.nitems_written(0) % 1000 0: print(fFreq: {self.current_freq/1e6}MHz | Power: {10*np.log10(power)} dB) # 跳转到下一个频率 self.current_freq self.step if self.current_freq self.scan_range[1]: self.current_freq self.scan_range[0] # 更新USRP频率 self.set_uhd_freq(self.current_freq) return len(input_items[0])5. 项目进阶与扩展应用5.1 信号分析工具集成结合Matplotlib实现频谱显示from matplotlib import pyplot as plt from scipy import fftpack def plot_spectrum(samples, fs): N len(samples) yf fftpack.fft(samples) xf np.linspace(-fs/2, fs/2, N) plt.figure() plt.plot(xf, 10*np.log10(np.abs(fftpack.fftshift(yf)))) plt.xlabel(Frequency (Hz)) plt.ylabel(Power (dB)) plt.grid() plt.show()5.2 多平台部署方案将接收系统部署到嵌入式平台的注意事项使用Raspberry Pi 4需外接USB 3.0扩展卡推荐使用64位操作系统降低采样率至1MS/s以下远程控制实现import xmlrpc.server class USRP_Server: def __init__(self, tb): self.tb tb def set_freq(self, freq): self.tb.uhd_usrp_source.set_center_freq(freq) return True server xmlrpc.server.SimpleXMLRPCServer((0.0.0.0, 8000)) server.register_instance(USRP_Server(tb)) server.serve_forever()在实际测试中使用标准FM广播信号源这套系统可以达到与传统收音机相当的音质水平同时具备以下独特优势实时频谱分析能力多频道同时监测自定义信号处理算法远程控制和自动化能力

更多文章