ESP32學(xué)習(xí)筆記(22)——ADC接口使用

一、概述

ESP32 集成了 2 個(gè) 12 位逐次逼近模數(shù)轉(zhuǎn)換器 (SARADC),支持 18 個(gè)測(cè)量通道(模擬使能引腳)。

支持以下通道:
ADC1:

  • 8通道:GPIO32 - GPIO39

ADC2:

  • 10個(gè)通道:GPIO0、GPIO2、GPIO4、GPIO12-GPIO15、GOIO25-GPIO27

ESP-IDF 編程指南——ADC

1.1 ADC限制

  • Wi-Fi 驅(qū)動(dòng)程序使用了 ADC2。因此,應(yīng)用程序只能在未啟動(dòng) Wi-Fi 驅(qū)動(dòng)程序時(shí)使用 ADC2。
  • 某些 ADC2 引腳用作捆扎引腳(GPIO 0,2,15),因此無法自由使用。
    ESP32 DevKitC : 由于外部自動(dòng)編程電路,無法使用 GPIO 0。
    ESP-WROVER-KIT : GPIO 0, 2, 4 和 15 由于不同用途的外部連接而無法使用。

1.2 ADC 采樣模式

每個(gè) ADC 單元支持兩種工作模式,ADC 單次采樣模式和ADC連續(xù)采樣(DMA)模式。

  • ADC 單次采樣模式適用于低頻采樣操作。
  • ADC 連續(xù)采樣(DMA)模式適用于高頻連續(xù)采樣動(dòng)作。

二、API說明

以下 ADC 接口位于 driver/esp32/include/driver/adc.h 、 driver/include/driver/adc_common.hesp_adc_cal/include/esp_adc_cal.h。

2.1 adc1_config_width

2.2 adc1_config_channel_atten

2.3 adc1_get_raw

2.4 esp_adc_cal_check_efuse

2.5 esp_adc_cal_characterize

2.6 esp_adc_cal_raw_to_voltage

三、編程流程

3.1 設(shè)置精度、衰減倍數(shù)和通道引腳

ADC 應(yīng)該在讀取之前配置。

  • 精度
    ESP32的內(nèi)置12位ADC可以在9位到12位的精度之間調(diào)整。
typedef enum {
    ADC_WIDTH_BIT_9  = 0, /*!< ADC capture width is 9Bit*/
    ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit*/
    ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit*/
    ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit*/
    ADC_WIDTH_MAX,
} adc_bits_width_t;
  • 衰減倍數(shù)
    不同的衰減倍數(shù)對(duì)應(yīng)不同的檢測(cè)電壓范圍。

    ADC的默認(rèn)滿量程電壓為1.1V。要讀取更高的電壓(最高為引腳最大電壓,通常為3.3V),則需要將該ADC通道的信號(hào)衰減設(shè)置為> 0dB。

    當(dāng)VDD_A為3.3V時(shí):

    • 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_ATTEN_DB_0   = 0,  /*!<No input attenumation, ADC can measure up to approx. 800 mV. */
    ADC_ATTEN_DB_2_5 = 1,  /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to approx. 1100 mV. */
    ADC_ATTEN_DB_6   = 2,  /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to  approx. 1350 mV. */
    ADC_ATTEN_DB_11  = 3,  /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to  approx. 2600 mV. */
    ADC_ATTEN_MAX,
} adc_atten_t;
  • 通道引腳
    兩個(gè)12位的ADC,其中ADC1(8個(gè)通道,連接到GPIO 32-39)和ADC2(10個(gè)通道,連接到GPIO 0、2、4、12-15和25-27)。
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;

3.2 讀取轉(zhuǎn)換結(jié)果

adc1_get_raw()和讀取 ADC 轉(zhuǎn)換結(jié)果adc2_get_raw()。ADC2 的讀取寬度應(yīng)設(shè)置為參數(shù)adc2_get_raw()而不是在配置函數(shù)中。

