新闻详情

新闻详情

首页 / 资讯中心 / 详情

ESP32锂电池电压监测:分压电路设计与ADC校准实战

发布时间:2026/9/28 18:07:55来源:尧图网络
ESP32锂电池电压监测:分压电路设计与ADC校准实战
1. 为什么电池电压监测值得单独拿出来做锂电池电压监测这件事看起来简单——不就是拿个万用表量一下正负极吗但放到嵌入式项目里尤其是用 ESP32 做电池供电设备的时候这件事就没那么随意了。我自己做过好几个带锂电池的 ESP32 项目从便携式环境监测到远程数据采集终端几乎每一个都绕不开电池电压的实时监测。原因很直接锂电池过放会永久损坏过充有安全风险而设备如果不知道自己的电量状态就没法做低电报警、自动休眠、电量百分比显示这些基本功能。ESP32 本身内置了 ADC模数转换器理论上可以直接读取模拟电压。但问题在于锂电池的电压范围通常在 3.0V 到 4.2V 之间而 ESP32 的 ADC 输入范围在默认配置下大约只能到 1.1V 左右取决于衰减设置直接把电池正极接到 ADC 引脚上轻则读数不准重则烧掉芯片。所以必须用分压电路把电池电压按比例降下来再送进 ADC 采样。这个项目的核心就是两件事一是设计一个靠谱的分压电路把电池电压安全地映射到 ADC 可测范围内二是用 ESP32 的 ADC 把这个电压读出来并通过校准和滤波得到可信的电池电压值。听起来不复杂但实际操作中有不少细节会让人翻车——ADC 非线性、参考电压漂移、分压电阻精度、WiFi 开启后的噪声干扰每一个都可能让你的读数跳得像心电图。这篇文章适合谁看如果你正在用 ESP32 做电池供电的项目需要监测锂电池电压或者你已经试过直接读 ADC 但发现数值完全不对又或者你只是想知道分压电路怎么算、电阻怎么选、代码怎么写那这篇内容应该能帮你省下不少试错时间。我会从电路设计讲到代码实现再到校准和避坑尽量把每个环节的“为什么”说清楚。2. 分压电路设计与电阻选型2.1 分压原理回顾与参数计算分压电路的本质就是两个电阻串联利用电阻上的电压分配关系把高电压按比例降低。电路结构很简单电池正极接电阻 R1 的一端R1 的另一端接 R2 的一端R2 的另一端接 GND。R1 和 R2 的连接点就是分压输出点接到 ESP32 的 ADC 引脚上。输出电压的公式是Vout Vin × R2 / (R1 R2)其中 Vin 是电池电压Vout 是送到 ADC 的电压。我们需要保证在电池最高电压4.2V时Vout 不超过 ADC 的安全输入范围。这里就涉及 ESP32 ADC 的衰减设置。ESP32 的 ADC 有几种衰减档位常用的有衰减档位可测范围理论适用场景ADC_ATTEN_DB_00 ~ 1.1V小信号采样ADC_ATTEN_DB_2_50 ~ 1.5V中等信号ADC_ATTEN_DB_60 ~ 2.2V一般模拟量ADC_ATTEN_DB_110 ~ 3.3V较大电压范围虽然 ADC_ATTEN_DB_11 理论上能测到 3.3V但实际线性度在接近上限时很差通常建议把最大输入控制在 2.5V 以下留出余量。我一般会选择让 4.2V 对应的分压输出在 2.0V 到 2.5V 之间这样既有足够的动态范围又避开了 ADC 的非线性区域。假设我们选择 4.2V 对应 2.2V 输出那么分压比就是R2 / (R1 R2) 2.2 / 4.2 ≈ 0.5238也就是说 R1 和 R2 的比值大约是 0.91:1。常见的电阻值组合中R1 100kΩR2 110kΩ 不太常见但 R1 100kΩR2 100kΩ 的分压比是 0.54.2V 对应 2.1V完全在安全范围内。这个组合的好处是电阻值相同采购方便计算也简单。但这里有个关键问题电阻值不能太大也不能太小。太大比如 1MΩ 级别会导致 ADC 输入阻抗不匹配采样时电荷注入不足读数偏低且不稳定太小比如 1kΩ 级别会导致分压电路持续消耗电流对于电池供电设备来说是不可接受的浪费。ESP32 的 ADC 输入阻抗大约在 100kΩ 量级所以分压电阻的并联值R1 和 R2 并联最好远小于这个值但又不能小到让静态电流过大。我通常选择 R1 100kΩR2 100kΩ并联值 50kΩ静态电流约 4.2V / 200kΩ 21μA。这个电流对于大多数锂电池应用来说可以忽略不计同时又能保证 ADC 采样时有足够的驱动能力。如果你想要更精确的分压比可以用 R1 100kΩR2 120kΩ分压比 0.5454.2V 对应 2.29V。或者 R1 100kΩR2 150kΩ分压比 0.64.2V 对应 2.52V稍微偏高但也能用。关键是算清楚你的最大输入电压然后留出至少 0.3V 的余量。2.2 电阻精度与温度漂移的影响普通碳膜电阻的精度通常是 ±5%金属膜电阻可以做到 ±1% 甚至 ±0.1%。分压电路的两个电阻如果精度不够分压比就会偏离设计值导致电压读数系统性偏差。举个例子假设 R1 实际是 95kΩR2 实际是 105kΩ那么实际分压比是 105 / (95 105) 0.525而设计值是 0.5。在 4.2V 输入时实际输出是 2.205V而你以为输出是 2.1V。如果你用设计值去反推电池电压就会得到 4.41V误差 0.21V。对于锂电池来说0.2V 的误差已经很大了可能把 3.5V 误判为 3.7V影响低电报警的准确性。所以我在实际项目中会优先选用 ±1% 精度的金属膜电阻价格也不贵几分钱一个。如果对精度要求更高可以用 ±0.1% 的电阻但一般电池监测没必要到这个级别。温度漂移是另一个容易被忽略的因素。电阻的阻值会随温度变化普通电阻的温度系数在 100ppm/°C 到 200ppm/°C 左右。假设温度变化 40°C阻值变化 0.4% 到 0.8%分压比的变化也在同一量级。对于电池电压监测来说这个影响通常可以接受但如果你的设备工作在极端温度环境下就需要考虑低温漂电阻或者软件温度补偿。还有一个实际问题电阻的长期稳定性。便宜的电阻在潮湿环境下阻值可能会漂移导致电压读数慢慢变化。我遇到过一个小批量产品用了半年后客户反馈电量显示不准最后查出来是分压电阻受潮导致阻值变化。所以如果做产品建议选防潮性能好的电阻或者给分压电路涂三防漆。2.3 滤波电容与输入保护分压输出点直接接到 ADC 引脚中间最好加一个滤波电容。这个电容的作用有两个一是滤掉高频噪声二是给 ADC 采样保持电容提供电荷缓冲。电容值怎么选太小了滤波效果不好太大了响应速度慢。我一般用 100nF 的陶瓷电容并联在 R2 两端也就是分压输出点和 GND 之间。这个值对于电池电压监测来说足够用了因为电池电压变化本身就很慢不需要快速响应。如果你发现 ADC 读数跳动比较厉害可以加大到 1μF。但要注意电容太大会导致上电后需要更长时间才能稳定因为电容充电需要时间。100nF 配合 50kΩ 的并联电阻时间常数是 5ms上电后 25ms 左右就稳定了完全没问题。输入保护方面虽然分压电路已经把电压降下来了但万一电阻虚焊或者短路电池电压可能直接灌到 ADC 引脚上。为了保险可以在 ADC 引脚和分压点之间串一个 1kΩ 的限流电阻再在 ADC 引脚和 GND 之间加一个 3.3V 的稳压二极管或者 TVS 二极管。这样即使分压电路出问题ADC 引脚也不会承受过高电压。不过对于大多数 DIY 项目来说分压电路本身已经足够安全了加保护电路更多是产品级考虑。我自己的经验是只要电阻焊接可靠分压电路出问题的概率很低。但如果你做的是要长期运行的设备加个保护没坏处。3. ESP32 ADC 采样与代码实现3.1 ESP32 ADC 的基本用法与衰减配置ESP32 的 ADC 使用起来不算复杂但有几个坑必须提前知道。首先ESP32 有两个 ADC 模块ADC1 和 ADC2。ADC1 有 8 个通道GPIO32 到 GPIO39ADC2 有 10 个通道GPIO0、GPIO2、GPIO4、GPIO12 到 GPIO15、GPIO25 到 GPIO27。关键问题是ADC2 在 WiFi 开启时无法使用。因为 WiFi 模块会占用 ADC2 的资源如果你同时用 WiFi 和 ADC2读数会完全不可靠。所以做电池监测时一定要用 ADC1 的引脚。我通常选 GPIO34、GPIO35、GPIO36 或 GPIO39这几个引脚都是输入专用没有其他复用功能用起来最省心。注意 GPIO34 到 GPIO39 没有内部上拉或下拉电阻如果你需要分压电路外部电阻已经提供了直流通路不需要额外上拉。衰减配置方面用 Arduino 框架的话可以这样设置#include driver/adc.h void setup() { adc1_config_width(ADC_WIDTH_BIT_12); // 12位分辨率0-4095 adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); // GPIO34 }ADC_ATTEN_DB_11 对应的理论满量程是 3.3V 左右但实际特性曲线并不是线性的。在低电压段0.5V 以下和接近满量程时非线性比较明显。所以前面才建议把分压输出控制在 2.0V 到 2.5V 之间这个区间的线性度相对较好。读取 ADC 值的代码int adc_raw adc1_get_raw(ADC1_CHANNEL_6); float voltage_at_adc adc_raw / 4095.0 * 3.3; // 粗略换算但这样算出来的电压误差很大因为 3.3V 只是标称值实际参考电压可能在 3.0V 到 3.6V 之间波动而且每个芯片都不一样。所以必须做校准。3.2 多点校准与线性拟合ESP32 的 ADC 校准有两种思路一种是查表法用 ESP-IDF 提供的esp_adc_cal库另一种是自己做多点校准拟合一条直线。esp_adc_cal库用起来很方便它内部存储了每个芯片的校准参数可以自动修正非线性。但它的校准是基于内部参考电压的精度有限通常误差在 ±2% 左右。对于电池监测来说这个精度勉强够用但如果你想要更准就得自己校准。我的做法是用可调电源给分压电路输入几个已知电压比如 3.0V、3.5V、4.0V、4.2V记录每个电压下的 ADC 原始值然后用最小二乘法拟合一条直线。这样得到的校准系数是针对你手上这块芯片和这个分压电路的精度可以做到 ±0.5% 以内。具体操作步骤用可调电源代替电池输出 3.0V记录 ADC 原始值比如 2450输出 3.5V记录 ADC 原始值比如 2860输出 4.0V记录 ADC 原始值比如 3270输出 4.2V记录 ADC 原始值比如 3430然后用这些数据点拟合直线。在代码里可以这样实现// 校准系数根据实际测量计算 const float slope 0.00122; // 每个ADC值对应的电压 const float intercept 0.012; // 截距 float get_battery_voltage() { int adc_raw adc1_get_raw(ADC1_CHANNEL_6); float voltage_at_adc adc_raw * slope intercept; float battery_voltage voltage_at_adc * (R1 R2) / R2; return battery_voltage; }这里的 slope 和 intercept 需要根据你的实际测量数据计算。计算方法很简单用 Excel 或者 Python 做个线性回归就行。如果你不想自己算也可以用两点校准测两个电压点解二元一次方程组。3.3 软件滤波与多次采样即使做了校准单次 ADC 读数仍然会有跳动尤其是在 WiFi 开启或者有其他高频干扰的情况下。所以必须做软件滤波。最简单的滤波方法是多次采样取平均float get_battery_voltage_filtered() { const int samples 32; long sum 0; for (int i 0; i samples; i) { sum adc1_get_raw(ADC1_CHANNEL_6); delayMicroseconds(100); } int adc_avg sum / samples; float voltage_at_adc adc_avg * slope intercept; return voltage_at_adc * (R1 R2) / R2; }取 32 次平均可以把随机噪声降低到原来的 1/√32 ≈ 1/5.6。如果你发现读数还是跳可以增加到 64 次或 128 次。但采样次数太多会占用 CPU 时间对于电池监测来说每秒采一次就够了所以 128 次平均也完全没问题。除了平均滤波还可以用中值滤波或者一阶低通滤波。中值滤波适合去除脉冲干扰一阶低通滤波适合平滑缓慢变化的信号。我一般用平均滤波就够了简单有效。如果你想要更高级的滤波可以试试卡尔曼滤波但对于电池电压监测来说有点杀鸡用牛刀。我试过在 ESP32 上跑卡尔曼滤波效果确实好但代码复杂度和调试难度都上去了不太划算。还有一个细节ADC 采样时最好关闭 WiFi 或者把 WiFi 任务优先级调低否则 WiFi 发射时的电流突变会通过电源耦合到 ADC 上导致读数跳变。我实测过WiFi 开启时 ADC 读数的标准差大约是 WiFi 关闭时的 3 到 5 倍。如果你的设备必须同时开 WiFi那就只能靠多次采样和滤波来压制噪声了。4. 常见问题与避坑指南4.1 ADC 读数不准的排查思路ADC 读数不准是最常见的问题可能的原因有很多。我整理了一个排查表按可能性从高到低排列问题现象可能原因排查方法解决方案读数整体偏高或偏低分压电阻精度不够用万用表测实际阻值换 ±1% 电阻重新校准读数跳动大电源噪声或 WiFi 干扰关闭 WiFi 对比测试增加滤波电容多次采样读数非线性ADC 衰减配置不当检查衰减档位改用 ADC_ATTEN_DB_11控制输入范围读数始终为 0 或 4095引脚配置错误或电路断路检查引脚号和焊接确认使用 ADC1 引脚重新焊接读数随温度变化电阻温漂或参考电压漂移加热/冷却测试换低温漂电阻软件温度补偿上电后读数慢慢变化滤波电容充电观察稳定时间减小电容值或等待稳定我踩过最坑的一次是用了 ADC2 的引脚GPIO25单独测试时读数正常一开 WiFi 就完全乱套。后来查资料才知道 ADC2 和 WiFi 冲突换成 GPIO34 后问题立刻消失。这个坑在 ESP32 社区里非常常见新手几乎必踩。另一个常见问题是分压电阻选得太大。我有一次为了省电用了 1MΩ 和 1MΩ 的分压电阻结果 ADC 读数比实际值低了 0.3V 左右。原因是 ADC 输入阻抗和分压电阻形成了额外的分压导致实际送到 ADC 采样保持电容的电压偏低。换成 100kΩ 后问题解决。所以分压电阻不要超过 200kΩ这是经验值。4.2 锂电池电压与电量的对应关系监测到电池电压后下一步通常是把电压转换成电量百分比。但锂电池的电压和电量并不是线性关系而是一条 S 形曲线。4.2V 是满电3.0V 是空电但中间的变化不是均匀的。一个粗略的对应关系如下电池电压大致电量说明4.20V100%满电4.10V90%刚放电不久3.95V70%中间平台区3.80V50%标称电压附近3.65V30%开始明显下降3.50V15%低电警告3.30V5%即将关机3.00V0%空电需立即充电注意这个表是近似值不同厂家、不同放电倍率的锂电池曲线会有差异。而且放电电流越大电压被拉得越低所以大电流放电时读到的电压会偏低。如果你的设备工作电流变化很大最好在电流稳定的时候采样或者做电流补偿。我在实际项目中一般会设置几个阈值3.5V 触发低电警告3.3V 触发自动休眠或关机。这样即使电压曲线有偏差也不会导致电池过放。另外锂电池在 3.0V 以下继续放电会加速老化所以 3.0V 是绝对底线不要等到 2.8V 才关机。4.3 分压电路的功耗优化对于电池供电设备来说分压电路的静态功耗也是需要考虑的。100kΩ 100kΩ 的分压电路在 4.2V 时消耗约 21μA。这个电流看起来很小但如果你的设备大部分时间在休眠休眠电流可能只有几十微安分压电路的 21μA 就占了很大比例。优化方法有几种一是增大分压电阻比如用 1MΩ 1MΩ静态电流降到 2.1μA但前面说过电阻太大会导致 ADC 读数不准。二是用 MOSFET 控制分压电路的通断只在需要测量的时候才接通。三是用低功耗的电压监测芯片代替分压电路比如 TI 的 BQ27441 或者 Maxim 的 MAX17048这些芯片自带库仑计精度更高但成本也更高。我一般用第二种方法用一个 N 沟道 MOSFET 控制分压电路的下端接地测量时拉高 GPIO 让 MOSFET 导通测完拉低 GPIO 断开。这样分压电路只在测量时消耗电流平均功耗可以降到 1μA 以下。MOSFET 选 2N7002 就行便宜好用。不过要注意MOSFET 导通时会有导通电阻这个电阻会和 R2 串联影响分压比。2N7002 的导通电阻大约几欧姆相对于 100kΩ 的 R2 来说可以忽略不计。但如果你用大电流 MOSFET导通电阻更小影响更小。5. 完整代码实现与调试记录5.1 硬件连接与初始化先说一下完整的硬件连接。以 ESP32 DevKit 为例电池正极接 R1 的一端R1 的另一端接 R2 的一端同时接 ESP32 的 GPIO34R2 的另一端接 GND在 GPIO34 和 GND 之间并联 100nF 电容电池负极接 GND如果你用 MOSFET 控制分压电路把 R2 的接地端接到 MOSFET 的漏极MOSFET 的源极接 GND栅极接一个 GPIO比如 GPIO25通过 10kΩ 电阻上拉到 3.3V再通过另一个 GPIO 控制。代码初始化部分#include driver/adc.h #define ADC_CHANNEL ADC1_CHANNEL_6 // GPIO34 #define R1 100000.0 #define R2 100000.0 #define CAL_SLOPE 0.00122 #define CAL_INTERCEPT 0.012 void setup() { Serial.begin(115200); adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_DB_11); // 如果用了 MOSFET 控制 // pinMode(25, OUTPUT); // digitalWrite(25, LOW); // 默认断开 }5.2 电压读取与串口输出完整的电压读取函数float read_battery_voltage() { // 如果用了 MOSFET先导通 // digitalWrite(25, HIGH); // delayMicroseconds(100); // 等待稳定 const int samples 64; long sum 0; for (int i 0; i samples; i) { sum adc1_get_raw(ADC_CHANNEL); delayMicroseconds(50); } int adc_avg sum / samples; // 如果用了 MOSFET测完断开 // digitalWrite(25, LOW); float voltage_at_adc adc_avg * CAL_SLOPE CAL_INTERCEPT; float battery_voltage voltage_at_adc * (R1 R2) / R2; return battery_voltage; } void loop() { float vbat read_battery_voltage(); Serial.print(Battery Voltage: ); Serial.print(vbat, 3); Serial.println( V); // 计算电量百分比粗略 int percent map(vbat * 100, 300, 420, 0, 100); percent constrain(percent, 0, 100); Serial.print(Battery Level: ); Serial.print(percent); Serial.println( %); delay(1000); }这段代码每秒钟读一次电池电压并通过串口输出。你可以用串口监视器查看数据也可以用蓝牙或者 WiFi 把数据传到手机或服务器上。5.3 校准实操与数据记录校准是保证精度的关键步骤。我的做法是用可调电源代替电池输出 3.0V记录串口打印的 ADC 原始值需要临时修改代码打印原始值依次输出 3.3V、3.6V、3.9V、4.2V记录对应的 ADC 原始值用 Excel 做散点图添加趋势线显示公式把公式的斜率和截距填入代码我最近一次校准的数据如下输入电压ADC 原始值计算电压误差3.00V24482.998V-0.002V3.30V26953.301V0.001V3.60V29423.603V0.003V3.90V31883.902V0.002V4.20V34354.201V0.001V可以看到校准后误差控制在 ±0.003V 以内对于电池监测来说完全够用了。这个精度甚至比很多成品的电池监测模块还要好。校准的时候要注意可调电源的输出要用万用表实测不要相信电源本身的显示因为电源显示也可能有误差。另外校准时的温度和实际使用温度尽量接近否则温漂会影响精度。5.4 实际运行中的问题与解决在实际运行中我遇到了几个问题这里分享一下解决过程。第一个问题是 WiFi 开启后 ADC 读数跳动明显增大。我的设备需要每 10 分钟通过 WiFi 上传一次数据上传时电流从 20mA 瞬间跳到 200mA 以上导致电源电压波动ADC 读数也跟着跳。解决方法是在 WiFi 上传前先读一次电池电压上传完成后等 100ms 再读一次取两次的平均值。另外在电源端加了一个 100μF 的电解电容和 100nF 的陶瓷电容缓解电流突变的影响。第二个问题是长时间运行后电压读数慢慢偏低。查了半天发现是分压电阻受潮导致阻值变化。后来给分压电路涂了一层三防漆问题解决。如果你做的是户外设备这个问题一定要提前预防。第三个问题是 ADC 读数偶尔出现 0 或 4095 的极端值。这是典型的脉冲干扰可能是静电或者电源尖峰导致的。解决方法是在软件里加一个限幅滤波如果本次读数和上次读数相差超过 0.5V就丢弃本次读数用上次的值代替。这个简单的逻辑可以过滤掉大部分突发干扰。float last_voltage 0.0; float read_battery_voltage_safe() { float v read_battery_voltage(); if (fabs(v - last_voltage) 0.5 last_voltage 0.0) { return last_voltage; // 丢弃异常值 } last_voltage v; return v; }这个限幅滤波在实际项目中非常有用尤其是设备工作在电机、继电器等干扰源附近时。我试过不加限幅滤波偶尔会出现电量从 80% 突然跳到 0% 的情况加了之后就没再出现过。6. 进阶优化与扩展思路6.1 用内部参考电压提高精度ESP32 的 ADC 参考电压默认是 VDDA约 3.3V但这个电压会随电源波动。如果你的设备用锂电池供电电池电压从 4.2V 降到 3.0V 的过程中如果经过 LDO 稳压到 3.3V那 VDDA 是稳定的。但如果直接用电池供电ESP32 工作电压范围是 2.2V 到 3.6VVDDA 就会随电池电压变化导致 ADC 读数完全不可信。解决方法是用 ESP32 内部的 1.1V 参考电压esp_adc_cal库支持或者用外部基准电压芯片。内部 1.1V 参考电压的精度大约 ±1%比 VDDA 稳定得多。用esp_adc_cal库的代码如下#include esp_adc_cal.h esp_adc_cal_characteristics_t *adc_chars; adc_chars calloc(1, sizeof(esp_adc_cal_characteristics_t)); esp_adc_cal_value_t val_type esp_adc_cal_characterize( ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, adc_chars); uint32_t voltage esp_adc_cal_raw_to_voltage(adc_raw, adc_chars);这样得到的电压值是基于内部参考电压的不受 VDDA 波动影响。但内部参考电压本身也有误差所以还是建议做一次外部校准。6.2 电池电量百分比的高级计算前面用的线性映射计算电量百分比太粗糙了实际锂电池的放电曲线是非线性的。更准确的做法是用查表法把电压-电量曲线分成多个区间每个区间用线性插值。int voltage_to_percent(float v) { const float voltages[] {4.20, 4.10, 3.95, 3.80, 3.65, 3.50, 3.30, 3.00}; const int percents[] {100, 90, 70, 50, 30, 15, 5, 0}; const int n 8; if (v voltages[0]) return 100; if (v voltages[n-1]) return 0; for (int i 0; i n - 1; i) { if (v voltages[i] v voltages[i1]) { float ratio (v - voltages[i1]) / (voltages[i] - voltages[i1]); return percents[i1] ratio * (percents[i] - percents[i1]); } } return 0; }这个查表法比线性映射准确得多尤其是在 3.8V 到 3.6V 的平台区线性映射会严重高估电量。我实测过查表法在平台区的误差可以控制在 5% 以内而线性映射的误差可能超过 20%。如果你想要更精确的电量计算可以用库仑计芯片比如 TI 的 BQ27441 或者 Maxim 的 MAX17048。这些芯片通过测量电流对时间积分来计算电量精度可以做到 1% 以内。但成本比电阻分压高不少适合对电量精度要求高的产品。6.3 低功耗设计与休眠唤醒对于电池供电设备低功耗是永恒的话题。除了前面说的用 MOSFET 控制分压电路通断还可以让 ESP32 在两次测量之间进入深度休眠。ESP32 的深度休眠电流可以低到 10μA 左右加上分压电路的 2μA整体休眠电流可以控制在 15μA 以内。如果每 10 分钟唤醒一次测量电压平均电流大约 15μA (测量电流 × 测量时间 / 休眠周期)。测量时电流约 40mA测量时间 10ms休眠周期 600s平均电流增加 40mA × 0.01s / 600s ≈ 0.67μA。总平均电流约 16μA对于 2000mAh 的电池来说理论续航超过 10 年当然实际受电池自放电限制可能一两年。深度休眠的代码esp_sleep_enable_timer_wakeup(600 * 1000000); // 600秒 esp_deep_sleep_start();唤醒后 ESP32 会重新启动所以需要在 setup 里判断唤醒原因如果是定时唤醒就执行测量然后再次进入休眠。注意深度休眠会丢失 RAM 数据所以电量百分比需要存在 RTC 内存或者 Flash 里。RTC 内存的使用RTC_DATA_ATTR float last_voltage 0.0; RTC_DATA_ATTR int last_percent 0;这两个变量在深度休眠后不会丢失可以用来保存上次的测量结果。6.4 从电压监测到完整 BMS 的扩展电压监测只是电池管理的第一步。如果你想要更完整的电池管理可以扩展以下功能电流监测用霍尔电流传感器或者采样电阻 运放测量充放电电流温度监测用 NTC 热敏电阻或者 DS18B20监测电池温度均衡管理多节电池串联时用被动均衡电路让各节电压保持一致保护电路过充、过放、过流、短路保护通常用专用的保护 IC这些功能加在一起就是一个完整的 BMS电池管理系统。对于大多数 DIY 项目来说电压监测 低电保护已经够用了。但如果你做的是电动工具、储能系统或者电动车就需要考虑更完整的方案。我自己从最简单的分压电路开始逐步加上了电流监测和温度监测最后做成了一个可以显示电压、电流、温度、电量的完整电池监测模块。整个过程踩了不少坑但也学到了很多。如果你也在做类似的项目建议先从电压监测开始跑通了再逐步扩展不要一上来就搞大而全的方案。最后分享一个我在调试过程中总结的小技巧每次修改分压电阻或者校准参数后用可调电源从 3.0V 慢慢升到 4.2V每隔 0.1V 记录一次读数画成曲线。这样可以直观地看到线性度和误差分布比单点校准靠谱得多。我一般会记录 13 个点3.0V 到 4.2V步进 0.1V用 Excel 画图一眼就能看出问题。这个习惯帮我发现了好几次电阻选型不当和校准参数错误的问题。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

