当前位置: 首页 > news >正文

MicroPython 开发ESP32应用教程 之 ADC及应用实例:电池电量检测并显示

MicroPython 中的 ADC(模数转换器)模块为嵌入式开发提供了便捷的模拟信号采集功能,其核心实现基于 machine.ADC 类。以下是关键要点:

一、 ‌ADC 基本原理

ADC 的作用是将连续变化的模拟信号(如电压、光照强度)转换为离散的数字信号,以便微控制器处理。其核心参数包含 ‌分辨率‌(如 10 位或 12 位)和 ‌输入电压范围‌。

1、. ‌硬件差异与配置

  • ESP32 系列‌:如 ESP32-S3 支持 ‌0-3.3V‌ 输入,12 位分辨率(返回值 0-4095)。需注意 ADC2 通道与 Wi-Fi 功能冲突,MicroPython 固件通常仅支持 ADC1。
  • 输入衰减设置‌:可通过 atten() 方法调整 ADC 输入电压范围,例如 ESP32 支持 0dB(0-1.1V)、6dB(0-1.5V)等衰减等级,以适配不同传感器信号。

2. ‌核心 API 使用方法

  • 构造对象‌:adc = machine.ADC(Pin(17))
  • 读取原始值‌:adc.read() 返回原始 ADC 数值adc_value
  • 电压转换公式‌:
    电压值 = (ADC原始值adc_value  / 最大分辨率) * 参考电压 
    例如 ESP32-S3 计算电压:voltage = (adc_value / 4095) * 3.3

3. ‌应用示例

  • 电位器电压采集‌:通过 ADC 读取引脚电压并显示在 OLED 屏幕,循环采样间隔可根据实际需要设置。
  • 光敏传感器‌:结合 ADC 读取光照强度,动态调整 LED 亮度(需配合 PWM 模块)。

4. ‌注意事项

  • 噪声抑制‌:ADC 易受电源干扰,建议硬件设计时增加滤波电路。
  • 精度限制‌:ESP 系列 ADC 线性度较差,高精度场景需外部 ADC 芯片

通过合理配置衰减、采样精度及数据处理逻辑,MicroPython ADC 可广泛应用于传感器数据采集、环境监测等物联网场景。

二、Micropython ADC的配置与使用

在 ESP32 上使用 MicroPython 的 ADC 模块时,需注意其特有的硬件配置和限制。以下是详细的配置步骤和代码示例(以锂电池的电量检测为例):

1. 硬件准备

  • ESP32s3 开发板‌( ESP32-s3-WROOM-1)。
  • ADC 输入源‌(锂电池电量检测)。电路如下所示:

  • 接线‌:将需要检测的电压信号点连接到 ESP32 的 ‌ADC 引脚‌(GPIO17)。需要注意的是,在检测之前需要将GPIO18置高,否则无法检测有效的锂电池电量。

2. 初始化 ADC

ESP32 的 ADC 通道分为 ‌ADC1‌ 和 ‌ADC2‌,但 ‌ADC2 与 Wi-Fi 功能冲突‌,因此在 Wi-Fi 启用时只能使用 ADC1。

from machine import ADC,Pinadc = ADC(Pin(17))

3. 配置输入电压范围(衰减设置)

ESP32 ADC 默认支持 ‌0-1.1V(11dB 衰减)‌,但可以通过 atten() 方法调整输入范围:

衰减值电压范围适用场景
ADC.ATTN_0DB0-1.1V低电压传感器(如光敏)
ADC.ATTN_2_5DB0-1.5V中等电压
ADC.ATTN_6DB0-2.2V常用范围
ADC.ATTN_11DB0-3.3V高电压(如电位器)

设置衰减

adc.atten(ADC.ATTN_11DB) # 允许输入 0-3.3V 电压

4. 设置分辨率

ESP32 ADC 支持 ‌9-12 位分辨率‌,通过 width() 方法调整:
 

adc.width(ADC.WIDTH_12BIT) # 12 位分辨率(0-4095) 

5. 读取原始值并转换为电压

读取原始 ADC 值

    def read_battery_voltage():raw = adc.read()  # 读取原始值voltage = raw / 4095 * 3.3  # 转换为电压(分压后的电压)return voltage * 2 # 计算实际电池电压,之所以乘以2与我们的电路有关,请参考上面的电路

