调试信号、看 PWM 波形、观察传感器输出,是嵌入式开发里非常常见的需求。专业示波器并不便宜,对于很多入门玩家和验证场景来说,用 ESP32-C3 做一台“WiFi 无线网页示波器”是很实用的折中方案。
这篇文章会从方案选型、硬件接线、ADC 采样原理讲到完整代码实现,最后形成一个能通过浏览器查看实时波形的 ESP32-C3 示波器。整个过程不依赖昂贵的外设,适合正在学习单片机和信号采集的同学一步步跟着复现。
1. 用 ESP32-C3 做示波器的整体思路
1.1 什么是低成本示波器
示波器的本质是“把电压随时间变化的曲线画出来”。专业示波器内部包含模拟前端、高速 ADC、大容量存储、触发电路和显示系统,所以价格高。而嵌入式 DIY 示波器,通常只解决其中一部分问题:
- 用单片机的内置 ADC 读取电压值;
- 以一定采样间隔连续读取一批数据;
- 将数据通过串口、WiFi 或屏幕显示出来。
ESP32-C3 是一款内置 RISC-V 内核、支持 WiFi 和 BLE 的低成本芯片,价格比传统 ESP32 更亲民,主频最高可达 160 MHz,带 12 位 SAR ADC。用它做示波器,主要优势不是精度和带宽,而是开发门槛低、网络功能强、能快速把采集结果显示在手机或电脑浏览器上。
1.2 显示方案的选型对比
很多入门项目会把示波器做成“单片机 + OLED/TFT 屏”,但屏幕小、刷新慢,而且画波形时还要处理图形库。这里采用“ESP32-C3 采集 + WiFi 传输 + 网页 Canvas 绘制”的方式,有几个明显好处:
| 方案 | 显示效果 | 实现难度 | 适用场景 |
|---|---|---|---|
| OLED 屏显示 | 显示区域小,刷新率低 | 中 | 简单电压表、迷你演示 |
| TFT 屏显示 | 相对直观,但要驱动屏幕 | 较高 | 手持小仪器 |
| 网页 Canvas 显示 | 屏幕大,交互方便,无需额外硬件 | 中 | 低频波形分析、教学实验 |
| 串口上位机 | 可以保存数据,但依赖 PC 软件 | 中 | 上位机数据采集系统 |
网页方案还有一个额外好处:后续想加按钮、输入框、自动缩放、数据导出,只需要改前端页面,不用反复改单片机 UI。
1.3 ESP32-C3 适合测什么信号
由于 ESP32-C3 内置 ADC 的采样能力和精度有限,这个项目定位是“低压低频虚拟示波器”,比较适合测量:
- 0~3.1 V 左右的正电压波形;
- PWM 输出、方波信号;
- 低频正弦波、三角波;
- 传感器输出电压变化;
- 音频经过偏置处理后的交流波形。
需要注意的是,不要直接拿它去测量 220 V 市电或任何超过芯片输入电压范围的信号,否则会损坏开发板。如果一定要测量更高电压,必须先用分压电阻或隔离电路把电压降到安全范围。
1.4 本项目功能规划
最终要实现的功能包括:
- ESP32-C3 以 STA 模式连接路由器;
- 提供 HTTP 网页,浏览器打开 IP 后可以看到波形界面;
- 提供 WebSocket 服务,网页按钮触发一次数据采集;
- 可选软件触发,超过设定阈值后开始采样;
- 把采样点电压值和平均采样间隔发送回浏览器;
- 前端 Canvas 自动缩放并绘制波形。
整个项目最容易踩坑的反而不是代码,而是电源、共地、ADC 引脚选择和电压输入范围。下面会从这几个关键点讲起。
2. 核心概念:ADC、分辨率、采样率与触发
2.1 ADC 采样原理
ADC(Analog-to-Digital Converter,模数转换器)负责把模拟电压转换成数字量。ESP32-C3 内置 SAR ADC,每次转换时比较输入电压和一个参考电压,最终输出一个整数值。
在 Arduino 环境中,读取一个引脚的模拟电压通常就一行:
int raw = analogRead(ADC_PIN);raw 的数值范围取决于 ADC 的分辨率。如果设置为 12 位,那么理论上读取结果在 0~4095 之间。电压越高,raw 越大。
2.2 分辨率与电压换算
12 位分辨率意味着满量程被分成2^12 = 4096个格。假设满量程电压约为 3.1 V,那么一个 LSB 对应的电压为:
3.1V / 4095 ≈ 0.000757V在代码中换算成电压:
float voltage = raw * 3.1f / 4095.0f;这里的 3.1 V 不是所有板子都严格一致,因为 ADC 参考电压、衰减配置、芯片批次都会影响结果。所以这个值通常只是“软件量程”,严谨的做法是接一个已知电压做校准,或者用万用表比对。
2.3 采样率为什么重要
示波器要还原一个波形,需要在一个周期内采足够多的点。根据奈奎斯特采样定理,采样频率至少要高于信号最高频率的两倍,实际工程中通常要求 5~10 倍以上。
举个例子,如果要观察 1 kHz 的正弦波,一个周期是 1 ms。假设一个周期想采 50 个点,那么采样间隔需要达到:
1000us / 50 = 20us也就是约 50 kHz 的采样率。
ESP32-C3 在 Arduino 环境下使用analogRead()连续读取,实际采样间隔会受 CPU 频率、GPIO 配置、WiFi 任务调度等多方面影响,并不是一个稳定值。为了不误导读者,本项目的代码在每次采集时都通过micros()记录实际耗时,然后在网页端显示真实平均采样间隔。
2.4 触发功能的作用
无触发的示波器,每次只是从头到尾随机记录一段波形。当信号是周期性波形时,你会发现波形在屏幕上乱跑,很难稳定观察。
触发功能是让采集过程等待一个条件满足后再开始。最常见的是“上升沿触发”:当电压从低于阈值变成高于阈值时,才开始采集采样点。这样每次采集都从信号同一个相位开始,显示出来的波形就会比较稳定。
本项目使用软件方式做触发,本质上是在采样前不断读 ADC,直到当前值大于阈值。优点是可以直观理解触发原理,缺点是实时性不如硬件比较器,后续要提升性能可以扩展 external trigger 电路。
3. 硬件准备与接线
3.1 元器件清单
在做这个项目前,建议准备以下材料:
| 序号 | 材料 | 数量 | 用途 |
|---|---|---|---|
| 1 | ESP32-C3 开发板 | 1 块 | 主控和 WiFi |
| 2 | USB 数据线 | 1 根 | 供电和下载程序 |
| 3 | 面包板 | 1 块 |