Monitoring LiPo battery voltage with Wemos D1 minibattery shield and Thingspeak

There are a million reasons why you would want to monitor the Battery voltage of  your Battery fed ESP8266. I will illustrate it with a Wemos D1 mini and the Battery shield

Wemos D1 Mini Battery shield

I am using a small 720 mAh LiPo cel. If I just leave the Wemos access the internet continuously it will last 6.5 hours, but for this example I will put the Wemos in Deepsleep for a minute, then read the battery voltage and upload that to Thingspeak.
You only need to make a few connections:
First, connect RST with GPIO16 (that is D0 on the Wemos D1 mini). This is needed to let the chip awake from sleep.
Then connect the Vbat  through a 100k resistor to A0.

So why a 100 k resistor?

Well the Wemos D1 mini already has an internal voltage divider  that connects the A0 pin to the ADC of the ESP8266 chip. This is a 220 k resistor over a 100 k resistor

Wemos D1 Internal Voltage divider
Wemos D1 Internal Voltage divider

By adding a 100k , it will in fact be a total resistance  of 100k+220k+100k=420k.
So if the Voltage of a fully loaded Cell would be 4.2 Volt, the ADC of the ESP8266 would get 4.2 * 100/420= 1 Volt

1 Volt is the max input to the ADC and will give a Raw reading of 1023.

The True voltage  then can be calculated by:
raw = AnalogRead(A0);voltage =raw/1023;
voltage =4.2*voltage;
Ofcourse you could also do that in one step, but I like to keep it easy to follow.

Wemos Battery monitoring
Wemos Battery monitoring

If you do use this possibility, do realise that the resistors drain the battery as well with a constant 10uA (4.2V/420 000ohm). The powerconsumption of an ESP8266 in deepsleep is about 77uA. With the battery monitor this would be 87uA, which is a sizeable increase. A solution could be to close off the Vbat to the A0 with a transistor, controlled from an ESP8266 pin

A program could look like this:


 * Wemos battery shield, measure Vbat
 * add 100k between Vbat and ADC
 * Voltage divider of 100k+220k over 100k
 * gives 100/420k
 * ergo 4.2V -> 1Volt
 * Max input on A0=1Volt ->1023
 * 4.2*(Raw/1023)=Vbat

// Connect RST en gpio16 (RST and D0 on Wemos)
#include <ESP8266WiFi.h>
unsigned int raw=0;
float volt=0.0;
// Time to sleep (in seconds):
const int sleepTimeS = 60;

void setup() {
  Serial.println("ESP8266 in normal mode");
  const char* ssid     = "YourSSID";
  const char* password = "YourPW";
  const char* host = "";
  const char* writeAPIKey="YourAPIkey";
  // put your setup code here, to run once:
  pinMode(A0, INPUT);
  raw = analogRead(A0);
//  Connect to WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  String v=String(volt);// change float into string
  // make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
  String url = "/update?key=";
  url += writeAPIKey;
  url += "&field6=";// I had field 6 still free that's why
  url += String(volt);
  url += "\r\n";
// Send request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");

   Serial.println("ESP8266 in sleep mode");
   ESP.deepSleep(sleepTimeS * 1000000);              

void loop() {
  //all code is in the Setup


10 thoughts on “Monitoring LiPo battery voltage with Wemos D1 minibattery shield and Thingspeak

  1. Depending of course on what your project is required to do, my advice would be to put the thing in the deepest possible sleep once it hits the low end of the battery voltage, maybe only to sound a piezo buzzer for say 200 ms when it shortly wakes up. That will be the safest bet to keep your LiPo alive as long as possible. The cell shown probably has a low voltage protection circuit build in though. Still, the warning is helpful.

    Sidenote: The other day I accidentally miswired a cell like that (600 mA version), reversed polarity. In a few ms, the magic smoke appeared and the cell seemed to have lost quite a bit of it’s capacity. Hard to believe things going south that fast. Turned out the protection circuit had fried a bit. Without it, the cell runs fine with 550 mAh betweem 3.0 and 4.2 volt.

    1. I agree. It is quite easy to do that. My intention ofcourse is that it will not get too low because of a solar cell that is to provide enough input.
      esp.deepsleep is as far as i know the deepest sleep, but when the battery voltage hits 3.0 it might be wise to let the deepsleep last as long as possible and do no uploads anymore.
      I am not sure at what voltage the esp stops working, but it does still work at 3Volt, and will proceed to discharge the cell.
      After 3.5 days my cell has discharged till 3.7 Volt. Obviously that still can be better, but the battery shield is not the most efficient. I will see how long it will take for the last 0.7Volt. Will repeat it with a bare ESP8266-12

      Yes, some components really dont like reversed potential, but seems you still had some luck

  2. From “the guy with the Swiss accent” I understood there is a setting that the ADC on the ESP8266 reports Vcc without any external components. Might save two resistors and a few uA. I think the episode where he experimented with a Li-Ion button cell.

    1. that is true, but that reports the Vcc on the board, which under normal circumstances would be 5 Volt, whereas I wanted to measure the direct battery voltage that even when lower, ideally should still give 5 Volts on the board. But I will check his video to make sure. Thanks
      Having said that… “the guy with the Swiss accent” is a hero

      1. Are you sure? AFAIK it reports the Vvv on the bare ESP module (so shoud be 3.3-ish). Now I know you want the battery voltage, and after boosting and then dropping to 3.3, all is lost. This is IMHO very usable if you hook up an ESP to a Lipo with just a good LDO. Agreed about “the guy”!!

      2. my mistake. I mean the VCC on the esp indeed.
        Needless to state the battery shield is not a good low power option at all.

  3. Hi,

    i added the 100k resistor like explained above, but there is some deviation between the readings from the esp8266 and by manually checking the voltage with the multimeter. In my setup a 18650 battery with 3000mAh is used, powering a wemos d1 mini with dht22-shield and battery shield. The 18650 had a voltage of 3.53V when i measured with the multimeter, the reading from A0 was 3.24V. Currently i am charging, at 4.09V (Multimeter) A0 reports 3.88V. So there is some inaccuracy betwen 0.21V and 0.27V. While i could “fix” that via adding an offset, i’m interested in the reason behind this.

    1. could be many reasons. Your multimeter might not be accurate and then again there might be a tolerance in the resistor(s)
      What the software and hardware does is based on calculation. The A0 needs 1 Volt. So ideally a 100k resistor on top of the internal voltage divider should give 1 V at A0 when the resistor is fed with 4.2 Volt. However if any of these resistors is not the exact value it is labelled for, the outcome is ofcourse different

    1. The connector on MY lipo battery is the standard lipocell connector. I think it is called a JST-PH. The shield however has a different connector, I think that is a JST-XH

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s