Battery Monitoring on the Adafruit Huzzah32 ESP32 with MongooseOS

Posted on December 27, 2017

Adafruit is undoubtedly the most important company for Makers and IoT builders.  Not only does Adafruit make high quality boards, they also supply the open source drivers we require to make these great components actually work.  Given all that Adafruit does for us, its only fair that we pay a little more.  While cheapo ESP32 boards can be purchased on Amazon for about $12 and you can find sketchy deals on AliExpress for as little as $6, the Adafruit Huzzah32 Feather Board is a pricey $20, but the build quality is excellent and it features a built in LiPo connection and charger.

If your using a battery, you naturally want to know what its capacity is.  Thankfully Adafruit has our backs and exposes the battery voltage on Pin 35, a non-exposed ADC pin that we can read from.  Adafruit notes on the Power Management page:

If you’re running off of a battery, chances are you wanna know what the voltage is at! That way you can tell when the battery needs recharging. Lipoly batteries are ‘maxed out’ at 4.2V and stick around 3.7V for much of the battery life, then slowly sink down to 3.2V or so before the protection circuitry cuts it off. By measuring the voltage you can quickly tell when you’re heading below 3.7V

Since the ESP32 has tons of ADC pins, we ‘sacrifice’ one for Lipoly battery monitoring. You can read half of the battery voltage off of A13. Don’t forget to double the voltage you read, since there is a divider.

That A13 pin is actually pin 35, on Arduino we’d use an AnalogRead() but on MongooseOS we’ll use the ADC.read() function.  To do this you’ll need to ensure your firmware includes the ADC library, add it to your projects mos.yml file under the libs: section like so:

libs:
  # ... libraries
  - origin: https://github.com/mongoose-os-libs/adc

Now you can use mJS to read the voltage. Here is some example code that would normally be embedded into a project (placed in init.js):

// Huzzah32 Battery Voltage Code <benr@cuddletech.com>
load('api_timer.js');
load("api_adc.js");

let battery = 35;  // Huzzah32 Battery Voltage is on Pin 35
ADC.enable(battery);

// Read and display battery voltage every 5 seconds:
Timer.set(5000, true, function() {
    let battery_voltage = (ADC.read(battery)/4095)*2*3.3*1.1;
    print("DEBUG: Battery Voltage is", battery_voltage, "V");
}, null);

When you read the ADC you’ll get a value like 2339. The ADC value is a 12-bit number, so the maximum value is 4095 (counting from 0). To convert the ADC integer value to a real voltage you’ll need to divide it by the maximum value of 4095, then double it (note above that Adafruit halves the voltage), then multiply that by the reference voltage of the ESP32 which is 3.3V and then vinally, multiply that again by the ADC Reference Voltage of 1100mV.  The result is that the 2339 value is decoded as 4.1461V on the battery.  You can verify this by sticking a multimeter into the BAT & GND pins, which measures 4.133V.  So we’re not exact but damned close.

Huzzah32 LiPo Monitoring

In this picture you can see this code at play in my environmental monitor where I’m outputting the battery voltage to an OLED display while monitoring the battery voltage via a Fluke Multimeter.  I let the battery discharge for 18 hours watching the voltages fall together and so far I’m happy with my calculation.