当前位置: 首页 > news >正文

用 HackRF + GNU Radio 制作 FM 发射机:从 WAV 到 103 MHz 空中信号

用 HackRF + GNU Radio 制作 FM 发射机:从 WAV 到 103 MHz 空中信号

作者:charlie
关键词:HackRF、GNU Radio 3.10、SoapySDR、analog_wfm_tx、FM 广播调制、采样率链

摘要

本文记录如何用一块 HackRF One/Pro 配合 GNU Radio,把一个普通 WAV 音频文件调制成标准 FM 广播信号并发射到空中(默认 103 MHz),用普通收音机即可接收。文章给出完整可运行的流图fm_tx.grc,并重点讲清三件事:(1) FM 调制与卡森带宽准则,为什么max_dev=75 kHzquad_rate必须是audio_rate的整数倍;(2) GNU Radioanalog_wfm_tx的内部插值(×5)与预加重(tau=75 µs);(3)SoapySDR 下 HackRF 在 1 MHz 采样率发射会触发 TIMEOUT bug,因此必须用 2 MHz 采样率,并用rational_resampler的 25/3 把 240 kHz 提到 2 MHz。文末附合规声明:本方案仅用于低功率近场教学测试。


1. 背景

FM 广播频段为 88–108 MHz,单声道基带音频带宽约 15 kHz,峰值频偏 75 kHz。HackRF 覆盖 1 MHz–6 GHz、半双工、8 位量化,既能接收也能发射,是做“软件定义 FM 发射机”的低成本平台。

目标链路非常短:

WAV 文件 (48k, 单声道) │ ▼ analog_wfm_tx (FM 调制, 插值 ×5) 240 kHz 复数基带 │ ▼ rational_resampler_ccc (25/3) 2 MHz 复数基带 │ ▼ soapy_hackrf_sink (TX, fc = freq×1e6, vga=16) 空中 103 MHz FM 信号 │ └─► qtgui_sink_x (本地频谱自检)

2. 理论基础

2.1 FM 调制与卡森带宽准则

在频率调制中,载波的瞬时频率正比于消息信号的幅度:

s(t) = A·cos( 2π·fc·t + 2π·kf·∫ m(τ)dτ )
  • kf决定频偏灵敏度;实际工程用峰值频偏 Δf描述:max_dev = 75000Hz。
  • 根据Carson 带宽准则,已调信号 98% 功率落在:
BW ≈ 2·(Δf + f_m,max)

FM 广播Δf = 75 kHz,基带最高f_m,max ≈ 15 kHz,故BW ≈ 2×(75+15) = 180 kHz。这就是quad_rate = 240 kHz(留有余量,且为audio_rate的 5 倍)的来源。

2.2 预加重 / 去加重(tau = 75 µs)

高频噪声在 FM 解调后会被提升,因此发射端对高频做预加重、接收端做去加重,以换得信噪比改善。时间常数分两派:

地区tau
美国 / 日本 / 韩国等75 µs
欧洲 / 中国等50 µs

analog_wfm_txtau = 75e-6对应 75 µs 预加重(美规)。若面向欧规设备,应改为50e-6fh = -1.0表示关闭发射端的高通滤波器(不额外滤直流)。

2.3 GNU Radio analog_wfm_tx 原理

analog_wfm_tx内部做四件事:

  1. 重采样:内置插值因子固定为5,所以要求quad_rate = 5 × audio_rate(本例 48k → 240k)。它把音频上采样后再调制,保证每个音频样本有足够多的复数采样刻画频率变化。
  2. 预加重:按tau对音频做一阶高通式加权。
  3. 相位累加 FM 调制:对每个输出采样累加相位增量Δφ = 2π·(kf·m[n])/fs,再取cos/sin得到复数基带I + jQ。这正是“间接调频”——用积分+正交本振实现,避免直接调 VCO。
  4. 限幅/缩放:输出幅度归一化到适合 DAC 的范围。

2.4 采样率链与 HackRF 限制(关键坑)

HackRF 基带采样率规格为2–20 MS/s。1 MHz 在规格外,且SoapySDR 的 HackRF TX 在 1 MHz 会触发 TIMEOUT bug(底层hackrf库在过低的采样率下 TX 超时,流图卡死/丢数)。因此:

  • wfm_tx自然产出 240 kHz;
  • rational_resampler_ccc(interp=25, decim=3)把它提到240k × 25/3 = 2,000,000 = 2 MHz,正好落在 HackRF 合法区间下沿;
  • HackRFsamp_rate设为 2 MHz,center_freq = freq × 1e6

若强行把samp_rate设 1 MHz,流图能“跑起来”但发射会间歇卡死且频谱异常——这是 Soapy/HackRF 的已知问题,不是你流图写错。

