• ESP32 ADC测量电压 arduino


    ADC

    ADC(模拟-数字转换器),首先了解模拟信号和数字信号之间的差异。模拟信号是连续的,可以在其范围内取无限个离散值,例如声音、光线等。 数字信号则是离散的,具有一组有限数量的值,通常用于计算机和电子设备中的信息传输。ADC的作用是将模拟信号转换为数字信号,以便计算机或其他电子设备进行处理和分析。
    在这里插入图片描述

    ADC转换的过程分为两个重要步骤:采样和量化。ADC的输入是模拟信号。当输入的模拟信号被采样时,其值将在设定的时间间隔(采样周期)内以等间隔的方式进行抽样。这样就可以将连续的模拟信号转换为一系列等间隔的采样值。接下来,将每个采样值映射到最接近的离散值(也称为“量化”),并且该离散值将作为ADC的输出。量化可以根据设定的分辨率完成,分辨率表示可以区分的离散值的数量。例如,12位ADC具有2^12(即4096)个可区分的离散值。此外,ADC提供选择衰减器(Attenuator)的功能,该衰减器可以对信号进行放大或消减,以确保输入信号处于ADC可接受的幅度范围内。

    ESP32的ADC通道

    在这里插入图片描述ESP32具有两个集成的ADC,分别称为ADC1和ADC2。两个12位的ADC,其中ADC1(8个通道,连接到GPIO 32-39)和ADC2(10个通道,连接到GPIO 0、2、4、12-15和25-27)

    衰减倍数

    不同的衰减倍数对应不同的检测电压范围。

    ADC的默认满量程电压为1.1V。要读取更高的电压(最高为引脚最大电压,通常为3.3V),则需要将该ADC通道的信号衰减设置为> 0dB。

    当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

    代码实现

    #include 
    #include 
    
    #define DEFAULT_VREF    1100    // 默认1.1V的参考电压
    #define NO_OF_SAMPLES   64      // ADC采样次数
    #define ADC_WIDTH       ADC_WIDTH_12Bit  // ADC 12位宽度
    #define ADC_ATTEN       ADC_ATTEN_6db    // 6dB衰减器
    #define ADC_PIN         ADC1_CHANNEL_4
    
    esp_adc_cal_characteristics_t *adc_chars;
    
    void setup() {
        Serial.begin(115200);
    
        adc1_config_width(ADC_WIDTH);  // 设置ADC为12位宽度
        adc1_config_channel_atten(ADC_PIN, ADC_ATTEN);  // 配置ADC通道为6dB衰减器
    
        // 使用eFuse校准ADC,并获取校准值
        adc_chars = (esp_adc_cal_characteristics_t *) malloc(sizeof(esp_adc_cal_characteristics_t));
        esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN, ADC_WIDTH, DEFAULT_VREF, adc_chars);
    }
    
    void loop() {
        uint32_t adc_reading = 0;
        for (int i = 0; i < NO_OF_SAMPLES; i++) {
            adc_reading += adc1_get_raw((adc1_channel_t) ADC_PIN);
            delay(1);
        }
    
        adc_reading /= NO_OF_SAMPLES;
        uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
    
        Serial.print("ADC Reading: ");
        Serial.print(adc_reading);
        Serial.print("\tVoltage: ");
        Serial.println(voltage);
    
        delay(1000);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    说明:本次测量时IO34已做分压处理

    adc_chars = new esp_adc_cal_characteristics_t; // 新分配一个存储ADC校准值的指针
    esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_11, ADC_WIDTH, DEFAULT_VREF, adc_chars); // 校准ADC2
    
    • 1
    • 2

    在ESP32上使用ADC读取模拟电压时,需要先进行ADC的校准,确保输出结果的准确性和稳定性。在校准过程中,需要使用ESP-IDF中的esp_adc_cal_characterize()函数对ADC进行校准。该函数需要传入ADC的一些基本参数和一个指向存储校准值的首地址赋值给adc_chars指针。sizeof(esp_adc_cal_characteristics_t)获取esp_adc_cal_characteristics_t结构体的大小,malloc()函数会返回一个指向分配的内存块的首地址的指针。这样就成功为存储ADC校准值的结构体分配了一段内存,可供后续的ADC校准过程使用。

    接下来,esp_adc_cal_characterize()函数将使用指定的参考电压DEFAULT_VREF和衰减ADC_ATTEN以及ADC的位宽ADC_WIDTH进行ADC的校准。校准完成后,esp_adc_cal_characterize()函数将会返回esp_adc_cal_value_t类型的校准值类型,这个值表示所选的ADC_UNITADC_ATTEN组合所需要的校准选项。同时,校准过程得到的校准值会被保存在之前动态分配内存块中的adc_chars指针所指向的结构体中,在后续的代码中可以直接使用校准值进行ADC读取和转换。

    总而言之,使用malloc()函数为存储ADC校准值的结构体变量分配内存,并使用esp_adc_cal_characterize()函数为ADC进行校准,可以确保ADC读取的准确性和稳定性。esp_adc_cal_characteristics_t结构体的指针。

    在上述代码中,通过使用malloc()函数在堆内存中动态分配了一段大小为esp_adc_cal_characteristics_t结构体大小的内存,同时将该内存的

    精度问题

    ESP32的ADC测试存在精度问题!!!解决方法:分段算出偏差,然后进行软件补偿,或者使用ESP源码。由于开发问题补偿代码不贴出参考了。
    可参考:https://zhuanlan.zhihu.com/p/540437244

    参考链接:https://www.jianshu.com/p/7739b143b41d

  • 相关阅读:
    STM32基于hal库的adc以DMA的多通道采样以及所遇问题解决
    Elasticsearch(十五)搜索---搜索匹配功能⑥--基于地理位置查询
    FullCalendarDemo5 控件的实例讲解—拖拽实现值班排班(一)
    七夕表白攻略:教你用自己的专业说情话,成功率100%,我只能帮你们到这里了啊~(程序员系列)
    JVM篇---第十篇
    GPT-3.5发布:大型语言模型的进化与挑战
    百度地图、高德地图和腾讯地图定位不准确的解决方案
    【Arduino与MFRC522握手】
    Vue系列(一)之 Vue入门,Vue的生命周期以及前后端分离介绍
    Springboot如何实现数据预热
  • 原文地址:https://blog.csdn.net/hongyun1221/article/details/130851207