当前位置:网站首页>ESP32 ESP-IDF ADC监测电池电压(带校正)
ESP32 ESP-IDF ADC监测电池电压(带校正)
2022-07-01 06:30:00 【晨之清风】
陈拓 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_A为3.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+]可以退出监视器程序)

边栏推荐
- Chapitre V gestion des entrées / sorties
- 给逆序对数求原数组
- Picture server project test
- [unity shader custom material panel part II]
- VS2019如何永久配置本地OpenCV4.5.5使用
- How does the port scanning tool help enterprises?
- Design of sales management system for C language course (big homework)
- Self confidence is indispensable for technology
- Forkjoin and stream flow test
- 自开发软件NoiseCreater1.1版本免费试用
猜你喜欢

SQL statement

Some pits designed by NOC

下载外文期刊的方法
![[enterprise data security] upgrade backup strategy to ensure enterprise data security](/img/59/e44c6533aa546e8854ef434aa64113.png)
[enterprise data security] upgrade backup strategy to ensure enterprise data security

ManageEngine Zhuohao helps you comply with ISO 20000 standard (IV)

脏读、幻读和不可重复读
![[wechat applet] to solve button, input and image components](/img/7f/a61ee2f610b2f0f9fb0b34cb960f81.jpg)
[wechat applet] to solve button, input and image components

C language course set up property fee management system (big work)
![[wechat applet] view container and basic content components](/img/25/181986ab4bf048854d1d1ca87de637.jpg)
[wechat applet] view container and basic content components

【微信小程序】一文解决button、input、image组件
随机推荐
Detailed steps for installing redis on Windows system
根据输入画有向图
C#如何打印输出原版数组
码力十足学量化|如何在财务报告寻找合适的财务公告
Design of sales management system for C language course (big homework)
【#Unity Shader#Amplify Shader Editor(ASE)_第九篇】
基金定投是高风险产品吗?
Functions of switch configuration software
Mysql 表分区创建方法
第五章 輸入/輸出(I/O)管理
C语言课设工资管理系统(大作业)
lxml模块(数据提取)
[network security tool] what is the use of USB control software
[ManageEngine Zhuohao] mobile terminal management solution, helping the digital transformation of Zhongzhou aviation industry
Interview questions for HW (OD) post
问题:OfficeException: failed to start and connect(二)
三分钟带你快速了解网站开发的整个流程
Forkjoin and stream flow test
Notes on probability theory
【#Unity Shader#自定义材质面板_第一篇】