2.5 法律与责任(务必阅读)

在 88–108 MHz发射信号,绝大多数国家/地区都需要电台执照;未经许可的 FM 广播发射可能违法并干扰合法广播。本文设置:

  • amp = False(关闭 HackRF 板载放大器);
  • vga = 16(适中增益,低功率);
  • 配合短天线、近场测试(发射机旁放一台收音机验证)。

请仅在合法授权、低功率、封闭/近场场景使用本方案,并遵守当地无线电法规。作者与本文不对任何违规使用负责。


3. 实践:流图搭建

3.1 音频准备

analog_wfm_tx要求单声道且采样率与audio_rate一致。用 ffmpeg 把任意音频转成 48 kHz 单声道 WAV:

ffmpeg-iin.wav-ar48000-ac1fm_input.wav

流图中blocks_wavfile_source指向/path/to/fm_input.wavrepeat=True(循环播放,方便反复测试)。

3.2 流图关键参数

变量 / 模块说明
freq88–108 MHz 滑杆,默认 103发射中心频率
samp_rate2,000,000HackRF TX 采样率(≥2M,避开 1M bug)
audio_rate48,000必须与 WAV 一致
quad_rate240,000= 5 × audio_rate
analog_wfm_tx.max_dev75,000峰值频偏 75 kHz(FM 广播标准)
analog_wfm_tx.tau75e-675 µs 预加重
rational_resamplerinterp=25, decim=3240k → 2M
soapy_hackrf_sink.vga16低功率增益
soapy_hackrf_sink.ampFalse关闭板载放大

3.3 关键模块源码(来自 fm_tx.grc)

WAV 源(循环播放):

-name:wav_source_0id:blocks_wavfile_sourceparameters:file:/path/to/fm_input.wavnchan:'1'repeat:'True'

FM 调制核心:

-name:analog_wfm_tx_0id:analog_wfm_txparameters:audio_rate:audio_rate# 48000quad_rate:quad_rate# 240000 (= 5 × audio_rate)max_dev:'75000'# 峰值频偏 75 kHztau:75e-6# 75 µs 预加重fh:'-1.0'# 关闭发射高通

采样率提升到 2 MHz(绕过 1M TX bug):

-name:rational_resampler_ccc_0id:rational_resampler_xxxparameters:type:cccinterp:'25'# 240000 × 25 / 3 = 2,000,000decim:'3'taps:'[]'

HackRF 发射与本地频谱自检:

-name:soapy_hackrf_sink_0id:soapy_hackrf_sinkparameters:type:fc32center_freq:freq*1e6# 103 MHzsamp_rate:samp_rate# 2,000,000vga:'16'amp:'False'# 低功率,合规近场测试bandwidth:'0'-name:qtgui_sink_x_0id:qtgui_sink_xparameters:type:complexfc:freq*1e6bw:samp_ratefftsize:'1024'plotfreq:'True'plotwaterfall:'True'

连接关系(等价于生成的 fm_tx.py):

# 信号流:WAV → FM调制 → 重采样(→2M) → HackRF TX,并旁路一份给频谱仪self.connect((self.wav_source_0,0),(self.analog_wfm_tx_0,0))self.connect((self.analog_wfm_tx_0,0),(self.rational_resampler_ccc_0,0))self.connect((self.rational_resampler_ccc_0,0),(self.soapy_hackrf_sink_0,0))self.connect((self.rational_resampler_ccc_0,0),(self.qtgui_sink_x_0,0))

4. 运行与自检

启动(GRC 或grcc生成脚本):

grcc-o/tmp fm_tx.grc&&python3 /tmp/fm_tx.py# 或直接用 GRC 的 “Run”

自检验证两步走:

  1. 本地频谱自检qtgui_sink_x应显示以 103 MHz 为中心、宽约 180–200 kHz 的 FM 谱(典型“双驼峰” Carrier + 对称边带)。若谱很窄或卡死,多半是踩了 1M bug——确认samp_rate=2M
  2. 真实接收:把一台 FM 收音机调到 103.0 MHz,靠近 HackRF 天线,应清晰听到 WAV 里的声音(循环播放便于确认)。听感发闷/高频不足,检查tau与接收机去加重是否匹配(美规 75 µs 对 75 µs)。

小贴士:freqcounter_slider可在运行中平滑改频;改到 88–108 内任意值,收音机同步调台即可验证。


5. 总结与踩坑清单

