模拟输入
1. 模拟信号
模拟信号是一种在一定范围内可以连续变化的信号。
比如调光灯旋钮,可以平滑地调节灯的亮度,从完全熄灭到最亮,中间有无数个亮度级别。这个亮度调节的过程就是模拟的。而数字信号就像普通电灯开关,只有“开”和“关”。
现实世界中,像温度、光线强度、声音大小等许多物理量都是模拟的,它们的变化是连续而平滑的。
对于 ESP32,若要测量连续变化的信号(例如读取电位器、传感器的数值),仅用 HIGH
或 LOW
两种数字状态是无法实现的。此时,就需要使用 ADC。
-
ADC(Analog-to-Digital Converter, 模数转换器):一种能将连续的模拟电压信号(例如 0V ~ 3.3V)转换为 ESP32 可处理的数字值的设备。
简单来说,ADC 就像一把将 0~3.3V 之间的电压切分成很多“刻度”的尺子,让每个电压范围都对应一个具体的数字。ADC 能将电压细分成多少个等级,这个能力就叫做分辨率。分辨率越高,能检测的电压变化就越细致。
ESP32 的 ADC 通常是 12 位的,也就是一共可以分成 2¹²(= 4096) 个等级。因此,ADC 的读数范围是 0 ~ 4095。
- 输入电压为 0V,ADC 读数约等于 0。
- 当输入电压从 0V 连续变化到 3.3V 时,ADC 读数会相应地从 0 连续变化到 4095。

这样,ESP32 程序就可以通过 analogRead()
得到 0~4095 之间的整数,这个数值直接对应了输入引脚上的电压大小。
并不是所有 ESP32 引脚都支持模拟输入。需要查询对应开发板的引脚图或者芯片的手册,查找标有“ADC”的引脚作为模拟输入使用。
建议优先选择 ADC1 通道的引脚,以避免与其他功能冲突。
2. 搭建电路
需要使用的器件有:
- 电位器 * 1
- 面包板 * 1
- 导线
- ESP32 开发板
ESP32-S3-Zero 引脚图

电路解析
让我们理解一下这个模拟信号读取电路是如何工作的:
-
电位器的连接:
- VCC 引脚:连接到 ESP32 的 3.3V,提供电位器工作电压
- GND 引脚:连接到 ESP32 的 GND,形成电路回路
- 信号引脚(中间):连接到 ESP32 的 GPIO7(ADC 引脚),输出 0V~3.3V 之间的模拟电压
-
电位器工作原理:
- 电位器内部是一个可变电阻,通过旋转可以改变阻值
- 旋转电位器旋钮时,信号引脚的输出电压会在 0V 到 3.3V 之间连续变化
- 完全逆时针:输出接近 0V
- 完全顺时针:输出接近 3.3V
3. 代码
const int potentiometerPin = 7; // 定义电位器连接的引脚
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率 9600
}
void loop() {
int analogValue = analogRead(potentiometerPin); // 读取电位器模拟值 (0-4095)
int analogVolts = analogReadMilliVolts(potentiometerPin); // 读取引脚上的电压值,单位是毫伏 (mV)
// 打印第一个标签和数值
Serial.print("ADC_Value:");
Serial.print(analogValue);
// 打印分隔符
Serial.print(",");
// 打印第二个标签和数值,并用 println() 结束
Serial.print("Voltage_mV:");
Serial.println(analogVolts);
delay(100); // 延时 0.1 秒,避免串口刷屏太快
}
运行结果:
将代码烧录到 ESP32 开发板后,打开串口监视器即可看到持续显示的数值。转动电位器时,数值会相应变化:电位器转到一端时数值为 0,转到另一端时数值为 4095。
-
串口监视器:
-
串口绘图仪:
你可能会发现,当输入电压达到约 3.1V 时,analogRead()
的读数就已经达到 4095,而不是在 3.3V 时。
这是 ESP32 ADC 的一个设计特性。其内部核心电路能直接处理的电压范围有限,因此它使用了一个名为衰减器 (Attenuator) 的内部模块来扩展可测量的电压范围。
在 Arduino 环境下,默认会启用一个能测量最高电压的衰减选项 (ADC_ATTEN_DB_11
)。根据官方文档,此设置下 ESP32 S3 ADC 可靠测量上限约为 3.1V。(注意:不同芯片在不同的衰减选项下,可测量的输入电压范围是不同的。查看 此表。)
因此,当输入电压超过 3.1V 时,读数就会“饱和”,即保持在最大值 4095。
对于读取 0%到 100%的应用,这个默认设置足够。如果需要优化特定电压范围精度,可以学习如何设置不同衰减等级。详情请参阅 官方文档中关于 analogSetAttenuation 的说明。
代码解析
-
analogRead(potentiometerPin)
读取指定引脚上的模拟电压值。返回 0 ~ 4095 之间的整数,代表当前滑动端电压在 0V ~ 3.3V 这个范围内的位置。
备注在调用
analogRead()
前,不需要使用pinMode()
定义引脚。 -
analogReadMilliVolts(potentiometerPin)
这是一个 ESP32 特有函数。它同样读取指定引脚的模拟信号,但直接将其转换为以毫伏(mV)为单位的电压值并返回。并且其内部实现还包含校准,让读数更准确。
-
串口输出与绘图仪格式
// 打印第一个标签和数值
Serial.print("ADC_Value:");
Serial.print(analogValue);
// 打印分隔符
Serial.print(",");
// 打印第二个标签和数值,并用 println() 结束
Serial.print("Voltage_mV:");
Serial.println(analogVolts);这段代码用于按照特定格式通过串口发送采集到的数据。这种格式 不仅方便在串口监视器中阅读,更重要的是能被 Arduino IDE 的串口绘图仪识别并绘制成曲线图。
让我们对照下图来解析这个格式的构成:
-
标签和数值: 每个数据由标签和数值组成,并用冒号 (:) 分隔。这有助于在绘图仪的图例中显示名称。
-
数据分隔符: 多个数据之间用数据分隔符(如逗号
,
、空格\t
)隔开。这是告诉绘图仪“一个数据结束,下一个开始”的关键信号。 -
换行符: 使用
Serial.println()
在所有数据输出后添加换行符。这个换行符是“记录结束”的标志,告诉绘图仪这一时间点的所有数据已发送完毕,可以进行绘制了。
最终,串口监视器中每行会显示类似
ADC_Value:2048,Voltage_mV:1650
的格式。在串口绘图仪中,你会看到两条分别代表 ADC 原始值和电压值的曲线。 -
4. 拓展:减少噪声
当你停止转动电位器时,你可能会发现,ADC 读数并不会稳定地停留在某一个值,而是在小范围内持续跳动,有时甚至会出现较大的毛刺。
这种现象通常是由噪声引起的。ESP32 的 ADC 对电源噪声和外部环境的电磁干扰比较敏感。
要减少噪声的影响,通常有两种方法:
-
硬件滤波:在 ADC 输入引脚和 GND 之间并联一个小的旁路电容(例如 100nF 的陶瓷电容),可以有效滤除高频噪声。
-
软件滤波:在代码中进行多次采样后取平均值。例如,连续读取 10 次 ADC 值,然后将它们的总和除以 10,得到一个更平滑、更稳定的结果。
在大多数要求不高的应用中,轻微的跳动可以忽略。但当你需要高精度读数时,可以尝试使用上述方法。