
ADC(Analog-to-Digital Converter,模数转换器)是一种将连续变化的模拟信号(如电压)转换为离散的数字信号的电子元件。在嵌入式系统中,我们经常需要读取各种传感器(如温度传感器、光敏电阻、电位器等)的模拟输出,这些传感器输出的是连续变化的电压值,而微处理器只能处理数字信号(0 和 1 组成的二进制数据),因此需要通过 ADC 来完成这种转换。
ADC 的转换过程主要包括以下步骤:
采样:按固定时间间隔测量模拟信号的瞬时值
量化:将采样得到的模拟值转换为最接近的离散值(数字量)
编码:将离散值转换为二进制代码
树莓派 Pico 的 RP2040 芯片内置了 3 个 12 位 ADC 通道,这意味着它可以将 0-3.3V 的模拟电压转换为 0-4095(2¹²-1)的数字值,转换精度为 3.3V/4096≈0.805mV
要运行此示例,你需要:一个 10kΩ 电位器,将电位器的三个引脚分别连接到:
中间引脚 → GP26
一端引脚 → 3.3V
另一端引脚 → GND
当你旋转电位器时,会看到打印的 ADC 值和电压值随之变化,这直观地展示了模拟信号到数字信号的转换过程。
注意事项:pico引脚的最大耐受电压为 3.3V。所以如果接传感器供电最好采用3.3V,千万不要直接连接到pico的5V针脚,如果接5v需要通过电阻分压电路(如10kΩ和20kΩ电阻)降压至 3.3V 以内。不然会损坏pico主板
下面是一个使用树莓派 Pico 读取电位器(可变电阻)值的示例,电位器可以提供 0-3.3V 的可变电压,适合演示 ADC 功能。
from machine import Pin, ADC
import time
# 初始化ADC,连接到GP26引脚(ADC0)
adc = ADC(Pin(26))
while True:
# 读取ADC值(0-4095)
adc_value = adc.read_u16() >> 4 # read_u16()返回0-65535,右移4位得到0-4095
# 转换为电压值(0-3.3V)
voltage = adc_value * 3.3 / 4095
# 打印结果
print(f"ADC值: {adc_value}, 电压: {voltage:.2f}V")
# 延迟500ms
time.sleep(0.5)首先导入必要的模块:Pin用于引脚配置,ADC用于 ADC 操作,time用于延时
创建 ADC 对象,指定连接到 GP26 引脚(ADC0 通道)
在循环中:
使用read_u16()读取 16 位 ADC 值(0-65535),然后右移 4 位转换为 12 位值(0-4095)
将 ADC 值转换为对应的电压值(0-3.3V)
打印 ADC 值和对应的电压值
延时 500 毫秒后重复
以下是基于 Arduino IDE 开发环境的 ESP32 读取 AO(模拟量输出)信号的标准示例代码。ESP32 内置了 12 位的 ADC(模数转换器),默认读取的原始值为 0 ~ 4095(对应 0V ~ 3.3V)
// 定义 AO 模拟量输入引脚(推荐使用 ADC1 对应的引脚,如 GPIO 32, 33, 34, 35, 36, 39)
const int ANALOG_PIN = 34;
void setup() {
// 初始化串口通信,波特率设置为 115200
Serial.begin(115200);
// 设置模拟引脚模式为输入
pinMode(ANALOG_PIN, INPUT);
// (可选)配置 ADC 衰减,默认为 ADC_11db,可测量范围约为 0~3.3V
// analogSetPinAttenuation(ANALOG_PIN, ADC_11db);
// (可选)设置 ADC 分辨率为 12 位(0 ~ 4095)
// analogReadResolution(12);
}
void loop() {
// 1. 读取原始模拟量数值 (0 - 4095)
int rawValue = analogRead(ANALOG_PIN);
// 2. 读取校准后的实际电压值 (单位:毫伏 mV),并转换为伏特 (V)
// analogReadMilliVolts() 会自动根据 ESP32 的出厂校准参数优化精度
float voltage = analogReadMilliVolts(ANALOG_PIN) / 1000.0;
// 3. 打印数据到串口监视器
Serial.print("原始 ADC 值: ");
Serial.print(rawValue);
Serial.print(" | 实际电压: ");
Serial.print(voltage, 3); // 保留 3 位小数
Serial.println(" V");
// 延时 500 毫秒后再次采集
delay(500);
}引脚选择(重要):推荐使用 ADC1 引脚: GPIO 32, 33, 34, 35, 36, 39。
避免使用 ADC2 引脚: GPIO 0, 2, 4, 12, 13, 14, 15, 25, 26, 27 在开启 Wi-Fi 时会被占用,导致 analogRead() 无法正常读取。
输入引脚: GPIO 34, 35, 36, 39 仅支持输入,无内部上下拉电阻,非常适合连接外部传感器 AO 口。
电压范围:ESP32 引脚的最大耐受电压为 3.3V。所以如果接传感器供电最好采用3.3V,千万不要直接连接到 ESP32的5V针脚,如果接5v需要通过电阻分压电路(如10kΩ和20kΩ电阻)降压至 3.3V 以内。不然会损坏ESP32主板
提高测量精度:
使用 analogReadMilliVolts() 比单纯通过 (rawValue / 4095.0) * 3.3 计算要精准得多,因为它读取了 ESP32 芯片内部存储的 ADC 参考电压校准数据(eFuse)。
如果测量数据抖动较大,可以在采样时对多个值取平均数(例如连续读取 10 次取平均值),或在 AO 信号引脚与 GND 之间并联一个0.1μF的去耦电容。