核心结论

  1. FM 广播调制 = 相位累加的数字 FM;quad_rate必须是audio_rate5 倍analog_wfm_tx内置插值 ×5)。
  2. 峰值频偏75 kHz+ 卡森准则 ⇒ 占用带宽约 180 kHz,决定了quad_rate=240k的选取。
  3. HackRF TX 不能用 1 MHz 采样率(Soapy TIMEOUT bug),必须 ≥2 MHz;用rational_resampler25/3 把 240k 升到 2M 是标准解法。
  4. 预加重tau=75 µs对应美规;面向欧规设备改50 µs

踩坑清单

  • 收音机收到但声音发尖/失真max_dev与收音机期望不一致,或音频本身超出 15 kHz;确认max_dev=75k
  • 收音机高频发闷tau不匹配(发射 75 µs 配欧规 50 µs 收音机会有差异)。
  • 流图卡死 / 频谱断续→ 几乎都是samp_rate=1M触发 Soapy/HackRF TX TIMEOUT;改成 2M。
  • 完全收不到→ 先确认amp=False时增益足够近场;天线用 88–108 MHz 鞭状天线;收音机与 HackRF 距离过远(低功率下十几厘米~一米内最佳)。
  • 音频杂音大→ WAV 不是 48k 单声道;用 ffmpeg 重转,并保证audio_rate与文件一致。

适用与局限

  • 适用:FM 广播调制教学、近场音频链路演示、SDR 发射链路验证。
  • 局限:HackRF 8 位 DAC,音质远不及专业 FM 激励器;半双工,不能收发同时;发射须合规、低功率、近场;立体声(MPX/Pilot 19 kHz)未实现,本文为单声道 FM。

合规声明(重申)

在 FM 广播频段发射通常需无线电执照。本方案默认amp=Falsevga=16、循环近场测试,仅供教学与合法授权场景。使用者须自行确保符合当地法规,作者对任何滥用后果不承担责任。

参考

  • GNU Radioanalog.wfm_tx文档(插值因子、预加重、频偏参数)
  • Carson, J. R. — “Notes on the Theory of Modulation” (1922),卡森带宽准则
  • HackRF One 规格(采样率 2–20 MS/s)、SoapySDR HackRF 模块
  • ITU / 当地无线电管理法规(FM 广播发射授权要求)
http://www.jsqmd.com/news/1402320/

相关文章:

  • 辣知·化智25 上古夷夏文明的东西格局
  • Windows系统删除“...”畸形文件夹的三种有效方法
  • Python脚本执行全解析:从基础运行到工程化部署的完整指南
  • Windows远程桌面连接Ubuntu:xrdp+Xorg保姆级配置与排错指南
  • 降AIGC终极攻略!AI率92%暴降至5%!实测10款降AIGC软件!免费降AIGC额度薅到爽!
  • 鸿蒙开发环境搭建:DevEco Studio Windows Tool 3.0.0.800 安装与配置全指南
  • 基于OpenClaw与本地大模型构建梅花易数AI智能体实践
  • 金钟壶红丝垂落,像把窑火留在月白上
  • 用过才知道,涿州会计供应商真的能满足财务需求吗?
  • 一次请求的前世今生(进阶):底层原理与生产环境那些坑
  • 并查集实战:扩展域思想解决“团伙”问题与C++实现
  • Python list()与map()深度解析:从基础到高阶的性能优化与实战应用
  • 炼油厂核心装置沙盘模型控制系统设计:基于STM32与Modbus RTU的常减压蒸馏-催化裂化-乙烯裂解全流程联动方案
  • 2026 年山东口碑好的美麟鸡柳棒品牌哪家可靠,楼下炸串摊的这玩意儿,比别家嫩三倍还无骨,老板说没人猜得出它的真实身份 - 行业严选官
  • 光纤线缆标识解读:从编码原理到运维实战的完整指南
  • Windows 10应用安装失败深度解析:从UWP机制到Microsoft To-Do安装全攻略
  • 基于OpenClaw构建自复盘AI智能体协作系统:从架构到实践
  • 数据脱敏实战:从原理到实现,构建隐私保护工具链
  • C# Dictionary字典
  • 找回昨天的自己:ArkTS 时间分组与关键词搜索的查询实现
  • VSCode我推荐的23个不得不装的插件
  • Hand Visibility Detector 论文解读
  • LeetCode AI助手:苏格拉底式引导与面试模拟提升算法思维
  • 算法与数据结构实战指南:从核心原理到工程优化
  • OpenClaw与Deepgram构建自动化语音转录工作流实战
  • Ubuntu启动卡在Logo界面?深度诊断与修复指南
  • Hive DML操作全解析:从数据装载到行级更新的核心技术与实战
  • AI论文写作工具哪个最好?2026亲测
  • 固定资产软件别只看功能数量:一份面向财务、集团与运维团队的选型指南
  • 无视觉无电机平衡小球方案:基于IMU与舵机的动态控制实现