嵌入式驱动开发实战:设备树、固件加载与调试全解析 2026/9/28 18:54:27

嵌入式驱动开发实战:设备树、固件加载与调试全解析

1. 嵌入式驱动开发到底在忙什么很多人对嵌入式驱动开发这个岗位有误解,觉得就是对着芯片手册抄寄存器、写写初始化代码,或者认为它跟应用层开发比起来更“底层”所以更枯燥。我做了十多年嵌入式,从早期的裸机开发到后来完整的Linux BSP维护&a…

阅读更多 →
在线教程丨Qwen3-Coder-Flash 配 TaoToken:settings.json 骨架与 Agentic 编程验证 2026/9/28 18:54:27

在线教程丨Qwen3-Coder-Flash 配 TaoToken:settings.json 骨架与 Agentic 编程验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Dify + Nacos 配置 TaoToken:MCP 集成与 Prompt 迭代的敏捷开发秘籍 2026/9/28 18:54:26

Dify + Nacos 配置 TaoToken:MCP 集成与 Prompt 迭代的敏捷开发秘籍

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
高血压的术语大全的庖丁解牛 2026/9/28 18:54:26

高血压的术语大全的庖丁解牛

总纲:高血压,是体循环动脉血管内压力持续升高的心血管综合征。很多人误以为高血压头晕头痛,没有不舒服就不用管。读懂本质:高血压被称为无声杀手,早期大多无症状;它不是单纯血压数字偏高,长期高…

阅读更多 →
【Linux操作系统学习】mkdir、cp、rm、mv命令 2026/9/28 18:54:26

【Linux操作系统学习】mkdir、cp、rm、mv命令

mkdir A 创建A文件(mkdir:创建指令) mkdir -p B/C/D 创建深度文件(B>C>D) mkdir shy{1…10} 创建多个文件(创建文件shy1到shy10,十个文件) touch /home/jiwang/A /2.txt (在 /home/jiwang/ 目…

阅读更多 →
定制多连接器线缆组件全流程指南:设计选材与测试要点 2026/9/28 18:54:20

定制多连接器线缆组件全流程指南:设计选材与测试要点

上午九点刚过,设备工程部的老周就夹着一捆线进了我办公室:“这个月的第二回了,新装的四台伺服电机,编码器线、抱闸线、电源线加起来十几根,在走线槽里缠成一窝,脉冲丢帧、干扰乱飘,客户已经拍了…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