也可以通過調(diào)用專用函數(shù)通過 ADC1 讀取內(nèi)部霍爾效應(yīng)傳感器hall_sensor_read()。請(qǐng)注意,即使霍爾傳感器也是 ESP32 內(nèi)部的,從它讀取使用 ADC1 的通道 0 和 3(GPIO 36 和 39)。不要將任何其他東西連接到這些引腳,也不要更改它們的配置。否則可能會(huì)影響來自傳感器的低值信號(hào)的測(cè)量。

此 API 提供了配置 ADC1 以從ULP讀取的便捷方法。為此,請(qǐng)調(diào)用函數(shù)adc1_ulp_enable(),然后如上所述設(shè)置精度和衰減。

還有另一個(gè)特定功能adc_vref_to_gpio()用于將內(nèi)部參考電壓路由到 GPIO 引腳。

四、應(yīng)用實(shí)例

4.1 ADC1單次采集

讀取 ADC1 通道 7 (GPIO 35) 上的電壓,輸入電壓為 0 至 1.1 V(0 dB 衰減)
具體代碼查看 esp-idf\examples\peripherals\adc 中的例程

#include <driver/adc.h>

static const adc_channel_t channel = ADC1_CHANNEL_7;     //GPIO35 if ADC1
...
    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(channel, ADC_ATTEN_DB_0);
    int val = adc1_get_raw(channel);

4.2 ADC2單次采集

讀取 ADC2 通道 7 (GPIO 27) 上的電壓
具體代碼查看 esp-idf\examples\peripherals\adc2 中的例程

#include <driver/adc.h>
...
    int read_raw;
    adc2_config_channel_atten( ADC2_CHANNEL_7, ADC_ATTEN_0db );

    esp_err_t r = adc2_get_raw( ADC2_CHANNEL_7, ADC_WIDTH_12Bit, &read_raw);
    if ( r == ESP_OK ) {
        printf("%d\n", read_raw );
    } else if ( r == ESP_ERR_TIMEOUT ) {
        printf("ADC2 used by Wi-Fi.\n");
    }

讀取可能會(huì)因?yàn)榕c Wi-Fi 沖突而失敗,如果該 API 的返回值為ESP_ERR_INVALID_STATE,則讀取結(jié)果無效。

4.3 ADC DMA

具體代碼查看 components/driver/test/adc_dma_test 中的例程

4.4 ADC校準(zhǔn)

具體代碼查看 esp-idf\examples\peripherals\adc 中的例程
在特定衰減下表征 ADC:

#include "driver/adc.h"
#include "esp_adc_cal.h"
...
    //Characterize ADC at particular atten
    esp_adc_cal_characteristics_t *adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
    //Check type of calibration value used to characterize ADC
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        printf("eFuse Vref");
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        printf("Two Point");
    } else {
        printf("Default");
    }

讀取 ADC,然后將讀數(shù)轉(zhuǎn)換為電壓:

#include "driver/adc.h"
#include "esp_adc_cal.h"
...
    uint32_t reading =  adc1_get_raw(ADC1_CHANNEL_5);
    uint32_t voltage = esp_adc_cal_raw_to_voltage(reading, adc_chars);

將 ADC 參考電壓路由到 GPIO,因此可以手動(dòng)測(cè)量(對(duì)于默認(rèn) Vref):

#include "driver/adc.h"
...
    esp_err_t status = adc_vref_to_gpio(ADC_UNIT_1, GPIO_NUM_25);
    if (status == ESP_OK) {
        printf("v_ref routed to GPIO\n");
    } else {
        printf("failed to route v_ref\n");
    }

4.5 讀取內(nèi)部霍爾效應(yīng)傳感器

#include <driver/adc.h>
...
    adc1_config_width(ADC_WIDTH_BIT_12);
    int val = hall_sensor_read();

? 由 Leung 寫于 2021 年 6 月 4 日

? 參考:ESP32 開發(fā)筆記(三)源碼示例 4_ADC_LightR 利用ADC讀取光敏電阻實(shí)現(xiàn)光線傳感
    ESP32-ADC學(xué)習(xí)
    ESP32S2的ADC出坑記錄

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容