‌6. 注意事项

  1. ADC2 与 Wi-Fi 冲突‌:
    使用 ADC2 时需禁用 Wi-Fi,否则会抛出异常:

  2. 噪声抑制‌:

    • 在信号线上并联 ‌0.1μF 电容‌。
    • 软件端可通过 ‌均值滤波‌ 提高稳定性:
  3. ADC 线性度问题‌:
    ESP32 内置 ADC 的精度较低(非线性误差约 ±5%),高精度场景建议使用 ‌外部 ADC 芯片‌(如 ADS1115)。

三、锂电池电量检测方法介绍

锂电池电量检测的核心原理基于电池电化学特性与电参数关联性,主要方法可分为以下三类:


一)、电压测量法

  1. 原理
    通过测量电池端电压估算剩余电量,依赖锂电池电压与荷电状态(SOC)的非线性关系。例如:

    • 满电电压 ≈ 4.2V(对应 100% SOC)
    • 欠压截止 ≈ 3.2V(对应 0% SOC)
  2. 实现方式

    • 静态检测:空载时直接读取电压,适用于低功耗场景(如待机模式)
    • 动态补偿:结合负载电流对压降的实时修正,公式为:
      V_corrected = V_measured + I_load × R_internal 
      其中 R_internal 为电池内阻。但实际应用中,我们往往很难准确获取电流及电池电阻,所以补偿电压很多时候也是一个大概的经验值。在我们的实例中,甚至没有作动态补偿。
  3. 优缺点

    • 优点‌:成本低、实现简单,适用于静态负载设备(如电子秤)
    • 缺点‌:
      • 电压-SOC 曲线非线性显著(如 3.7-4.2V 区间变化剧烈)
      • 动态负载下电压波动导致误差(如电动车启动时电量显示骤降)

二)、充放电曲线法(OCV 法)

  1. 原理
    基于电池开路电压(OCV)与 SOC 的对应关系建立查表数据库,通过实测电压反向映射剩余电量。

  2. 实现步骤

    • 标定阶段‌:使用高精度库仑计记录不同 SOC 下的 OCV 值,生成校准曲线
    • 应用阶段‌:设备休眠时测量 OCV,结合温度补偿算法查表输出 SOC
  3. 优化方案

    • 分段线性化处理电压-SOC 曲线,降低查表复杂度
    • 引入老化因子动态修正曲线(如循环次数对容量的影响)

三)、库仑计法(电流积分法)

  1. 原理
    通过实时监测充/放电电流,对时间积分计算电荷量:
    Q_remaining = Q_initial ± ∫I(t)dt

    其中 Q_initial 为初始电量

  2. 硬件实现

    • 检流电阻‌:串联在电池回路中(常用 10mΩ-100mΩ 阻值)
    • ADC 采样‌:采集电阻两端压差计算电流
    • 温度补偿‌:集成 NTC 传感器修正内阻温漂误差
  3. 校准机制

    • 满充复位‌:充电至截止电压时自动重置容量计数器
    • 开路电压校验‌:定期休眠测量 OCV,修正累积误差

四)、复合算法与扩展技术

  1. 融合模型
    结合电压法、库仑计及电池模型(如等效电路模型),提升全工况精度:

    • 低 SOC 时依赖电压阈值
    • 高 SOC 时启用电流积分
  2. 电化学阻抗谱(EIS)
    通过施加交流扰动信号分析阻抗频谱,推算电池健康状态(SOH)与 SOC

  3. AI 预测
    基于循环伏安(CV)数据训练神经网络,实现动态负载下的 SOC 预估


五)、典型应用场景对比

方法精度误差成本适用场景代表方案
电压测量法10-20%低端玩具、电动自行车LED 分级显示
充放电曲线法5-10%手机、智能穿戴设备OCV 查表算法
库仑计法1-3%医疗设备、电动汽车TI BQ 系列芯片

‌四、实例讲解

本例采用的是电压测量法,有兴趣的朋友可以自行探索后面两种锂电池电量的检测方法。

 显示部分请参考:MicroPython for ESP32开发st7789 TFT显示屏驱动、ST7735TFT 显示屏驱动

1、 BatteryStatus(电池电量检测模块)

 为了方便,我们将电池电量检测功能封装成了class BatteryStatus:

