1. 项目概述用ESP32-S3让老式收音机“上网”最近我完成了一个挺有意思的小项目用一块ESP32-S3开发板把网络电台的音频流接收下来解码然后通过一根从旧收音机里拆出来的磁棒天线以AM调幅广播的方式发射出去。这样一来我书架上那台几十年前的老式晶体管收音机就能直接收听到世界各地的网络电台了。这感觉就像给古董收音机装上了“数字心脏”让它在数字时代重新焕发生机。这个项目的核心是把现代的数字信号处理技术和经典的模拟无线电技术结合在了一起。ESP32-S3负责从Wi-Fi获取HLS/AAC格式的网络音频流在芯片内部实时解码成PCM音频然后通过一种叫做“Σ-Δ编码”的数字调制技术直接在I2S接口上生成AM调制的射频信号。最终这个数字信号经过一个简单的驱动电路送到磁棒天线上发射出去。整个过程从数字流到空中传播的无线电波几乎全部在ESP32-S3内部完成硬件电路异常简洁。我之所以想做这个一方面是出于对老物件的喜爱想让它们继续发挥作用另一方面也是想挑战一下ESP32-S3这颗芯片的实时处理能力。它那双核架构、大容量的PSRAM以及硬件音频解码加速到底能不能流畅地搞定从网络流媒体到射频生成这一整条高实时性要求的处理链实测下来效果远超预期。2. 硬件设计极简主义的射频发射器2.1 核心控制器与外围电路整个项目的硬件核心是一块ESP32-S3-WROOM-1模组我特意选了带8MB PSRAM的版本。这8MB的PSRAM至关重要它充当了音频数据的“蓄水池”。网络下载的AAC数据包、解码后的PCM音频流都需要在这里进行缓冲。如果没有这片额外的内存在Wi-Fi网络稍有波动时音频播放就很容易出现卡顿或中断。16MB的Flash则绰绰有余用来存放固件和网页配置界面。用户交互部分我力求极简。一个8位的二进制编码旋转开关连接在GPIO 40、41和42上用来选择8个预设的网络电台。这个开关的编码方式直接对应一个0-7的索引值省去了软件去抖和编码解析的麻烦。同时我设计了一个复用逻辑长按BOOT键的同时旋转开关可以进入Wi-Fi配网模式此时旋转开关的8个位置对应存储8套不同的Wi-Fi密码方便在不同地点使用。一个WS2812B RGB LED提供了所有的状态反馈。比如切换电台时它会闪烁对应位置的颜色保存Wi-Fi密码时显示绿色网络超时时显示红色等。视觉反馈非常直观完全不需要屏幕。为了测试和校准发射机的性能我增加了一个小功能。在GPIO 3上设置了一个跳线帽接口当短接时设备会进入“正弦波测试模式”。此时旋转开关不再选择电台而是选择8个固定的测试音频频率从46.875 Hz到4.6875 kHz并以80%的固定调制度发射。这个功能在调试天线谐振点和测量失真度时特别好用。2.2 射频输出级从数字比特流到电磁波这是整个硬件设计中最关键也最值得细说的一部分。ESP32-S3的I2S外设被配置为以1.92 Mbps的速率在GPIO 17上输出一串原始的1比特数据流。这个速率是目标载波频率我设为960kHz的两倍。为什么是两倍这涉及到后面要讲的Σ-Δ调制和I2S数据格式的巧妙安排。这个3.3V的数字信号不能直接驱动天线。我最初尝试了一个非常简单的方案用一个2N2222A三极管搭建一个单端驱动电路。结果实测的失真大得惊人在80%调制度时谐波失真高达10%左右。这对于音频传输来说是绝对不能接受的。注意驱动AM发射机末级线性度是首要考量。单管放大电路工作在开关状态或非线性区时会严重劣化调制信号的波形引入大量谐波不仅音质变差还可能产生带外杂散发射。于是我改用了现在的方案一个专用的栅极驱动芯片我手头有些现成的型号比如TC4427之类来构建一个图腾柱输出级。这个电路的作用有两个一是将信号电平从3.3V提升到5V获得更好的驱动能力二是提供极低的输出阻抗和快速的上升/下降时间确保输出的数字方波干净利落。图腾柱结构推挽输出能主动拉高和拉低电平比单管驱动性能好得多。即使换用了图腾柱驱动当我把谐振回路精确调谐到载波频率时频谱仪上依然能看到约3%的二次谐波失真。但有趣的是当我稍微失谐一点磁棒天线的谐振电容时这个失真就消失了。我推测在完美谐振时天线回路的高Q值会导致磁棒内部的磁通密度达到很高水平可能引起了磁芯材料的轻微非线性饱和。这个现象提示我们在实际制作时不一定非要追求绝对的谐振点稍微偏一点或许能获得更好的综合性能。2.3 天线制作与调谐天线是从一台报废的旧AM收音机上拆下来的磁棒天线。磁棒尺寸大约是直径8mm长110mm。我保留了上面的线圈主谐振线圈次级用漆包线绕了大约100匝集中绕在大约24mm的长度上驱动线圈初级只有2匝直接绕在次级线圈的外层。谐振电容也来自同一台旧收音机是一个双联可变电容我把它的两联并联起来以增大容量范围。调谐过程非常简单粗暴将一台成品AM收音机放在2-3米外调到我的发射频率比如960kHz然后慢慢旋转可变电容的旋钮直到收音机里收到的“沙沙”声最响或者测试音调最清晰、音量最大那就是谐振点了。这个发射机的辐射功率 intentionally 设计得非常小有效距离也就几米到十几米。这个功率水平在绝大多数国家和地区都属于“无执照发射”的豁免范围之内用于个人实验和室内收听是没问题的。如果有人想增加发射距离请务必、务必、务必增加低通或带通滤波器因为Σ-Δ调制产生的噪声频谱很宽虽然在我这个小功率设备上不是问题但一旦放大这些带外噪声就可能干扰其他频段的正常业务。3. 软件架构双核协同的实时音频流水线3.1 任务划分与优先级设计ESP32-S3的双核在这里派上了大用场。我的设计原则是所有对实时性要求苛刻的任务全部扔到Core 1APP CPU上而网络、解码等可以容忍一定延迟的任务则放在Core 0PRO CPU上。Core 0 任务低优先级HTTP下载任务负责从互联网获取M3U8播放列表和AAC音频片段文件。网络延迟是波动的所以这个任务优先级不能高。AAC解码任务调用Espressif官方的esp_audio_codec库将下载的AAC数据解码成48kHz、16位、立体声的PCM原始音频。这个计算量不小但用上芯片的硬件加速后压力不大。Core 1 任务高优先级音频处理任务这是整个系统的“心脏”。它接收解码后的PCM数据进行立体声转单声道、动态范围压缩、采样率提升插值最后执行核心的Σ-Δ调制算法生成最终的1比特射频数据流。这个任务必须绝对稳定不能有任何卡顿。I2S DMA服务任务负责将音频处理任务生成的比特流数据通过DMA不间断地喂给I2S外设。这个任务由I2S驱动内部管理但依赖于Core 1上音频处理任务持续供料。在FreeRTOS中我这样设置优先级数字越大优先级越高音频处理任务 (Core 1): 优先级 24I2S服务任务 (由驱动管理): 优先级 23AAC解码任务 (Core 0): 优先级 19HTTP下载任务 (Core 0): 优先级 18M3U8播放列表解析任务 (Core 0): 优先级 17Wi-Fi事件处理、系统监控等任务: 优先级 10以下这样的优先级设计确保了即使网络突然需要重连或处理大量数据Core 1上的音频处理和射频生成也永远能抢到CPU时间从而保证声音连续不中断。3.2 音频流水线与网络优化数据在系统中的流动像一条流水线M3U8解析器首先请求电台的M3U8播放列表URLHTTPS。这里我做了一个非常有效的优化典型的M3U8文件大约70KB每10秒左右更新一次但只是末尾增加一段新的媒体片段URL。如果每隔几秒就重新下载整个70KB的文件太浪费带宽和時間。我的优化策略是每次检查更新时只下载文件的前4KB。这4KB数据一定包含了关键的序列号信息。如果序列号没变说明播放列表没更新立刻终止下载。实测下来这个“偷懒”的方法节省了超过94%的播放列表下载流量并且让电台切换速度大幅提升到1-2秒内完成。AAC片段下载器根据M3U8解析出的URL下载一个个AAC音频片段每个约410KB包含10秒左右的音频。下载的数据被送入AAC解码队列。AAC解码器从队列取出AAC数据利用硬件加速解码为PCM送入PCM环形缓冲区。这个缓冲区很大128KB用来对抗网络抖动。音频处理与调制引擎Core 1从PCM缓冲区取出数据进行后续处理并调制。电台切换的处理逻辑也很重要。当用户转动旋转开关时系统会立即向下载任务发送中止信号立刻停止当前AAC片段的下载。清空AAC解码队列和PCM环形缓冲区。这是为了防止新旧电台的音频数据混在一起产生奇怪的混杂声音。M3U8解析任务会在1秒内检测到电台索引变化并开始获取新电台的播放列表。实操心得在嵌入式网络音频项目中缓冲区的设计是稳定性的关键。我的原则是“宁大勿小”。AAC解码队列和PCM环形缓冲区都设置得比较大用PSRAM的成本很低但这能有效吸收因Wi-Fi信号波动、路由器处理延迟等带来的网络抖动。即使网络短暂卡顿2-3秒缓冲区也能保证音频持续输出用户只会看到状态LED闪烁一下而不会听到声音中断。4. 核心原理Σ-Δ数字调幅详解4.1 音频预处理从立体声到适合调制的单声道网络流媒体通常是立体声的但AM广播传统上是单声道。首先我将左右声道相加并除以2合并为单声道信号。接下来是最关键的一步自动动态范围压缩。AM调制有一个物理限制调制深度不能超过100%否则会导致过调制失真。而音乐和语音的动态范围最弱音和最强音的比值往往很大。如果不加处理弱音部分调制深度太浅信噪比差强音部分又容易冲顶导致过调制。我的压缩器算法很简单但有效计算音频信号的瞬时绝对值全波整流。用一个峰值检测器跟踪信号的包络。这个检测器采用“快攻击、慢释放”的策略当信号幅度上升时峰值跟踪速度很快时间常数约5ms能迅速抓住瞬态峰值当信号下降时峰值缓慢衰减时间常数约680ms。用检测到的峰值作为参考动态调整整个信号的增益使得最大峰值始终对应一个预设的目标电平比如对应90%的调制深度。这样做的效果是无论播放的是激昂的交响乐还是轻柔的独白发射机的调制深度都能保持在一个相对稳定、饱满且不越界的范围内。680ms的慢释放时间保证了音乐的自然起伏感动态不会被完全抹平听感上不会有明显的“喘息效应”。4.2 Σ-Δ调制用1比特流“代表”模拟信号这是整个项目的数字信号处理核心。我们的目标是把48kHz的音频样本转换成一个1.92MHz的1比特数据流并且这个数据流的平均值或说其低频分量要正比于原始的音频信号。第一步采样率提升插值48kHz的音频采样率对于960kHz的载波来说太低了。我们需要通过线性插值将音频数据“填充”到1.92MHz的速率上。我使用定点数Q15格式运算来实现兼顾了速度和精度。一个分数累加器负责跟踪音频样本的相位同时给出插值的权重系数。第二步加入直流偏置和噪声整形AM调制的本质是载波的幅度随着音频信号变化。在数字域我们构造一个“调制信号”调制信号 音频信号 直流偏置。这个直流偏置值设为最大调制范围的一半。这样当音频信号为0时调制信号等于直流偏置对应50%的载波幅度即无调制状态这里需要修正。实际上更准确的理解是我们构造的“调制信号”直接对应了发射信号的包络。当这个信号为0时对应0%调制无输出为最大值时对应100%调制。此外在信号接近直流或极低电平时Σ-Δ调制器容易陷入一种叫做“极限环振荡”的模式产生固定的图案噪声。为了解决这个问题我向音频信号中注入了一点点高通滤波后的伪随机噪声。这个噪声的幅度非常小人耳听不见但它能“搅动”调制器打破固定模式将由此产生的量化噪声推向更高的频率这个过程叫噪声整形而高频噪声很容易被后端的模拟谐振电路滤除。第三步二阶Σ-Δ调制这是核心算法。我把经过插值和偏置处理的RF速率样本送入一个二阶Σ-Δ调制器。这个调制器内部有两个积分器和一个量化器本质上就是一个比较器。它的工作原理是不断累积输入信号与1比特输出之间的误差并反馈回去调整下一次的输出使得在长时间尺度上1比特输出的平均值无限逼近输入信号的值。最终调制器输出一个1.92MHz的1比特流其中“1”和“0”的密度变化就代表了音频信号的变化。第四步从比特流到射频方波如果直接把1.92MHz的1比特流送到GPIO上我们得到的是一个1.92MHz的方波这不是我们想要的AM载波。这里有一个巧妙的变换比特填充。 每产生16个1比特数据我把它们扩展成32位在每个原始比特后面插入一个“0”。 即原始流b0, b1, b2, ... b15变成b0, 0, b1, 0, b2, 0, ... b15, 0。这个操作的神奇之处在于当输入信号为最大值对应100%调制时Σ-Δ调制器会输出全“1”。经过填充后就变成了“1,0,1,0,1,0...”这正好是一个占空比为50%、频率为960kHz的方波这正是我们想要的载波。当输入信号为其他值时填充后的序列中会随机地出现“0,0”或“1,1”的组合但从频谱上看其主要能量仍然集中在960kHz并且其幅度的变化就体现了音频调制。第五步I2S输出最后将填充好的32位数据块通过DMA送入I2S外设。I2S被配置为32位数据宽度、仅使用一个数据线GPIO 17、主模式、无WS字选和BCK位时钟输出。实际上我们只是借用I2S的DMA和并串转换功能将内存中的32位数据以固定的时钟速率60 kHz串行移出。这个时钟频率的计算是载波频率 * 2 / 32 960kHz * 2 / 32 60kHz。I2S外设会自动完成这一切不占用CPU资源。5. 性能实测与调试心得5.1 音质与失真评估我选择测试的电台源都是256kbps的AAC-LC格式音质基础很好。经过整个系统处理后用一台德生牌的老式指针调幅收音机在几米外接收主观听感令人满意。语音清晰音乐也有足够的保真度。自动压缩器工作良好在不同类型的节目间切换时音量保持稳定没有可闻的“泵浦”噪声。使用内置的正弦波测试模式配合一台廉价的RTL-SDR软件无线电接收机和频谱分析软件可以对系统进行客观测量。频率响应在46.875 Hz 到 4.7 kHz的音频范围内幅度波动小于±1dB。AM广播的标准带宽是±4.5kHz这个指标完全达标。总谐波失真THD在1kHz测试音、80%调制度下使用最终版的图腾柱驱动电路并略微失谐天线后测得的THD低于1%。这主要来自于驱动级的非线性Σ-Δ调制器本身引入的失真在频谱仪上几乎看不到。噪声水平在无调制状态下载波纯发射在4.5kHz带宽内测得的信噪比优于50dB。实际播放音频时底噪被音乐掩蔽完全听不到。5.2 频谱分析与合规性考量用频谱仪靠近天线测量发射频谱能直观地看到Σ-Δ调制的特点。近载波频谱10kHz带宽可以看到清晰的载波峰以及对称的调制边带。谐波分量非常低。宽频谱100kHz/1MHz带宽可以看到量化噪声被“整形”到了高频区域在离载波几十kHz远的地方噪声基底就抬起来了。这正是Σ-Δ调制噪声整形的典型特征。对于我这个功率极小微瓦级、天线效率极低磁棒小环的设备这些带外噪声的绝对强度非常微弱完全不会造成任何干扰。但是这是一个非常重要的警示如果有人想通过加装功率放大器、使用长线天线来增加传输距离那么必须在功放之前加入一个截止频率在1MHz左右的低通滤波器狠狠地把这些高频噪声滤掉。否则这些噪声可能会干扰到短波甚至更高频段的其他无线电业务这是非法的也不符合业余无线电爱好者的道德准则。5.3 踩过的坑与解决方案单管驱动失真大如前所述最初用2N2222单管驱动失真严重。解决方案换用图腾柱结构的驱动电路线性度大幅改善。Wi-Fi断流导致声音卡顿早期版本缓冲区较小Wi-Fi信号不稳时容易断音。解决方案增大PSRAM中的环形缓冲区至128KB并为网络任务设置合理的重试机制和超时判断。HTTPS证书验证导致CPU峰值最初启用了完整的TLS证书验证发现在某些流媒体服务器证书链较长时验证过程会短暂占用大量CPU导致Core 1的音频任务被抢占产生“噗噗”的爆音。解决方案对于这个纯娱乐、非敏感的应用我权衡后禁用了服务器证书验证。这确实降低了安全性理论上可能遭遇中间人攻击但性能提升显著且即使被攻击设备也不会泄露任何用户敏感信息。对于商业或敏感应用绝不能这样做可能需要选择更快的加密芯片或优化证书库。磁棒天线谐振点失真发现天线精确谐振时失真反而增大。解决方案调试时不必追求频谱仪上最尖的载波峰应以实际接收到的音频音质纯净为准稍微调偏一点谐振电容往往效果更好。6. 项目总结与扩展思路这个项目成功地验证了ESP32-S3作为一款低成本、高性能的微控制器完全有能力处理从网络流媒体接收、解码到数字射频生成这样一套复杂的实时信号处理任务。双核架构和PSRAM的搭配让任务调度和缓冲游刃有余。代码和完整的硬件设计原理图、PCB布局文件都已经在GitHub上开源Apache 2.0协议。对于想复现或改进的朋友这里有几个可能的扩展方向增加用户界面可以外接一个小OLED屏幕显示电台名称、音量、IP地址等信息。或者做一个简单的网页服务器用手机浏览器来选择和配置电台比旋转开关更灵活。支持更多音频源目前只支持HLS/AAC。可以扩展支持MP3流SHOUTcast、本地SD卡播放甚至蓝牙A2DP输入让设备变成一个通用的“AM转发器”。改进射频前端可以设计一个简单的LC或π型低通滤波器集成到驱动电路之后让输出频谱更干净为未来可能的功率放大打下基础。多频点发射可以通过旋转开关或网页选择不同的载波频率比如中波波段的多个常用频率避免与本地强台干扰。最后必须再次强调合规使用。本项目设计为极低功率的近距离发射旨在实验和教育。在任何地方使用无线电发射设备请务必了解并遵守当地关于频率、功率和发射频谱的相关法规。享受技术乐趣的同时也要做一个有责任的无线电使用者。