输入输出与编程 / 测量方法发布 内容更新

ESP32 读电压:ADC 原始值、毫伏与三点测量方法

用受限电位器输入、GPIO1和32点采样窗口,区分12位raw与analogReadMilliVolts校准值。提供三点万用表比较步骤与空白记录表,不虚构实测误差。

读完能做什么
完成可复验的三点采样记录,正确计算与万用表读数的差值。
开始之前
先核对模块与电源清单;会使用万用表直流电压挡。
所需器材
10kΩ线性电位器(误差≤20%、≥0.1W、允许工作电压≥3.3V)、2.2kΩ ±5% 0.25W电阻、100nF ≥10V陶瓷电容、万用表与精度/量程说明、USB供电的参考开发板
版本组合
Arduino CLI:1.5.1Arduino-ESP32:3.3.12 · 94afccf35fb1e401facddbcf9e13bcf7c76a31d8参考硬件:ESP32-S3-DevKitC-1 v1.1 · WROOM-1-N8R8FQBN:esp32:esp32:esp32s3:FlashSize=8M,PSRAM=opi,FlashMode=qio,PartitionScheme=default_8MB,CDCOnBoot=default,USBMode=hwcdc
适用范围

官方ESP32-S3-DevKitC-1 v1.1、ESP32-S3-WROOM-1-N8R8;Arduino CLI 1.5.1、Arduino-ESP32 3.3.12;USB-to-UART口。

这篇验证到了哪一步

资料核对已通过
docs/esp32-evidence/programming.md#p05版本:Arduino-ESP32 3.3.12验证日期:
构建 / 配置已通过
docs/esp32-evidence/logs/esp32-adc-voltage-basics-esp32-adc-voltage-basics.log对象:esp32:esp32:esp32s3:FlashSize=8M,PSRAM=opi,FlashMode=qio,PartitionScheme=default_8MB,CDCOnBoot=default,USBMode=hwcdc版本:Arduino CLI 1.5.1 / core 3.3.12验证日期:
仿真不适用
本篇未运行仿真;外设/电气与实物行为按独立硬件步骤验收,没有仿真通过声明
本站实板待验证
本站未实板验证;正文提供可执行验收步骤

构建通过只说明指定环境中的代码或配置通过检查;实物功能、功耗和稳定性以对应的实板记录为准。

01 / 测量方法

先明确本篇交付的是可执行的测量方法

本篇保留计划ID P05与原slug,把题目明确为ADC三点测量方法。没有开发板与万用表的实际记录,就不能编一组“误差只有几毫伏”的结果。下载中提供采样器和空白measurements.csv,完成后你能对自己的板在明确条件下做比较。

我们只测由本板3V3经电阻与电位器产生的低电压,使用GPIO1的ADC1_CH0。芯片、衰减、输入范围和参考仪表都影响结果;“GPIO逻辑供电是3.3V”并不推出“ADC满量程正好是3.3V”。

做到这里,你应该看到
知道本篇没有本站测量结果,并明确要记录板型、输入点、参考表计与误差定义。

参考:[1] Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围[3] 乐鑫:ESP32-S3-DevKitC-1 v1.1,排针与RGB修订

02 / 测量方法

搭一个最大输入留余量的电位器电路

器材为10kΩ线性电位器、2.2kΩ电阻、100nF陶瓷电容和有量程/精度说明的万用表。3V3先经过2.2kΩ接电位器一端,电位器另一端接GND,滑动端接GPIO1(J3-4),100nF跨GPIO1和GND。表计直流电压挡并联在同一输入节点,红GPIO1、黑GND。

顶端名义电压约3.3×10/(10+2.2)=2.70V,低于S3在ADC_11db下文档给出的约3.1V可测上界。这个计算是设计估算,电阻误差、3V3实际值与接触都要考虑;连接ADC前先量滑端全程范围。不要将本电路直接接电池或5V外部信号。

这里使用分立元件而非未知模拟模块:电位器标称10kΩ、线性、总阻值误差不超过20%、额定功率至少0.1W、允许工作电压至少3.3V;串联电阻2.2kΩ、±5%、0.25W;电容100nF、耐压至少10V。购买时核对器件标注/厂家额定值,断电测总阻与滑动端后再连接。标称值不同就重新计算并实际测量输入范围,不能把2.70V当成保护钳位。

节点连接目的
3V32.2kΩ→电位器端点A压低名义输入上限
电位器端点BGND固定下端参考
滑端GPIO1(J3-4)ADC1_CH0采样
100nFGPIO1与GND之间减小输入高频扰动
万用表红GPIO1、黑GND同节点参考读数

参考:[1] Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围[3] 乐鑫:ESP32-S3-DevKitC-1 v1.1,排针与RGB修订

03 / 测量方法

raw、毫伏和校准分别回答不同问题

analogReadResolution(12)使返回码按12位表达,raw范围0–4095。raw是原始转换码,不能用raw/4095×3300当作可靠电压公式。analogReadMilliVolts通过core中的校准路径给出毫伏值,但仍会受输入和硬件误差影响,不是外部精密电压表。

本例先调用analogRead再调用analogReadMilliVolts,所以同一行的raw与mV不是同一个瞬间、同一次转换的两个表示。电位器固定在稳定输入,才适合比较各窗口均值;快速变化信号需要另行设计同步采样与带宽。

