IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> ESP32 ESP-IDF ADC监测电池电压(带校正) -> 正文阅读

[嵌入式]ESP32 ESP-IDF ADC监测电池电压(带校正)

陈拓 2022/06/24-2022/06/24

1. 概述

  • 此示例显示如何配置ADC1并读取连接到GPIO引脚的电压。
  • 引脚功能

在本例中,我们使用默认的ADC_UNIT_1,我们电池供电的应用中将ESP32开发板的电源连接到GPIO34,以监测电池电压。如果在应用程序中选择了其他ADC单元,则需要更改GPIO引脚(请参阅《ESP32技术参考手册》第4.11章)。

ESP32有2个12位的ADC,共18个通道。要注意的是ADC2和wifi共用引脚,wifi的优先级更高,所以ADC2只有在WIFI模块不用的情况下才能使用。

ESP32的18个ADC通道如下:

ADC1有8个通道:GPIO32 - GPIO39

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

每个ADC单元支持两种工作模式,单次采样模式和连续采样(DMA)模式。单次采样模式适用于低频采样操作,连续采样模式适用于高频连续采样动作。

本例为单次采样模式。

  • 官方例程国内镜像

https://gitee.com/EspressifSystems/esp-idf/tree/master/examples/peripherals/adc/single_read/adc

?

2. 开发环境

《用乐鑫国内Gitee镜像搭建ESP32开发环境》

https://zhuanlan.zhihu.com/p/348106034

https://blog.csdn.net/chentuo2000/article/details/113424934?spm=1001.2014.3001.5501

3. 修改代码

  • 克隆官方例程

将官方例子项目复制到ESP-IDF开发工具之外:

cd ~/esp

cp -r ~/esp/esp-idf/examples/peripherals/adc/single_read/adc ~/esp/

  • 项目树

cd adc

tree

?

  • 衰减与测量范围

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

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

VDD_A3.3V时:

-- 0dB衰减(ADC_ATTEN_0)满量程电压为1.1V

-- 2.5dB衰减(ADC_ATTEN_DB_2_5)满量程电压为1.5V

-- 6dB衰减(ADC_ATTEN_6)满量程电压为2.2V

-- 11dB衰减(ADC_ATTEN_11)满量程电压为3.9 V(见以下注释)

注释:

满量程电压是对应于最大读数的电压(取决于ADC1配置的位宽度,该值为:4095表示12位,2047表示11位,1023表示10位,511表示9位。)

注释:

11dB衰减时,最大电压受VDD_A限制,而非满量程电压。

由于ADC特性,可在以下近似电压范围内获得最准确的结果:

-- 0dB衰减(ADC_ATTEN_DB_0) 100~950 mV

-- 2.5dB衰减(ADC_ATTEN_DB_2_5) 100~1250 mV

-- 6dB衰减(ADC_ATTEN_DB_6) 150~1750 mV

-- 11dB衰减(ADC_ATTEN_DB_11) 150~2450 mV

为了2450mV以上电压测量更准确我们使用了

ESP32在电池供电时用ULP监测电池电压》

https://zhuanlan.zhihu.com/p/523358887

https://blog.csdn.net/chentuo2000/article/details/125094853?spm=1001.2014.3001.5502

一文中相关的校正代码。

  • eFuse校正

ADC1是带有出厂校准的,所以计算结果有eFuse Vref: Supported

  • 修改代码

adc1_example_main.c

/* ADC1 Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"

#define DEFAULT_VREF    1100        //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES   64          // 多重采样次数

static esp_adc_cal_characteristics_t *adc_chars;
#if CONFIG_IDF_TARGET_ESP32
static const adc_channel_t channel = ADC_CHANNEL_6;     //GPIO34 if ADC1, GPIO14 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_channel_t channel = ADC_CHANNEL_6;     // GPIO7 if ADC1, GPIO17 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;

// voltage to raw data struct
typedef struct {
    float vol;
    uint32_t raw;
} vol_to_raw_t;

/* Set thresholds, approx. 2.00V - 3.30V */
#define VAL_TO_RAW_NUM   14
static const vol_to_raw_t g_v0l_to_raw[VAL_TO_RAW_NUM] = {
    {2.00, 3123},
    {2.10, 3207},
    {2.20, 3301},
    {2.27, 3361},
    {2.35, 3434},
    {2.43, 3515},
    {2.52, 3598},
    {2.60, 3682},
    {2.68, 3745},
    {2.76, 3825},
    {2.80, 3867},
    {2.90, 3891},
    {3.00, 3986},
    {3.30, 4095},
};