from micropython import const
#import time# 锂电池电压与电量对应关系(以3.7V LiPo为例)
VOLTAGE_MIN = const(3.2)  # 电量0%对应电压
VOLTAGE_MAX = const(4.2)  # 电量100%对应电压class BatteryStatus:CheckBATInterval = 0voltage_min = VOLTAGE_MINvoltage_max = VOLTAGE_MAXdef __init__(self, adc, adc_atten,adc_width,power=None):# 初始化ADC引脚(示例使用GPIO34)self.adc = adcself.adc.atten(adc_atten)self.adc.width(adc_width)self.power = power    #根据前面的电路图,我们知道,检测电池电量前GPIO18必须置高def bat_config(self,v_min,v_max):self.voltage_min = v_minself.voltage_max = v_maxdef read_battery_voltage(self):if self.power is not None:self.power(1)     #根据前面的电路图,我们知道,检测电池电量前GPIO18必须置高raw = self.adc.read()  # 读取原始值if self.power is not None:self.power(0)voltage = raw / 4095 * 3.3  # 转换为电压(分压后的电压)return voltage * 2 # 计算实际电池电压,之所以乘以2与电路有关,请参考前面的电路图def voltage_to_percent(self,voltage):if voltage >= self.voltage_max:return 100elif voltage <= self.voltage_min:return 0else:percent = (voltage - self.voltage_min) / (self.voltage_max - self.voltage_min) * 100return round(percent, 1)def battery_monitor(self):
#        while True:v = self.read_battery_voltage()percent = self.voltage_to_percent(v)
#        print(f"Voltage: {v:.2f}V, Percent: {percent}%")return percent
#            time.sleep(6)  # 每分钟检测一次

结合前面的知识点及代码中的注释,相信大家很容易能明白,这部分代码就不多讲解。

2、增加显示电量的接口

 在现有的显示模块ST7789中增加显示电池电量的接口:

    def  battery_status(self,x,y,width = 24,height = 16,percent=90,c=color(0,0xff,0)):self.rect(x,y,width,height,c)width = int((width - 4) * percent / 100)self.rect(x + 2, y + 2,width,height - 4,c,True) 

3、电池电量检测模块的初始化

def battery_status_init():bat_power = Pin(18,Pin.OUT)adc = ADC(Pin(17))batstatus = BatteryStatus(adc,ADC.ATTN_11DB,ADC.WIDTH_12BIT,bat_power)batstatus.bat_config(3.2,4.18)  #设置最低电压及最高电压return batstatus

4、定时检测电池电量

    tim = Timer(3)tim.init(period = MOINTOR_Interval,mode=Timer.PERIODIC,callback=monitor)def monitor(t):global bat_intervalglobal chgbat_statusbat_interval += 1if bat_interval >= (BAT_Interval / MOINTOR_Interval):bat_interval = 0chgbat_status = TruePowerOn = Truetft.showstring("电池电量监测实验",40,60)while True:if chgbat_status or PowerOn:percent = batstatus.battery_monitor()tft.battery_status(H_Pixel - 20,0,20,12,percent)tft.show()PowerOn = False

这里利用定时器中断来实现定时检测电池电量。

关于定时器中断,大家可以参考:MicroPython 开发ESP32应用教程 之 Timer、GPIO中断

最后,完整代码 可以参考:micropythonforesp32s3电池电量检测并显示资源-CSDN文库

相关文章:

  • js闭包概念和使用
  • 从实列中学习linux shell5: 利用shell 脚本 检测硬盘空间容量,当使用量达到80%的时候 发送邮件
  • 安恒安全培训实习生,CTF方向面试题!
  • crashpad 编译
  • MacOS 安装 cocoapods
  • 解读 AI绘画工作流ComfyUI Stable Diffusion
  • react中封装一个预览.doc和.docx文件的组件
  • TCP三次握手、四次挥手+多线程并发处理
  • ceph存储原理
  • 【UE5】“对不起,您的客户端未能传递登录所需的参数”解决办法
  • Linux Quota 显示空间占用远大于实际数据的问题排查记录
  • 01 mysql 安装(Windows)
  • 32单片机——独立看门狗
  • 算法基础学习|03整数二分
  • 如何编制研发部门绩效考核制度
  • 删除k8s某命名空间,一直卡住了怎么办?
  • java之Integer、Double自动拆装箱比较,踩坑值int和Integer比较之空指针异常
  • 垒球世界纪录多少米·棒球1号位
  • 三格电子上新了——超高频RFID读写器
  • 2025最新福昕PDF编辑器,PDF万能处理工具
  • 抗美援朝老战士宁昭逝世,享年93岁
  • 2024“好评中国”网络评论大赛结果揭晓
  • 央行副行长:研究建立民营中小企业增信制度,破解民营中小企业信用不足等融资制约
  • 程璧“自由生长”,刘卓辉“被旋律牵着走”
  • 葛兰西:“生活就是抵抗”
  • 我国首个大型通用光谱望远镜JUST在青海启动建设