
1. 一块十几块钱的开发板怎么就被推上了SDR的牌桌第一次在社区里刷到“ESP32可以当SDR”这个说法的时候我的反应和大多数人一样这不扯吗。ESP32是一颗带Wi-Fi和蓝牙的MCU主频撑死240MHzADC采样率标称最高也就2Msps拿它去碰软件无线电听起来就像拿买菜车去跑拉力赛。但把帖子翻完、自己动手跑了一遍之后我确实在椅子上坐了好一会儿——不是因为它性能有多强而是因为它把“SDR入门”这件事的门槛从“先花几百块买接收机”直接砍到了“你抽屉里那块吃灰的开发板”。先把结论摆在前面免得有人抱着不切实际的期待ESP32做SDR做的是“窄带、低频、低速”的接收不是让你去收宽带信号或者做专业频谱监测。它的定位更像是一个“无线电信号感知玩具”加“教学平台”能让你用极低的成本理解IQ采样、混频、解调这一整套SDR的核心链路。适合谁适合想入门SDR但不想一上来就砸钱的人、适合玩ESP32想找点新花样的嵌入式玩家、也适合想给学生讲清楚“软件无线电到底怎么回事”的老师。如果你指望它替代RTL-SDR或者Airspy那还是趁早关掉这篇文章。这篇文章我会把整件事拆开讲为什么ESP32能沾上SDR的边、它的硬件到底卡在哪里、实际能收到什么、代码怎么写、踩过哪些坑。所有涉及具体参数的地方我都会给出计算过程涉及操作的地方我都会说明意图尽量让你看完能自己复现一遍。2. 先搞清楚ESP32到底凭什么能碰SDR2.1 SDR的最小必要条件是“可编程采样”不是“高性能”很多人对SDR有个误解觉得必须要有高采样率、高分辨率ADC才配叫SDR。其实SDRSoftware Defined Radio软件定义无线电的核心定义只有一条信号的调制解调尽量用软件完成而不是靠一堆硬件电路。只要你能拿到一段按时间排列的采样数据并且能在软件里对它做数学运算你就在做SDR了。从这个角度看ESP32其实满足最低门槛。它内部有SAR型ADC虽然指标寒酸但确实能按固定时间间隔采到电压值。你把这些电压值当成IQ信号或者更准确地说当成实信号存下来在芯片里或者传到电脑上做FFT、滤波、解调这条链路在概念上就是完整的SDR接收流程。区别只在于专业SDR的ADC是几百Msps、12bit以上而ESP32是2Msps、12bit但实际有效位数ENOB大概只有9到10位。所以“ESP32可以当SDR”这句话严格来说应该修正为ESP32可以作为一个极低成本的SDR接收前端完成窄带信号的采样和初步处理。这个修正很重要因为它决定了你后面所有的期待值和方案设计。2.2 关键硬件指标拆解哪些够用哪些是硬伤我把ESP32和一颗典型入门SDR芯片比如RTL2832U做个对照你一眼就能看出差距在哪指标ESP32经典款RTL2832U方案影响ADC采样率最高约2Msps最高2.4Msps以上可覆盖带宽差不太多但ESP32实际稳定采样率远低于标称ADC分辨率12bit标称ENOB约9-10bit8bitESP32理论动态范围略好调谐范围依赖外部混频本身无射频前端24MHz-1.7GHzESP32是硬伤需要外接电路处理能力240MHz双核无FPU加速FFT依赖PC处理ESP32只能做轻量处理成本十几到几十元几十到上百元ESP32胜看这张表就明白了ESP32做SDR最大的短板不是采样而是没有射频前端。它的ADC引脚直接接天线只能采到很低频的信号理论上几十kHz到几MHz实际受限于采样率和引脚特性。想收短波、FM广播这些必须外接混频器把高频信号搬移到低频这就把“低成本”的优势吃掉一部分了。但反过来说如果你只是想收LF/VLF频段比如长波授时信号、某些低频信标或者配合一个简单的直接变频前端收短波ESP32是完全能胜任的。这也是目前社区里大多数ESP32 SDR项目的实际玩法。2.3 为什么是现在火起来生态成熟度到了临界点这个玩法其实不是新东西几年前就有人试过。但为什么最近突然被翻出来讨论我的判断是三个条件同时满足了第一ESP-IDF和Arduino-ESP32的ADC驱动成熟了。早期ESP32的ADC被吐槽得厉害非线性、噪声大、Wi-Fi一开就飘。现在有了校准接口和DMA连续采样支持虽然还是不如专业ADC但至少能用了。第二I2SDMA连续采样的方案被验证可行。用I2S外设去驱动ADC做连续采样绕开CPU轮询能稳定跑到几百ksps到1Msps级别这是做SDR的前提。第三上位机软件生态现成。你不需要自己写频谱软件把IQ数据通过串口或者Wi-Fi传到电脑用现成的SDR软件比如基于Python的、或者通用的IQ处理工具就能看频谱、做解调。ESP32只负责采样和传输重活交给PC。这三个条件凑齐才让“ESP32当SDR”从一个段子变成了能跑通的项目。3. 方案选型三条路线选错了白折腾3.1 路线一纯ESP32直采只玩低频这是最简单的路线不需要任何外部射频电路。天线一根导线就行直接接到ESP32的ADC引脚比如GPIO34用I2S驱动ADC连续采样把数据传到电脑上看频谱。能收到什么说实话非常有限。ESP32的ADC输入带宽大概到几十kHz就开始衰减采样率就算跑到1Msps你看到的也主要是低频噪声和工频干扰。但这条路线有一个不可替代的价值它是理解SDR原理的最佳教学工具。你可以亲手看到采样率变化对频谱的影响、看到混叠现象、看到加窗和不加窗的区别。这些在专业SDR上反而不好观察因为前端太复杂了。我建议所有想认真学SDR的人都先用这条路线跑一遍。花不了半小时但能帮你把“采样率、奈奎斯特、混叠、FFT bin”这些概念从纸面变成眼睛能看到的东西。3.2 路线二外接混频前端收短波这是目前社区里最主流的玩法。用一个简单的混频器芯片比如NE612或者更现代的Tayloe检测器结构配合一个本振可以是ESP32自己产生的方波也可以是专用时钟芯片把短波信号搬移到ESP32能采的低频段。为什么选短波因为短波3-30MHz的信号相对容易接收天线要求不高而且内容丰富业余无线电、信标、数字模式等。更重要的是短波信号的带宽通常很窄几kHz正好匹配ESP32的处理能力。这条路线里本振的质量直接决定成败。ESP32的LEDC或者RMT外设可以产生方波本振但方波谐波多会引入大量杂散。我的经验是如果预算允许用一个专用的Si5351时钟芯片做本振效果会好很多。Si5351通过I2C控制ESP32驱动起来很方便频率稳定度和纯度都远超ESP32自己产生的方波。3.3 路线三ESP32只做数据搬运射频全靠外部这条路线本质上是把ESP32当成一个“带Wi-Fi的USB声卡”。外部用一个完整的射频前端比如直接变频接收机输出基带IQ信号ESP32只负责采样和通过网络传输。这条路线适合谁适合已经有射频前端、想加个网络传输功能的人。但说实话如果射频前端都做好了用ESP32做采样有点浪费——它的ADC指标配不上好的前端。所以这条路线我不太推荐除非你有特殊需求比如要做远程部署的接收节点。综合来看新手从路线一开始想深入玩短波走路线二路线三留给有特定需求的老手。下面我的实操部分主要围绕路线一和路线二展开。4. 实操从零跑通ESP32 SDR接收4.1 环境准备与开发框架选择先说开发环境。ESP32的开发框架主要有两个Arduino-ESP32和ESP-IDF。做SDR采样这件事我强烈建议用ESP-IDF原因有三第一I2SDMA的底层配置在IDF里更直接Arduino封装层有时候会挡住关键参数。第二IDF对中断和时序的控制更精确采样这种对时间敏感的任务差几个微秒结果就不一样。第三IDF的示例代码里有现成的I2S ADC采样例程改起来快。如果你实在不想装IDFArduino-ESP32也能做但要注意版本。建议用2.0.11或更高版本早期版本的I2S ADC驱动有bug采样会丢数据。安装方法这里不展开社区里教程很多核心就是开发板管理器地址填对然后选对芯片型号。装好之后先跑一个最简单的测试用ADC读一个引脚串口打印数值。这一步是为了确认你的板子和工具链没问题。别小看这一步我见过太多人直接上SDR代码结果卡在串口都打不开。4.2 用I2S驱动ADC连续采样的关键配置这是整个项目的技术核心。ESP32的ADC如果靠CPU轮询读采样率根本上不去而且时间间隔不均匀。正确做法是用I2S外设的DMA模式让ADC数据自动搬进内存缓冲区。关键配置参数如下以IDF为例i2s_config_t i2s_config { .mode I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, .sample_rate 1000000, // 目标采样率1Msps .bits_per_sample I2S_BITS_PER_SAMPLE_16BIT, .channel_format I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format I2S_COMM_FORMAT_STAND_I2S, .dma_buf_count 8, .dma_buf_len 1024, .use_apll true, // 关键用APLL保证采样时钟稳定 .intr_alloc_flags ESP_INTR_FLAG_LEVEL1 };这里有几个点必须解释清楚sample_rate设1Msps实际能跑到多少实测下来用APLL时钟源稳定跑到800ksps左右问题不大再往上丢数据概率明显增加。所以如果你看到别人说2Msps那多半是理论值或者短时间爆发。做SDR要的是连续稳定采样不是峰值。use_apll为什么关键APLL是音频锁相环它能提供一个比主时钟更干净的采样时钟。不用APLL的话采样时钟会有抖动反映到频谱上就是底噪抬高、杂散增多。这个参数一开频谱干净程度肉眼可见地提升。dma_buf_count和dma_buf_len怎么定这两个参数决定了缓冲区大小。buf_count乘buf_len就是总缓冲字节数。太小会丢数据太大延迟高。我的经验是8乘1024比较平衡对应16KB缓冲在1Msps下大概能缓冲16ms的数据足够CPU处理一轮。配置好之后调用i2s_driver_install和i2s_set_adc_mode然后就可以用i2s_read读数据了。读到的数据是原始ADC值需要做一步转换才能变成有意义的电压值。4.3 ADC数据校准不做这一步频谱全是假的ESP32的ADC有个著名的问题非线性。原始读数直接拿去做FFT你会看到一堆莫名其妙的谐波和杂散那不是信号是ADC自己的失真。解决办法是用ESP-IDF提供的校准接口。具体做法是esp_adc_cal_characteristics_t *adc_chars calloc(1, sizeof(esp_adc_cal_characteristics_t)); esp_adc_cal_value_t val_type esp_adc_cal_characterize( ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, adc_chars);然后在每次读到原始值后用esp_adc_cal_raw_to_voltage转成电压。这一步能把非线性误差压下去不少。但要注意校准只能改善不能根治。ESP32的ADC在接近0和接近满量程的地方仍然不准所以实际使用中建议把信号控制在量程的20%到80%之间。还有一个坑Wi-Fi一开ADC就飘。这是电源噪声耦合导致的。如果你用Wi-Fi传数据要么在采样时关掉Wi-Fi采完再开要么给ADC部分加独立的LDO供电和滤波。我试过在采样期间关Wi-Fi频谱底噪能降好几个dB。4.4 数据传到电脑串口还是Wi-Fi采样数据怎么送到电脑做后续处理有两条路串口传输的优点是简单可靠缺点是速度慢。115200波特率下每秒只能传约11KB数据对应1Msps、16bit采样的话连1%的数据都传不完。所以串口只适合低采样率场景比如几十ksps。Wi-Fi传输速度快得多TCP下轻松跑到几MB/s足够传1Msps的16bit数据2MB/s。但Wi-Fi的功耗和噪声是代价。我的做法是采样时关Wi-Fi采满一个缓冲区比如16KB后开Wi-Fi发出去发完再关。这样虽然不能连续实时但能保证采样质量。对于看频谱这种应用每秒更新几次足够了。如果你要做实时频谱那就得接受Wi-Fi噪声或者用有线以太网部分ESP32型号支持。以太网是折中方案速度快且噪声比Wi-Fi小。4.5 上位机端用Python快速搭一个频谱显示ESP32把数据传过来之后电脑端需要做FFT和显示。我用Python写了一个最简版本核心就几行import numpy as np import matplotlib.pyplot as plt def process_iq(samples, sample_rate): # samples是原始ADC值先去掉直流分量 samples samples - np.mean(samples) # 加汉宁窗减少频谱泄漏 window np.hanning(len(samples)) windowed samples * window # 做FFT fft_result np.fft.fft(windowed) fft_mag 20 * np.log10(np.abs(fft_result) 1e-10) # 生成频率轴 freqs np.fft.fftfreq(len(samples), 1/sample_rate) return freqs, fft_mag这段代码里去直流和加窗是两个不能省的步骤。不去直流频谱最左边会有一个巨大的峰把其他信号全压住。不加窗强信号的旁瓣会掩盖弱信号。汉宁窗是最常用的折中主瓣宽度和旁瓣抑制比较平衡。显示的时候把频率轴只取正半部分0到采样率的一半因为实信号的频谱是对称的看一半就够了。5. 实际能收到什么别抱幻想但有惊喜5.1 低频段工频、开关电源、长波信号在纯直采模式下你最先看到的肯定是50Hz工频及其谐波。这不是干扰这是“免费信号源”可以用来验证你的系统是否正常工作。如果连50Hz都看不到说明采样链路有问题。把天线加长一点能收到一些长波授时信号比如某些国家在60kHz附近发的授时信号。这些信号很强用一根几米长的导线就能收到。收到的时候你会看到一个稳定的、频率精确的窄带峰那种成就感还是挺足的。开关电源的干扰也很有意思。你会看到一堆间隔均匀的峰那是开关频率及其谐波。这个可以用来判断周围电磁环境也算实用。5.2 短波段配合混频前端后的实际表现接上混频前端之后短波段就打开了。我用Si5351做本振NE612做混频天线是一根20米长的偶极子条件有限的话一根长导线也行。实测能收到的信号类型业余无线电SSB语音在7MHz、14MHz等业余频段能清楚听到语音。ESP32的采样率足够覆盖SSB的3kHz带宽。等幅报CW窄带信号ESP32处理起来很轻松能听到清晰的滴答声。数字模式比如FT8这种窄带数字模式ESP32采到的数据传到电脑上用现成软件能解码。广播电台某些短波广播信号很强能收到。收不到什么宽带信号比如FM广播的200kHz带宽收不了因为ESP32的采样率和处理能力都不够。跳频信号也追不上因为它的调谐速度跟不上。5.3 一个容易被忽略的用途信号存在性检测如果你不追求解调只是想知道“某个频段有没有信号”ESP32其实很够用。它可以长时间监测一个频点检测能量超过阈值就报警。这种应用对采样率要求不高ESP32完全胜任而且功耗低可以电池供电长期部署。我做过一个简单的场强监测器ESP32每隔几秒采一次把能量值通过Wi-Fi发到服务器。用来监测某个频段是否被占用效果不错。6. 踩过的坑与排查技巧实录6.1 采样数据全是噪声或者全是零这是最常见的问题排查顺序如下现象可能原因排查方法全是零ADC引脚没接对或者I2S配置错误用万用表测引脚电压确认有信号全是噪声天线没接或者增益不够接一根长导线看50Hz工频是否出现数据跳变剧烈电源噪声或者Wi-Fi干扰关Wi-Fi再采换电池供电试试频谱有规律杂散ADC非线性或者采样时钟抖动开APLL做ADC校准我的经验是先确认能看到50Hz工频再往下做。如果连工频都看不到说明采样链路根本没通后面所有分析都是白费。6.2 采样率上不去一高就丢数据ESP32的I2S DMA不是无限快的。实测下来800ksps是个比较稳的上限。如果你设1Msps以上丢数据概率大增。解决办法降低采样率或者用双缓冲交替。双缓冲的意思是开两个DMA缓冲区一个在采的时候另一个在处理这样能提高有效吞吐。但实现起来复杂一些新手建议先把采样率降到500ksps稳定之后再往上试。还有一个隐藏问题串口打印会拖慢采样。如果你在采样循环里加printf采样率直接掉一半。正确做法是采样和打印分开采完一批再打印。6.3 频谱上出现莫名其妙的峰这些峰通常来自三个地方第一ADC谐波。如果输入信号太强ADC会产生谐波。解决方法是加衰减把信号控制在量程的50%以下。第二采样时钟泄漏。采样时钟的频率及其谐波会耦合到信号里。解决方法是开APLL并且做好电源滤波。第三混叠。如果输入信号频率超过采样率的一半会混叠到低频。解决方法是加抗混叠滤波器或者在混频前端就把带宽限制住。排查的时候可以改变采样率看峰是否移动。如果峰跟着采样率变那就是混叠或者时钟泄漏如果峰不动那就是真实信号或者ADC谐波。6.4 上位机收到的数据对不上有时候ESP32说采了1000个点电脑收到只有900个。这通常是传输丢包。串口传输的话检查波特率是否匹配、流控是否开启。Wi-Fi传输的话检查TCP缓冲区大小和发送节奏。我的做法是加一个简单的帧头和帧尾每包数据带上序号。电脑端检查序号连续性丢包就丢弃整包避免数据错位。这个机制虽然简单但能避免很多诡异问题。7. 这条路还能怎么走几个值得尝试的扩展方向7.1 用ESP32-S3或ESP32-C6试试经典ESP32的ADC确实拉胯但新款的ESP32-S3和C6在ADC上有所改进。S3的ADC线性度好一些C6支持更灵活的射频配置。如果你手头有这些板子值得试试。不过要注意不同型号的I2S ADC驱动可能有差异代码需要调整。7.2 加一个简单的抗混叠滤波器在ADC输入前加一个RC低通滤波器截止频率设在采样率的一半以下。这个滤波器成本几毛钱但能明显减少混叠。具体参数如果采样率500ksps截止频率设200kHz左右用1k电阻加1nF电容就能做到。7.3 把解调也放到ESP32上做目前大多数方案是把IQ数据传到电脑解调。但对于窄带信号比如CW或者窄带FSKESP32的处理能力其实够做简单解调。比如用Goertzel算法检测特定频率的能量或者做简单的包络检波。这样就能脱离电脑独立运行做成一个便携接收器。7.4 多板协同分布式接收ESP32便宜可以多买几块放在不同位置同时接收然后把数据汇总到一台服务器做相干处理或者分集接收。这个玩法有点进阶但成本很低适合想深入研究的人。8. 最后分享几个实操中总结的小技巧第一个技巧天线不用太讲究但地线要讲究。接收低频信号时地线质量比天线长度更重要。把ESP32的GND接到真正的大地比如水管或者接地棒底噪会明显下降。第二个技巧采样时把屏幕关掉。如果你用的是带屏幕的开发板屏幕刷新会产生噪声。采样期间关屏频谱会干净一些。第三个技巧用电池供电。USB供电的噪声比电池大得多。用一节18650电池供电频谱底噪能降好几个dB。这个提升比换天线还明显。第四个技巧别追求高采样率追求稳定采样率。500ksps稳定采样比1Msps丢一半数据有用得多。SDR里采样时间的均匀性比采样率更重要。第五个技巧先用已知信号源验证。拿一个信号发生器或者另一块ESP32产生方波输入已知频率看频谱上是否出现在正确位置。这一步能帮你排除大部分配置错误。这个玩法我断断续续折腾了几个月最大的感受是ESP32做SDR性能上确实寒酸但它把“软件无线电”从一门需要昂贵设备的专业手艺变成了一个周末就能上手的爱好。你不需要理解所有射频理论才能开始接一根线、跑一段代码、看到频谱上跳出一个峰这个过程本身就很有价值。至于它能走多远取决于你愿意往里投入多少时间——硬件是天花板但天花板之前还有很大的空间可以折腾。