static void check_efuse(void)
{
#if CONFIG_IDF_TARGET_ESP32
    //Check if TP is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("eFuse Two Point: NOT supported\n");
    }
    //Check Vref is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        printf("eFuse Vref: Supported\n");
    } else {
        printf("eFuse Vref: NOT supported\n");
    }
#elif CONFIG_IDF_TARGET_ESP32S2
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("Cannot retrieve eFuse Two Point calibration values. Default calibration values will be used.\n");
    }
#else
#error "This example is configured for ESP32/ESP32S2."
#endif
}


static void print_char_val_type(esp_adc_cal_value_t val_type)
{
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        printf("Characterized using Two Point Value\n");
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        printf("Characterized using eFuse Vref\n");
    } else {
        printf("Characterized using Default Vref\n");
    }
}

static float ulp_adc_raw_to_vol(uint32_t adc_raw)
{
    if (adc_raw < g_v0l_to_raw[0].raw
            || adc_raw > g_v0l_to_raw[VAL_TO_RAW_NUM - 1].raw) {
        return 0;
    }

    float ret_vol = 0;
    for (int i = 0; i < VAL_TO_RAW_NUM - 1; i++) {
        if (g_v0l_to_raw[i].raw <= adc_raw && g_v0l_to_raw[i + 1].raw >= adc_raw) {
            uint32_t raw_dif = g_v0l_to_raw[i + 1].raw - g_v0l_to_raw[i].raw;
            float vol_dif    = g_v0l_to_raw[i + 1].vol - g_v0l_to_raw[i].vol;
            ret_vol = g_v0l_to_raw[i].vol + (float)(adc_raw - g_v0l_to_raw[i].raw) / (float)raw_dif * vol_dif;
            break;
        }
    }
    return ret_vol;
}

void app_main(void)
{
    //Check if Two Point or Vref are burned into eFuse
    check_efuse();

    //Configure ADC
    if (unit == ADC_UNIT_1) {
        adc1_config_width(width);
        adc1_config_channel_atten(channel, atten);
    } else {
        adc2_config_channel_atten((adc2_channel_t)channel, atten);
    }

    //Characterize ADC
    adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    print_char_val_type(val_type);

    //Continuously sample ADC1
    while (1) {
        uint32_t adc_reading = 0;
        //Multisampling
        for (int i = 0; i < NO_OF_SAMPLES; i++) {
            if (unit == ADC_UNIT_1) {
                adc_reading += adc1_get_raw((adc1_channel_t)channel);
            } else {
                int raw;
                adc2_get_raw((adc2_channel_t)channel, width, &raw);
                adc_reading += raw;
            }
        }
        adc_reading /= NO_OF_SAMPLES; // 取多重采样的平均值
        //Convert adc_reading to voltage in mV
        uint32_t voltage = 0;
        if(adc_reading < 3123) { // 如果电压小于2.00, 3123
            voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
        } else {
            float voltage_f = ulp_adc_raw_to_vol(adc_reading) * 1000;
            voltage = (uint32_t)voltage_f;
        }
        printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

4. 构建项目

  • 刷新esp-idf环境

get_idf

  • 设定目标芯片

idf.py set-target esp32

  • 配置项目

idf.py menuconfig

1) 将闪存设置为4MB

?

保存,退出。

  • 编译项目

idf.py build

  • 烧写项目

查看USB转串口的COM口号:

?

烧写:

idf.py -p /dev/ttyS3 -b 115200 flash

  • 启用监视器

idf.py monitor -p /dev/ttyS3

(Ctrl+]可以退出监视器程序)

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:16:14  更:2022-06-29 19:16:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:29:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码