Arduino ESP32 ADC功能介绍以及模拟量信号读取示例


这篇文章展示如何使用Arduino IDE读取与ESP32模拟输入。模拟读数对于读出可变电阻(如电位器或模拟传感器)的值很有用。

ESP32ADC连续采集电压不准 esp32 模拟量采集_嵌入式硬件

ADC引脚

  • ADC1:

8通道:GPIO32 - GPIO39

  • ADC2:

10个通道:GPIO0、GPIO2、GPIO4、GPIO12-GPIO15、GOIO25-GPIO27

typedef enum {
    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO37 */
    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO38 */
    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO39 */
    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO32 */
    ADC1_CHANNEL_5,     /*!< ADC1 channel 5 is GPIO33 */
    ADC1_CHANNEL_6,     /*!< ADC1 channel 6 is GPIO34 */
    ADC1_CHANNEL_7,     /*!< ADC1 channel 7 is GPIO35 */
    ADC1_CHANNEL_MAX,
} adc1_channel_t;

typedef enum {
    ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 */
    ADC2_CHANNEL_1,     /*!< ADC2 channel 1 is GPIO0 */
    ADC2_CHANNEL_2,     /*!< ADC2 channel 2 is GPIO2 */
    ADC2_CHANNEL_3,     /*!< ADC2 channel 3 is GPIO15 */
    ADC2_CHANNEL_4,     /*!< ADC2 channel 4 is GPIO13 */
    ADC2_CHANNEL_5,     /*!< ADC2 channel 5 is GPIO12 */
    ADC2_CHANNEL_6,     /*!< ADC2 channel 6 is GPIO14 */
    ADC2_CHANNEL_7,     /*!< ADC2 channel 7 is GPIO27 */
    ADC2_CHANNEL_8,     /*!< ADC2 channel 8 is GPIO25 */
    ADC2_CHANNEL_9,     /*!< ADC2 channel 9 is GPIO26 */
    ADC2_CHANNEL_MAX,
} adc2_channel_t;

使用ESP32读取模拟输入就像使用analogRead(GPIO)函数一样简单,它接受要读取的GPIO作为参数。

ADC2使用限制说明

  • Wi-Fi 驱动程序使用了 ADC2。因此,应用程序只能在未启动 Wi-Fi 驱动程序时使用 ADC2。
  • 有些 ADC2 引脚用作捆扎引脚(GPIO 0,2,15),因此无法自由使用。
  • ESP32 DevKitC型号 : 由于外部自动编程电路,无法使用 GPIO 0。
  • ESP-WROVER-KIT型号 : GPIO 0, 2, 4 和 15 由于不同用途的外部连接而无法使用。

ADC 采样模式

每个 ADC 单元支持两种工作模式,ADC 单次采样模式和ADC连续采样(DMA)模式。

  • ADC 单次采样模式适用于低频采样操作。
  • ADC 连续采样(DMA)模式适用于高频连续采样动作。

衰减倍数

  • 不同的衰减倍数对应不同的检测电压范围。
ADC的默认满量程电压为1.1V。要读取更高的电压(最高为引脚最大电压,通常为3.3V),则需要将该ADC通道的信号衰减设置为> 0dB。

ESP32ADC连续采集电压不准 esp32 模拟量采集_嵌入式硬件_02

  • 当VDD_A为3.3V时:

0dB衰减(ADC_ATTEN_0db)表示参考电压为1.1V
2.5dB衰减(ADC_ATTEN_2_5db)表示参考电压为1.5V
6dB衰减(ADC_ATTEN_6db)表示参考电压为2.2V
11dB衰减(ADC_ATTEN_11db)表示参考电压为3.9V

Arduino ESP32 核心库有关ADC库函数

ESP32ADC连续采集电压不准 esp32 模拟量采集_模拟输入_03

  • esp32-hal-adc.h
#ifndef MAIN_ESP32_HAL_ADC_H_
#define MAIN_ESP32_HAL_ADC_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "esp32-hal.h"
/*
衰减倍数
0dB衰减(ADC_ATTEN_0db)表示参考电压为1.1V
2.5dB衰减(ADC_ATTEN_2_5db)表示参考电压为1.5V
6dB衰减(ADC_ATTEN_6db)表示参考电压为2.2V
11dB衰减(ADC_ATTEN_11db)表示参考电压为3.9V
*/
typedef enum {
    ADC_0db,
    ADC_2_5db,
    ADC_6db,
    ADC_11db
} adc_attenuation_t;

/*
 * 获取引脚的ADC值
 * */
uint16_t analogRead(uint8_t pin);

/*
*设置analogRead返回值的分辨率。缺省值是12位(0 ~ 4096)。
*如果在9和12之间,它将等于设置的硬件分辨率,否则值将被移动。
*范围为1 - 16
 *
 * 注:兼容Arduino SAM
 */
void analogReadResolution(uint8_t bits);