每20毫秒取一组,32组形成一窗,输出raw均值/最小/最大与mV均值。平均能观察随机波动,不能修复接地错误、饱和或系统偏差;raw min/max的跨度也不是准确度。

参考:[1] Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围[2] Arduino-ESP32 3.3.12:ADC采样与校准实现

04 / 测量方法

完整采样器与CSV输出

程序只用core内置ADC接口,没有第三方库。配置12位与ADC_11db后开始输出,约每0.64秒一窗,实际周期受循环与串口影响。它没有把任何预期读数写死,也没有在代码里加入未经验证的经验校正常数。

代码 / 配置
// SPDX-License-Identifier: MIT
#include <Arduino.h>
constexpr uint8_t ADC_PIN = 1;
constexpr uint16_t WINDOW = 32;
uint16_t count = 0, minRaw = 4095, maxRaw = 0;
uint32_t rawSum = 0, mvSum = 0, sampledAt = 0, windowId = 0;
void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  analogSetPinAttenuation(ADC_PIN, ADC_11db);
  Serial.println("P05 core=3.3.12 GPIO1 ADC1_CH0 12bit 11dB");
  Serial.println("window,raw_mean,raw_min,raw_max,mV_mean");
}
void loop() {
  const uint32_t now = millis();
  if (uint32_t(now - sampledAt) < 20) return;
  sampledAt = now;
  // Separate conversions: do not treat raw and mV as the same instant/sample.
  const uint16_t raw = analogRead(ADC_PIN);
  const uint32_t mv = analogReadMilliVolts(ADC_PIN);
  rawSum += raw;
  mvSum += mv;
  if (raw < minRaw) minRaw = raw;
  if (raw > maxRaw) maxRaw = raw;
  if (++count == WINDOW) {
    Serial.printf("%lu,%.2f,%u,%u,%.2f\n", (unsigned long)++windowId,
      rawSum / float(WINDOW), minRaw, maxRaw, mvSum / float(WINDOW));
    count = 0; rawSum = mvSum = 0; minRaw = 4095; maxRaw = 0;
  }
}

参考:[1] Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围[2] Arduino-ESP32 3.3.12:ADC采样与校准实现[4] Arduino:millis()返回类型与回绕

05 / 测量方法

用三个输入点和每点十窗完成比较

先记录DMM型号、量程、精度声明、开发板模组后缀、core版本、USB供电与环境。若表计精度来源不明,只能称为“与这台表比较”,不能声称可溯源校准。本文未提供实测数据,下载CSV仅有列名。

  1. 先将滑端调到表计约500mV,等待2秒稳定;记录表计实际值,不把500作为输入真值。
  2. 保留连续10个window的mV_mean、raw_mean、raw_min和raw_max;记下采样期间表计是否漂移。
  3. 同样采集约1500mV和2500mV两个输入点各10窗;每次调节后重新等待稳定。
  4. 对每点算10个mV_mean的均值和标准差,与同期DMM读数比较。差值Δ=Vadc−Vdmm,绝对差=|Δ|,相对差=Δ/Vdmm×100%。
  5. 先由项目需求定义允许差值,例如把±50mV作为一个拟定要求;这个数不是芯片保证或本站测量结论。不满足时先排输入稳定性、接地、衰减与参考表计,再考虑校正。
  6. 若拟合校正系数,另取未参与拟合的点验证;只对原三个点回算不能证明全量程精度。
记录列必须填入的内容
point/window真实点位与窗口号
dmm_model/range/accuracy型号、量程、精度来源
dmm_mV/adc_mV_mean同时段真实读数
raw_mean/min/max程序输出
supply_V/temperature_C/notes测量条件与异常
做到这里,你应该看到
三点各十窗有真实记录、仪表信息和计算过程后,才能报告这块板在这些条件下的比较差值。
06 / 测量方法

读数顶格、漂移和校准异常怎样处理

raw一直4095或接近上边界:先停止调高输入,量GPIO1对GND,检查是否误接3V3直通、滑端识别错误或衰减没设置。raw一直0时先量节点是否真的有电压,再查GPIO号与共地。不要用软件缩放掩盖饱和。

读数漂移先检查供电与导线接触,断电确认100nF和共地,固定旋钮后再采样。若raw有效但mV持续异常,保留启动与core错误日志,核对3.3.12的校准路径;不能擅自把异常值解释为有效0V。

断电恢复默认电阻/电位器电路,删除任何临时校正常数后复测。下一步学习I2C,让传感器自己给出数字数据;数字接口仍然要处理供电、地址与错误状态。

参考:[1] Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围[2] Arduino-ESP32 3.3.12:ADC采样与校准实现

BACK TO THE SOURCE

资料来源与版本说明

资料与固定版本源码核对;构建、仿真与实板为分开的验证维度。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。

  1. Arduino-ESP32 3.3.12:ADC返回值、分辨率、S3衰减范围
  2. Arduino-ESP32 3.3.12:ADC采样与校准实现
  3. 乐鑫:ESP32-S3-DevKitC-1 v1.1,排针与RGB修订
  4. Arduino:millis()返回类型与回绕