• ESP32系列--第九篇 ADC的使用


    一、目的

            本篇主要介绍ESP32的ADC功能,ESP32有两个ADC模块,分别为ADC1/ADC2;每个ADC具有8个通道。

            在WiFi在使用时,ADC2的使用受到一些限制,实际应用场景中一般只使用ADC1即可。

    二、介绍

    ADC的IO引脚分配(下表来自ESP-IDF开发文档)

    GPIO

    Analog Function

    RTC GPIO

    Comments

    GPIO0

    ADC2_CH1

    RTC_GPIO11

    Strapping pin

    GPIO1

    TXD

    GPIO2

    ADC2_CH2

    RTC_GPIO12

    Strapping pin

    GPIO3

    RXD

    GPIO4

    ADC2_CH0

    RTC_GPIO10

    GPIO5

    Strapping pin

    GPIO6

    SPI0/1

    GPIO7

    SPI0/1

    GPIO8

    SPI0/1

    GPIO9

    SPI0/1

    GPIO10

    SPI0/1

    GPIO11

    SPI0/1

    GPIO12

    ADC2_CH5

    RTC_GPIO15

    Strapping pin; JTAG

    GPIO13

    ADC2_CH4

    RTC_GPIO14

    JTAG

    GPIO14

    ADC2_CH6

    RTC_GPIO16

    JTAG

    GPIO15

    ADC2_CH3

    RTC_GPIO13

    Strapping pin; JTAG

    GPIO16

    SPI0/1

    GPIO17

    SPI0/1

    GPIO18

    GPIO19

    GPIO21

    GPIO22

    GPIO23

    GPIO25

    ADC2_CH8

    RTC_GPIO6

    GPIO26

    ADC2_CH9

    RTC_GPIO7

    GPIO27

    ADC2_CH7

    RTC_GPIO17

    GPIO32

    ADC1_CH4

    RTC_GPIO9

    GPIO33

    ADC1_CH5

    RTC_GPIO8

    GPIO34

    ADC1_CH6

    RTC_GPIO4

    GPI

    GPIO35

    ADC1_CH7

    RTC_GPIO5

    GPI

    GPIO36

    ADC1_CH0

    RTC_GPIO0

    GPI

    GPIO37

    ADC1_CH1

    RTC_GPIO1

    GPI

    GPIO38

    ADC1_CH2

    RTC_GPIO2

    GPI

    GPIO39

    ADC1_CH3

    RTC_GPIO3

    GPI

            从上表我们可以看到ADC1可以使用的IO引脚为GPIO32-GPIO39总共8个通道。

    ADC的参考电压

            ESP32默认的参考电压是1.1V(每个芯片间有差异,非精准),所以只能测量0-1.1V的电压;

    ADC的量程设置

            为了能够测量更大量程的电压,需要使用其衰减配置;每个通道都可以单独配置

    1. /**
    2. * @brief ADC attenuation parameter. Different parameters determine the range of the ADC. See ``adc1_config_channel_atten``.
    3. */
    4. typedef enum {
    5. ADC_ATTEN_DB_0 = 0, ///<No input attenumation, ADC can measure up to approx. 800 mV
    6. ADC_ATTEN_DB_2_5 = 1, ///<The input voltage of ADC will be attenuated extending the range of measurement by about 2.5 dB (1.33 x)
    7. ADC_ATTEN_DB_6 = 2, ///<The input voltage of ADC will be attenuated extending the range of measurement by about 6 dB (2 x)
    8. ADC_ATTEN_DB_11 = 3, ///<The input voltage of ADC will be attenuated extending the range of measurement by about 11 dB (3.55 x)
    9. } adc_atten_t;

            每个配置推荐的输入范围

    Attenuation

    Measurable input voltage range

    ADC_ATTEN_DB_0

    100 mV ~ 950 mV

    ADC_ATTEN_DB_2_5

    100 mV ~ 1250 mV

    ADC_ATTEN_DB_6

    150 mV ~ 1750 mV

    ADC_ATTEN_DB_11

    150 mV ~ 2450 mV

    ADC最小化噪声

            1.在输入引脚接一个100nF的陶瓷电容

            2.多次采样取平均

    ADC的校准方式

            不同芯片的参考电压不一样(1000mV - 1200mV),所以建议进行硬件校准

    1. /**
    2. * @brief Type of calibration value used in characterization
    3. */
    4. typedef enum {
    5. ESP_ADC_CAL_VAL_EFUSE_VREF = 0, /**< Characterization based on reference voltage stored in eFuse*/
    6. ESP_ADC_CAL_VAL_EFUSE_TP = 1, /**< Characterization based on Two Point values stored in eFuse*/
    7. ESP_ADC_CAL_VAL_DEFAULT_VREF = 2, /**< Characterization based on default reference voltage*/
    8. ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3, /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */
    9. ESP_ADC_CAL_VAL_MAX,
    10. ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX,
    11. } esp_adc_cal_value_t;

            ESP32支持ESP_ADC_CAL_VAL_EFUSE_TP/ESP_ADC_CAL_VAL_EFUSE_VREF

            ESP32S2支持ESP_ADC_CAL_VAL_EFUSE_TP

            ESP32S3支持ESP_ADC_CAL_VAL_EFUSE_TP_FIT

            ESP_ADC_CAL_VAL_EFUSE_TP根据EFUSE里面两个采样值进行校准(150mV/850mV)

            ESP_ADC_CAL_VAL_EFUSE_VREF根据EFUSE里面的参考电压校准

            ESP_ADC_CAL_VAL_EFUSE_TP_FIT根据EFUSE里面两个采样点和特性曲线校准

            有些ESP32模组出厂时已经做了校准,我们可以通过工具查看

    ADC相关的efuse设置        

    1. $espefuse.py -p /dev/cu.SLAB_USBtoUART adc_info
    2. Connecting......
    3. Detecting chip type... Unsupported detection protocol, switching and trying again...
    4. Connecting......
    5. Detecting chip type... ESP32
    6. espefuse.py v4.1
    7. === Run "adc_info" command ===
    8. ADC VRef calibration: 1128mV

            通过espefuse.py adc_info命令我们可以看到我的ESP32模组默认支持VRef校验。

            如果不支持VRef校准输出如下

    ADC VRef calibration: None (1100 mV nominal)

             如果支持两点校准,输出如下

    1. ADC VRef calibration: 1149 mV
    2. ADC readings stored in efuse BLK3:
    3. ADC1 Low reading (150 mV): 306
    4. ADC1 High reading (850 mV): 3153
    5. ADC2 Low reading (150 mV): 389
    6. ADC2 High reading (850 mV): 3206

    三、实战

            接口说明

            1.检查是否支持指定的校准方式

            esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t value_type);

            2.设置采样量化位数

            esp_err_t adc1_config_width(adc_bits_width_t width_bit);

            3.设置指定通道的衰减

            esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);

            4.获取指定通道校准特征值

            esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
                                                 adc_atten_t atten,
                                                 adc_bits_width_t bit_width,
                                                 uint32_t default_vref,
                                                 esp_adc_cal_characteristics_t *chars);

            5.获取指定通道的采样值

            int adc1_get_raw(adc1_channel_t channel);

            6.根据校准特征值获取实际电压值

            uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars);

            参考代码

    1. /* ADC1 Example
    2. This example code is in the Public Domain (or CC0 licensed, at your option.)
    3. Unless required by applicable law or agreed to in writing, this
    4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    5. CONDITIONS OF ANY KIND, either express or implied.
    6. */
    7. #include <stdio.h>
    8. #include <stdlib.h>
    9. #include "freertos/FreeRTOS.h"
    10. #include "freertos/task.h"
    11. #include "driver/gpio.h"
    12. #include "driver/adc.h"
    13. #include "esp_adc_cal.h"
    14. #define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate
    15. #define NO_OF_SAMPLES 64 //Multisampling
    16. static esp_adc_cal_characteristics_t *adc_chars;
    17. #if CONFIG_IDF_TARGET_ESP32
    18. static const adc_channel_t channel = ADC_CHANNEL_6; //GPIO34 if ADC1, GPIO14 if ADC2
    19. static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
    20. #elif CONFIG_IDF_TARGET_ESP32S2
    21. static const adc_channel_t channel = ADC_CHANNEL_6; // GPIO7 if ADC1, GPIO17 if ADC2
    22. static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
    23. #endif
    24. static const adc_atten_t atten = ADC_ATTEN_DB_0;
    25. static const adc_unit_t unit = ADC_UNIT_1;
    26. static void check_efuse(void)
    27. {
    28. #if CONFIG_IDF_TARGET_ESP32
    29. //Check if TP is burned into eFuse
    30. if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
    31. printf("eFuse Two Point: Supported\n");
    32. } else {
    33. printf("eFuse Two Point: NOT supported\n");
    34. }
    35. //Check Vref is burned into eFuse
    36. if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
    37. printf("eFuse Vref: Supported\n");
    38. } else {
    39. printf("eFuse Vref: NOT supported\n");
    40. }
    41. #elif CONFIG_IDF_TARGET_ESP32S2
    42. if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
    43. printf("eFuse Two Point: Supported\n");
    44. } else {
    45. printf("Cannot retrieve eFuse Two Point calibration values. Default calibration values will be used.\n");
    46. }
    47. #else
    48. #error "This example is configured for ESP32/ESP32S2."
    49. #endif
    50. }
    51. static void print_char_val_type(esp_adc_cal_value_t val_type)
    52. {
    53. if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
    54. printf("Characterized using Two Point Value\n");
    55. } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
    56. printf("Characterized using eFuse Vref\n");
    57. } else {
    58. printf("Characterized using Default Vref\n");
    59. }
    60. }
    61. void app_main(void)
    62. {
    63. //Check if Two Point or Vref are burned into eFuse
    64. check_efuse();
    65. //Configure ADC
    66. if (unit == ADC_UNIT_1) {
    67. adc1_config_width(width);
    68. adc1_config_channel_atten(channel, atten);
    69. } else {
    70. adc2_config_channel_atten((adc2_channel_t)channel, atten);
    71. }
    72. //Characterize ADC
    73. adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    74. esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    75. print_char_val_type(val_type);
    76. //Continuously sample ADC1
    77. while (1) {
    78. uint32_t adc_reading = 0;
    79. //Multisampling
    80. for (int i = 0; i < NO_OF_SAMPLES; i++) {
    81. if (unit == ADC_UNIT_1) {
    82. adc_reading += adc1_get_raw((adc1_channel_t)channel);
    83. } else {
    84. int raw;
    85. adc2_get_raw((adc2_channel_t)channel, width, &raw);
    86. adc_reading += raw;
    87. }
    88. }
    89. adc_reading /= NO_OF_SAMPLES;
    90. //Convert adc_reading to voltage in mV
    91. uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
    92. printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
    93. vTaskDelay(pdMS_TO_TICKS(1000));
    94. }
    95. }

    以上,基本就讲完了ADC1的使用,点赞收藏不可少

  • 相关阅读:
    iptables应用大全
    Docker OCI runtime create failed
    @ConditionalOnProperty 注解的四个属性解释
    啥,要我前端去对接外部?我也不会呀
    vite+vue集成cesium
    爬取东方财富股票信息
    计算机毕业设计基于Python实现的作业查重系统
    八股文之redis
    BMS电池管理系统之SOC估算方法介绍
    CSS 中的变量
  • 原文地址:https://blog.csdn.net/tianizimark/article/details/125348749