Battery monitoring on ESP32

Hi All,

New at the ESP32 (Thing).

I would like to monitor the battery level, and give a warning to the user when the battery is too low. It sounds like the VBat pin is what I need to monitor, but I connect it to A0, it does not seem to vary with battery life/level. There is a EN pin that sounds important, but I cannot figure this out from a global search.

Can anyone help?

Thanks!

Hi CENlab,

There are a few issues you are going to run into trying to monitor the battery level using analogRead tied to the VBATT pin. The first and most important problem is single-cell battery voltage varies from ~3V at fully discharged and 4.2V at full charge and the max voltage the ESP32 can safely handle is 3.3V so you’ll want to drop that voltage to something the ADC can effectively read. Most likely, you’re seeing some noisy results where the ADC values are maxed out (~4096. The default resolution is 12 bit) since your battery voltage is rarely dipping below 3.3V. In order to connect that to an analog pin, you’ll need to use a [voltage divider to drop the battery voltage range so the max does not exceed 3.3V and you also have access to a wider range of the ADC pin.

The other issue is according to [some users the analogRead function is noisy and non-linear. I have not personally tested that and the topic linked above is now over 2 years old so the folks at Espressif may have updated the [ESP32 Arduino Core to make that function more reliable so I think it would still possibly work for you if you’re just trying to get a rough estimate of your battery’s charge level. [This header file for ESP32 ADC will have some helpful notes on setting up an analogRead circuit on an ESP32 Thing.

I hope this helps explain some of the pitfalls you may run into (or already have) and gives you some ideas on how to revise your circuit and code to get better battery level results from your ESP32 Thing.](arduino-esp32/cores/esp32/esp32-hal-adc.h at master · espressif/arduino-esp32 · GitHub)](GitHub - espressif/arduino-esp32: Arduino core for the ESP32)]([Answered] What are the ADC input ranges? - ESP32 Forum)](https://learn.sparkfun.com/tutorials/voltage-dividers)

Thanks TS-Mark!

You are right… just looking at voltage is not the right way to go.

After some trial and error, looking at different ways of doing it, I converged on the following, which works very well (see test below). This is inspired by this excellent video:

https://www.youtube.com/watch?v=3yHRrPDczK4

Hardware:

  • Get a Fuel Gauge circuit (FG: got the Sparkfun TOL-10617). This is a bit of money, but it will save you a lot of headaches. It is based around the MAX 17043 fuel gauge, which is I2C accessible.

  • I use a ESP32 WROOM (ESP: but I don’t think the type matters much)

  • Connect the VBAT and ground of the ESP to the + and - of the FG (respectively)

  • Connect the SDA (pin23) and SCL (pin 22) of the ESP to the SDA and SCL pins of the FG (respectively)

  • Connect the ground of the FG to the ground of the ESP

Software:

Download/Install the I2C MAX 17043 library from Github as a ZIP file

https://github.com/lucadentella/ArduinoLib_MAX17043

(but see also https://github.com/awelters/LiPoFuelGauge)

using the Arduino IDE install it (Sketch>Include Library > Add .ZIP Library)

and as far as code, basically, you need the following:

#include “MAX17043.h” // fuel gauge

#include “Wire.h”

MAX17043 batteryMonitor;

setup(){

Wire.begin(); // Fuel Gauge

batteryMonitor.reset();

batteryMonitor.quickStart();

}

loop(){

float soc = batteryMonitor.getSoC();

float voltage= batteryMonitor.getVCell();

Serial.printf(“%d: BatteryTest SOC=%.1f %%, Voltage=%.1f V\n”, idx,soc, voltage);

delay(10000);

}

Here is a battery run-down test. For this I used one ESP32WROOM wifi connected using painless mesh to a ESP32 Thing. The WROOM is sending a LiPo battery (DTP603450, 3.7V 1000mAh) readout every 10 seconds to the ESP32Thing which sends it through its COM link to a Labview program that stores the readout in an Excel spreadsheet (part of a larger program, not important here). You can see the discharge, then the WROOM stops working (overnight run), then the charge rate (plugged the WROOM into the USB in the morning).

Conclusions: In this particular setup: no need to query the battery more than 1/minute (every 2 minutes is fine), alert the user at 30% and critical at 20%. Time to recharge:~3.3hours.

Hope this is useful to everyone!

Comments/improvement welcome… Please post here.

BatteryTest.pdf (406 KB)