/*
*设置示例位和读取分辨率
*默认为12bit (0 - 4095)
*范围是9 - 12
 * */
void analogSetWidth(uint8_t bits);

/*
*设置ADC时钟的分压器。
*默认值为1
*取值范围为1 - 255
 * */
void analogSetClockDiv(uint8_t clockDiv);

/*
 * Set the attenuation for all channels
 * Default is 11db
 * */
void analogSetAttenuation(adc_attenuation_t attenuation);

/*
*设置所有通道的衰减
*默认为11db
 * */
void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);

/*
 * 获取霍尔传感器的值(无LNA)
*	连接到引脚36(SVP)和引脚39(SVN)
 * */
int hallRead();

/*
 *将引脚连接到ADC(也将清除任何其他模拟模式,可以打开)
 * */
bool adcAttachPin(uint8_t pin);

/*设置引脚用于ADC校准,如果esp还没有校准(25、26或27)
 * Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27)
 * */
void analogSetVRefPin(uint8_t pin);

/*获取引脚的毫伏值
 * Get MilliVolts value for pin
 * */
uint32_t analogReadMilliVolts(uint8_t pin);

#ifdef __cplusplus
}
#endif

#endif /* MAIN_ESP32_HAL_ADC_H_ */

ESP32模拟输入(ADC)

用ESP32读取模拟值意味着你可以测量0 V到3.3 V之间的变化电压等级。然后将测量的电压赋给0到4095之间的一个值,其中0 V对应0,3.3 V对应4095。0 V到3.3 V之间的任何电压都将给出两者之间的相应值。

ESP32ADC连续采集电压不准 esp32 模拟量采集_嵌入式硬件_04

ADC是非线性的值

理想情况下,当使用ESP32 ADC引脚时,你会期望线性行为。然而,这并没有发生。你会得到如下图所示的行为:

ESP32ADC连续采集电压不准 esp32 模拟量采集_模拟输入_05

这种行为意味着你的ESP32无法区分3.3 V和3.2 V。你会得到相同的电压值:4095。
同样的情况发生在非常低的电压值:对于0 V和0.1 V,你将得到相同的值:0。
在使用ESP32 ADC引脚时,您需要记住这一点。

analogRead()

使用Arduino IDE读取ESP32模拟输入就像使用analogRead()函数一样简单。它接受你想要读取的GPIO作为参数:

analogRead(GPIO);
  • ESP32支持18个不同通道的测量。在DEVKIT V1 DOIT板(30 gpio版本)中只有15个可用。

其他相关的功能

  • analogReadResolution(resolution):设置样本位和分辨率。它可以是一个介于9(0 - 511)和12位(0 - 4095)之间的值。默认是12位分辨率。
  • analogSetWidth(width):设置样本位和分辨率。它可以是一个介于9(0 - 511)和12位(0 - 4095)之间的值。默认是12位分辨率。
  • analogSetCycles(cycles):设置每个样本的循环次数。默认是8。取值范围:1 ~ 255。
  • analogSetSamples(samples):设置范围内的样本数量。默认为1个样本。它有增加灵敏度的作用。
  • analogSetClockDiv(attenuation):设置ADC时钟的分压器。默认值为1。取值范围:1 ~ 255。
  • analogSetAttenuation(attenuation):设置所有ADC引脚的输入衰减。默认是ADC_11db。其他取值:

ADC_0db: 集没有衰减。ADC可以测量大约800mv (1V输入= ADC读数1088)。
ADC_2_5db: ADC的输入电压将被衰减,扩展测量范围至约。1100 mV。(1V输入= ADC读数3722)。
ADC_6db: ADC的输入电压将被衰减,扩展测量范围至约。1350 mV。(1V输入= ADC读数3033)。
ADC_11db: ADC的输入电压将被衰减,扩展测量范围至约。2600 mV。(1V输入= ADC读数1575)。

  • analogSetPinAttenuation(pin, attenuation):设置指定引脚的输入衰减。默认是ADC_11db。衰减值与前一个函数相同。
  • adcAttachPin(pin):附加一个引脚到ADC(也清除任何其他模拟模式可能是on)。返回TRUE或FALSE结果。
  • adcStart(pin), adcBusy(pin)resultadcEnd(pin):在附加引脚的总线上启动ADC转换。检查引脚的ADC总线上的转换是否正在运行(返回TRUEFALSE)。获取转换的结果:返回16位整数。

接线图

ESP32ADC连续采集电压不准 esp32 模拟量采集_ESP32ADC连续采集电压不准_06

ESP32ADC连续采集电压不准 esp32 模拟量采集_ESP32读取模拟量_07

实例代码

// 电位器连接到GPIO 34(模拟ADC1_CH6)
const int potPin = 34;

// 用于存储电位器值的变量
int potValue = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  // 读取电位计值
  potValue = analogRead(potPin);
  Serial.println(potValue);
  delay(500);
}
  • 串口打印读取定位器的数值(得到的最大值是4095,最小值是0。)