Overview
In this project, we will build a DIY LiPo Battery Charger with IoT Voltage/SoC Monitoring System using ESP8266 Board. The circuit board will charge a single cell Lithium-ion or Polymer Battery. Apart from charging the device will send the Battery Voltage & Battery Percent (SoC) data to Thingspeak Server online.
The battery, being a device’s primary power source, requires constant voltage monitoring to prevent damage or system failure from improper charging/discharging. This task is handled by the Battery Management System (BMS) found in most electrical/electronic devices, which keeps track of the battery’s voltage, current, temperature, and has an auto cut-off system, ensuring the safe usage of Lithium-Ion or Lithium Polymer batteries. Previously, BMS merely monitored battery conditions and alerted users through battery indicators, but with the advent of the Internet of Things, users can now receive remote notifications and check their battery status from anywhere using smartphones or computer dashboards.
In this project, we designed our own PCB and utilized the ESP8266 raw chip along with a Low Power LDO and a Battery Charger chip for component assembly. This Battery Charger chip, capable of charging the battery, encompasses all BMS features. Given the device’s low power consumption, it uses the battery power to transmit data to the Thingspeak Server, visually representing the battery’s charging and discharging status. So lets build this DIY LiPo Battery Charger with IoT Voltage Monitoring System.
You may refer to some of our previous similar article before moving ahead with this project:
- Design your own ESP Board for Battery Powered IoT Applications
- IoT Based Battery Status Monitoring System using ESP8266
- IoT Based 12V Battery Monitoring System with ESP8266
- 5V 3A USB Charger
Bill of Materials
We need following components to build this DIY LiPo Battery Charger Board.
| S.N. | Components | Designator | Footprint | Quantity |
|---|---|---|---|---|
| 1 | ESP-12E | U1 | WIFIM-SMD_ESP-12E | 1 |
| 2 | MCP73831 | U3 | SOT-23-5 | 1 |
| 3 | OLED Display (Optional) | OLED | 0.96 OLED | 2 |
| 4 | LDO HT7333 | U4 | SOT-89-3 | 3 |
| 5 | Header Female-2.54_2x3 | H1 | HDR-TH_6P-P2.54 | 1 |
| 6 | Header Male-2.54_2x3 | GPIO,PROG | HDR-TH_6P-P2.54 | 2 |
| 7 | Reset Switch | FLS,RST | SWITCH SMD 3X4X2MM | 2 |
| 8 | ON/OFF Switch | SW1 | MINI TOGGLE (1P2T) SPDT SLIDE SWITCH | 1 |
| 9 | Micro USB Female | USB1 | MICRO-USB-SMD_5P | 1 |
| 10 | Battery Connector | CN1 | 2 PIN JST | 1 |
| 11 | LED | LED2 | LED-0805 | 1 |
| 12 | Transistor BC847 | Q1,Q2 | SOT23 | 2 |
| 13 | Resistor 330E | R6 | R0805 | 1 |
| 14 | Resistor 20K | R11 | R0805 | 1 |
| 15 | Resistor 2K | R10 | R805 | 1 |
| 16 | Resistor 100K | R12 | R0805 | 1 |
| 17 | Resistor 12K | R1,R2,R3,R4,R5 | R0805 | 5 |
| 18 | Resistor 470E | R9 | R805 | 1 |
| 19 | Resistor 22K | R7,R8 | R0805 | 2 |
| 20 | Capacitor 10uF | C3,C4 | C0805 | 2 |
| 21 | Capacitor 0.1uF | C1 | C0805 | 1 |
| 22 | Capacitor 470pF | C2 | C0805 | 1 |
| 23 | Capacitor 4.7uF | C5,C6 | C0805 | 2 |
| 24 | Battery 3.7V, 500mAh | 1 | ||
| 25 | FTDI Module | 1 | ||
| 26 | Jumper Wires (M-to-F) | 6 |
Lithium-Ion/Polymer Batteries
Lithium-ion batteries are popular power sources due to their high energy density, long lifespan, and low self-discharge rate. They work through the movement of lithium ions from the negative to the positive electrode during discharge and vice versa during charging. However, they require a battery management system for safe operation, and overcharging can lead to heat generation and potential explosion.
On the other hand, lithium-polymer batteries, a subtype of lithium-ion, offer the additional advantages of lightweight, flexibility, and a thinner profile. They have a gel-like electrolyte which allows them to be encased in flexible pouches, enabling diverse shapes and sizes. Despite these benefits, they usually have a slightly lower energy density and shorter lifespans than standard lithium-ion batteries.
Both types are commonly used in portable electronics due to their rechargeable nature and high performance.
Nominal, Maximum & Cut-off Voltage
I’ve been using several Lithium-Ion batteries for my various projects for a considerable time now. Some of these batteries come with an integrated Battery Management System Circuit that offers protections such as over-voltage, balanced charging, and short-circuit.
Most Lithium-Ion batteries operate at a nominal voltage of 3.7V, reaching a maximum of 4.2±0.5V when fully charged. According to the manufacturer’s datasheet, the cut-off voltage, which can vary based on battery type and application, is typically 3V. The battery I currently use has a discharge cut-off voltage of 2.8V, though there are batteries available with a cut-off voltage as low as 2.5V.
IoT Battery Monitoring System with DIY LiPo Charger
Now let us go through the circuit and components used in this project and understand the concepts and design logic.
Circuit Design & Schematic
The schematic we’re looking at is for an ESP8266 that runs on battery power. We use the raw ESP8266 chip, specifically the ESP8266-12E/12F variant. The setup includes a low-power LDO, a battery management IC, and a USB port for battery charging. There’s also a switch for powering the system on and off.
BMS & Charging IC MCP73831
Given that the device operates on battery power, it necessitates regular battery charging and management, a task handled by the MCP73831 IC.
The MCP73831 IC devices are sophisticated linear charge management controllers suitable for applications with space limitations and cost concerns. They utilize a constant-current/constant-voltage charge algorithm, featuring selectable preconditioning and charge termination.
You can follow the MCP73831 Application Circuit for more about the IC.
Voltage Regulator & LDO HT7333
Many ESP8266-based boards come with voltage regulators like the AMS117, which has a voltage drop-out of 1.3V. This voltage drop-out is too significant for ESP boards powered by batteries.
Thus, a preferable alternative is the HT7333 3.3V Linear Voltage Regulator IC, which has a drop-out of just 170mV and an exceptionally low quiescent current of 8uA. This makes it ideal for battery-powered applications. The IC receives input from the battery and delivers a regulated 3.3V output to the whole circuit, including the ESP8266 chip.
ESP8266 Programmer Circuit
The discussed circuit comes equipped with an automatic programmer, eliminating the need for manual programming or the operation of push buttons. All it requires is an FTDI Module to program the raw ESP chip. The programming process is managed by two switches (FLS and RST), two BC547 transistors (Q1 and Q2), among other components.
The RTS signal is utilized for resetting the ESP8266, and the DTR signal puts the chip into flash mode. Transistors Q1 and Q2 ensure that the ESP8266 doesn’t reset when both DTR and RTS signals are low. When an upload command is detected, the ESP module automatically enters flash mode, facilitating the smooth upload of a new sketch. Without an upload command, the ESP-12E/F operates in normal mode, allowing the programmed ESP-12E/F board to be tested or deployed in an application.
Voltage Divider Network & ESP8266 ADC
The Battery Maximum voltage is 4.2V and the cut of voltage is 2.8V. The ESP8266 chip features a single analog pin with an input voltage range from 0 to 1V. Anything lesser than 1V will be easily supported by ESP8266 Analog Pin.
To manage voltages beyond this range, a voltage divider network, created by the R11(20K) and R12(100K) resistors, steps down the voltage. Consequently, in the above circuit, the battery’s output voltage is linked to the ESP8266 chip’s ADC (Analog-to-Digital Converter). Using some mathematical calculation, we can convert the ADC value into real voltage. Use the ADC Calculator to find out real voltage value. The Battery life can be calculated using the Battery Life Calculator.
OLED Display & GPIO Pins (Optional)
The OLED Display is optional for this DIY LiPo Battery Charger project that can be used for monitoring Battery Voltage and Charge. The display used here is SSD1306 I2C OLED Display.
The GPIO output pins here are I04, I05, IO12, IO13, I014, IO16. All the pins are digital pins and out of them IO4 (SDA) & IO5 (SCL) are the I2C pins. You can use these pins to connect some external sensor and modules. There is a header H1 in the circuit which is having 6 pins. Out of them, 3 pins are the VCC & the other 3 are the GND pins.
Project PCB Design, Gerber File & PCB Ordering Online
The above schematic is designed using EasyEDA. You can convert the schematic to the PCB.
The PCB has SMD components with resistors and capacitors with an SMD package of 0805. The other ICs are also in the SMD package. The front side of the PCB looks something like below.
The backside of the PCB also has some components to assemble. The backside looks something like this.
The Gerber File for the PCB is given below. You can simply download the Gerber File and order the PCB from ALLPCB at 1$ only.
You can use this Gerber file to order high quality PCB for this project. To do that visit the ALLPCB official website by clicking here: https://www.allpcb.com/.
You can now upload the Gerber File by choosing the Quote Now option. From these options, you can choose the Material Type, Dimensions, Quantity, Thickness, Solder Mask Color and other required parameters.
After filling all details, select your country and shipping method. Finally you can place the order.
PCB & Hardware Assembly
After ordering the PCB, it took almost 5 days and I got my PCB.
The PCB quality from ALLPCB is superb with very high quality. That is why most of the people trust ALLPCB for PCB/PCBA Services.
On the front side, first solder all the SMD components like resistors, capacitors, transistors, LED, pus buttons & micro-USB port. Be careful about the SMD LED polarity, place it in proper direction. After soldering all these, you can solder the ESP8266 raw chip.
On the back side, you can solder all the resistors, capacitors, MCP73831 IC, HT7333 IC.
After soldering all the SMD components, you can solder the through-hole components like Slide Switch, Battery Connector Pins & Male/Female Header Pins.
Testing the Hardware
After assembly all the components on the PCB, it’s time to test the hardware. To do that first connect the 3.7V LiPo or Lithium-Ion Battery to the Battery port.
Slide the switch to turn on the system. When the switch is slided, the LED on ESP8266 chip blinks which indicates the hardware is fine.
In order to test the Battery charging, insert the Micro-USB charger to micro-USB port. The red LED on the board turns on immediately indicating the battery charging system is working fine.
To test whether you are able to upload the code to the ESP8266 Chip or not, connect a USB-to-TTL Converter Module (FTDI) to the Board using the pins mentioned in the PCB. Make sure to connect the RTS pin from side of the USB-to-TTL Module as well.
Connect the FTDI Board to your computer and open the Arduino Blink Sketch.
From the Board list Select “Generic ESP8266” Board and also select the COM port.
Now hit the upload button to upload the code. After successful uploading the Arduino IDE will show following messages. This means the code is successfully uploaded and you are ready to go.
On the other hand, the on-board LED on the ESP8266 will turn on/off for 1 seconds.
So board testing part is done. Now lets move to the main project, i.e. DIY LiPo Battery Charger with IoT Voltage/SoC Monitoring System. All we need is the code for battery charger voltage testing and sending it to Thingspeak Server.
Setting up ThingSpeak Server
In order to Monitor the Battery Data on Thingspeak Server, you first need to Setup the Thingspeak. To set up the Thingspeak Server, visit https://thingspeak.com/. Create an account or simply sign in if you created the account earlier.
Then create a new channel with following details.
Then go to the API section of the dashboard and copy the API Key.
This API code will be used in the code to receive the data from ESP8266 hardware.
Source Code/Program for IoT Battery Monitoring System
Now let us see the ESP8266 code for LiPo Battery Charger with Online Voltage/Charge Monitoring System. The script is for an ESP8266 microcontroller to read battery voltage, calculate the percentage, and then send this information to a ThingSpeak channel using a WiFi connection.
From the following lines change the WiFi SSID, Password and ThingSpeak API Key.
|
1 2 3 |
String apiKey = "*************"; // Enter your ThingSpeak API Key const char* ssid = "*************"; // Enter your WiFi Network's SSID const char* pass = "*************"; // Enter your WiFi Network's Password |
After changing these parameters, you can now upload the code to the ESP8266 Board.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#include <ESP8266WiFi.h> String apiKey = "*************"; const char* ssid = "*************"; // Enter your WiFi Network's SSID const char* pass = "*************"; // Enter your WiFi Network's Password const char* server = "api.thingspeak.com"; const int analogInPin = A0; float adcValue = 0; float voltage = 0; WiFiClient client; void setup() { Serial.begin(115200); Serial.println("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("*"); } Serial.println(""); Serial.println("WiFi connected"); } void loop() { adcValue = analogRead(analogInPin); voltage = (adcValue * 0.00549538); int bat_percentage = mapfloat(voltage, 3.3, 4.2, 0, 100); if (bat_percentage >= 100) { bat_percentage = 100; } if (bat_percentage <= 0) { bat_percentage = 0; } Serial.print("ADC Value = "); Serial.println(adcValue); Serial.print("Voltage = "); Serial.print(voltage); Serial.println(" V"); Serial.print("Battery Percentage = "); Serial.print(bat_percentage); Serial.println(" %"); delay(2000); Serial.println("Sending Data to ThingSpeak Server"); if (client.connect(server, 80)) { String postStr = apiKey; postStr += "&field1="; postStr += String(voltage); postStr += "&field2="; postStr += String(bat_percentage); postStr += "\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); delay(100); client.print("Host: api.thingspeak.com\n"); delay(100); client.print("Connection: close\n"); delay(100); client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n"); delay(100); client.print("Content-Type: application/x-www-form-urlencoded\n"); delay(100); client.print("Content-Length: "); delay(100); client.print(postStr.length()); delay(100); client.print("\n\n"); delay(100); client.print(postStr); delay(100); } client.stop(); Serial.println("Sent Successfully :)"); Serial.println(); delay(30000); } float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Code Explanation
Let’s break down the code section by section.
|
1 2 3 4 5 6 |
#include <ESP8266WiFi.h> String apiKey = "7VWG5MRP54ABO2PO"; const char* ssid = "maganates"; const char* pass = "Itnetworking@18$#"; const char* server = "api.thingspeak.com"; |
This section includes the ESP8266WiFi library, which allows for WiFi connectivity. It also sets up some variables for connecting to the network (ssid and pass) and to the ThingSpeak server (server). The apiKey is used for sending data to a specific ThingSpeak channel.
|
1 2 3 4 5 |
const int analogInPin = A0; float adcValue = 0; float voltage = 0; WiFiClient client; |
Here, analogInPin is assigned to pin A0, where the battery voltage will be read. adcValue and voltage are initialized at 0. WiFiClient client initializes a client for the WiFi connection.
|
1 2 3 |
void setup() { ... } |
The setup() function is called once when the ESP8266 starts up. It initializes the serial communication at a baud rate of 115200 and tries to connect to the WiFi network with the given ssid and pass. It keeps trying until a connection is established.
|
1 2 3 4 5 6 7 |
void loop() { adcValue = analogRead(analogInPin); voltage = (adcValue * 0.00549538); int bat_percentage = mapfloat(voltage, 3.3, 4.2, 0, 100); ... } |
The loop() function is the main function that runs continuously. It reads the analog value from the battery connected to pin A0, then it converts the ADC value into voltage with a scaling factor.
To convert the ADC value into voltage, we multiplied ADC value by a factor of 0.00549538. This factor is experimental value which we got from the voltage divider network R12 and R11 in the PCB and the maximum input voltage from the Battery.
The mapfloat() function is used to convert the voltage value into battery percentage (assuming 3.3V is 0% and 4.2V is 100%).
|
1 2 3 |
if (client.connect(server, 80)) { ... } |
Inside the loop(), it checks if the client has connected to the ThingSpeak server. If it is connected, it creates a HTTP POST request to send the voltage and battery percentage to the server. The client.print() statements are constructing the HTTP request, and the delay(100) calls give the ESP8266 time to process the requests.
|
1 |
client.stop(); |
This closes the client’s connection to the server after the data is sent.
|
1 2 3 |
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Finally, the mapfloat() function is defined. It’s a utility function used to map one range of values (in_min to in_max) to another range of values (out_min to out_max). It’s used in the script to convert voltage values into battery percentage values.
Project Working & Demo
After uploading the code, its time to test the LiPo Battery Charger with Online Voltage/Charge Monitoring System using ESP8266 on ThingSpeak Server.
Open the Serial Monitor. The Serial Monitor will display the ADC Value, Battery Voltage and Soc (Charge %).
The ESP8266 will simultaneously connect to the WiFi Network and will upload the data to the Thingspeak Server. To view the data on ThingSpeak Server, go to the private view section on the ThingSpeak dashboard.
Here is the charging graph that shows the rising voltage per time as battery was put in charging state.
It just took 30 minutes to attend a full charging as I was charging the device using 500mAh LiPo Battery.
In order to see the discharge curve, I had to leave the device turned on for the whole night. As the device is low power, the discharging process is so slow. Here is the discharge graph on ThingSpeak Server.
You may setup the widgets and graphical display on ThingSpeak Server according to your wish.
Video Tutorial & Guide
Further Enhancements and Conclusion
Apart from monitoring the voltage online, what if you don’t have a WiFi connection? In this case, you may solder a 0.96″ I2C OLED Display on the backside and write a code to display Battery Voltage and Soc(%) on OLED.
You can further enhance this board by doing some modifications related to deep sleep mode and power optimizing’s mode. This will reduce the battery power consumptions. You may send the Battery Voltage and Soc to ThingSpeak Server after an interval of every 5 minutes and put the device in sleep mode during remaining times.
In conclusion, we’ve successfully created a DIY LiPo Battery Charger that integrates an IoT Voltage/SoC Monitoring System using an ESP8266 Board. Our custom-designed PCB uses the ESP8266 raw chip, a Low Power LDO, and a Battery Charger chip for a highly efficient assembly. This setup, geared for single-cell Lithium-ion or Polymer batteries, not only charges the battery but also harnesses the power to relay the battery’s voltage and state of charge (SoC) data to the Thingspeak Server. Thus, we’re able to monitor the charging and discharging status of the battery remotely.
This project showcases how technology can be used to create a power-efficient, IoT-enabled battery charger that simplifies the task of battery management. We hope you found this exploration into building a DIY LiPo Battery Charger with IoT Voltage Monitoring System beneficial and inspiring for your own projects.


































2 Comments
Great tutorial !
Thanks for sharing…
hi sir your every post is Awesome