When you install IOT sensors inside your house, you will have plenty main power outlets, USB adapters etc. to power your boards. But when sensors should be mobile, or should be used at places without power supply, they need to be powered by batteries. While it’s not difficult to provide battery power - assuming you use the right capacity and voltage - it can be challenging to measure the remaining battery power so that you can ensure a continuous operation.
In this article, you will learn how to reliable measure the remaining battery power for an ESP8266 board. I will discuss the required hardware, shortly explain the required soldering process, and then continue with the ESPHome configuration to read the values. On top of that, you will see different options for visualizing the battery status in Home Assistant.
The technical context of this article is Home Assistant 2024.11
and ESPHome 2024.10
, but it should work with newer versions as well.
This article originally appeared at my blog admantium.com.
Preparations & Setup
Required Hardware
The particular hardware used in this article is inspired by the great article best battery for ESP8266. Specifically, it will be this:
- ESP8266 D1 Mini Board
- ESP8266 D1 Mini Battery Shield
- 18650 Lithium Ion Battery
- External battery Case with JST Connector
Soldering
Soldering is an activity that I just learned to love when working with Arduino and other boards. I quite enjoyed it this time because I needed to solder the following things:
- Pin connectors to the board
- Battery shield on top of the board
- JST cables to the battery case
It took me about 1 hour to get everything done.
Battery Measurement on ESP Board
There are two different methods to measure an externally connected battery.
The first method is to measure the internal VCC directly. VCC is the supply voltage of the board, it depends on the specific type and brand, and usually flaps a lot. The minimal required voltage for the board to still be operational is hopefully mentioned in its specifications. If not, you need to measure it yourself.
The second option is to measure outgoing voltage from the battery. Several factors need to be considered. First, the battery outputs a specific maximum value that you need to determine, e.g. its 4.2V for my 18650 Lithium Ion Battery Second, you need to drop this voltage to the maximum input voltage of the analog pin on your board. In my case, the D1 Mini Rev2, its 3.2 Volt, while older models only allow up to 1 Volt - be very careful to not fry your board! Then, you need to build a voltage divider, a circuit that will drop the maximum voltage to the desired voltage. Third, you connect the output of this circuit to the analog pin of your board.
Which method do you prefer? Keep on reading, or just jump to the section that you choose.
Battery Measurement of VCC Pin on the ESP Board
ESP Home Configuration
To measure the VCC voltage directly, you will need to add three new entries in to the sensor
section:
- An
adc
sensor that reads the raw 10Bit value of the internal VCC pin, which means it provides values from 0 to 1023 - A custom
template
sensor that translated the adc value to a voltage value - Another custom
template
sensor that calculates the battery percentage
Overall, add these to the board’s configuration. But please note: This calculation absolutely depends on the specifics of your hardware setup - so take my suggestion here just as a starting point.
# Chip Info:
# - Chip Family: ESP8266
# - Chip Model: ESP8266EX
esphome:
name: esp8266-02
platform: ESP8266
board: d1_mini
# ...
sensor:
- platform: adc
pin: VCC
id: "VCC"
internal: true
- platform: template
name: "esp8266-01.voltage"
unit_of_measurement: 'V'
update_interval: 30min
lambda: |-
return id(VCC).state;
- platform: template
name: "esp8266-01.battery"
unit_of_measurement: '%'
update_interval: 30min
lambda: |-
return (id(VCC).state - 3.2) * 100.00;
Upload all these changes to the board...
Building .pioenvs/esp8266-01/firmware.bin
Retrieving maximum program size .pioenvs/esp8266-01/firmware.elf
Checking size .pioenvs/esp8266-01/firmware.elf
RAM: [==== ] 40.3% (used 33012 bytes from 81920 bytes)
Flash: [=== ] 33.9% (used 354064 bytes from 1044464 bytes)
Creating BIN file ".pioenvs/esp8266-01/firmware.bin" using "/root/.platformio/packages/framework-arduinoespressif8266/bootloaders/eboot/eboot.elf" and ".pioenvs/esp8266-01/firmware.elf"
========================= [SUCCESS] Took 31.35 seconds =========================
INFO Successfully compiled program.
INFO Connecting to 192.168.3.213
INFO Uploading /config/esp8266-01/.pioenvs/esp8266-01/firmware.bin (358224 bytes)
Uploading: [============================================================] 100% Done...
... and check the log files that the ADC sensor and the template sensor are recognized without any errors:
INFO OTA successful
INFO Successfully uploaded program.
INFO Waiting for result...
INFO OTA successful
INFO Successfully uploaded program.
INFO Starting log output from 192.168.3.213 using esphome API
INFO Successfully connected to 192.168.3.213
[10:00:35][I][app:102]: ESPHome version 2021.9.1 compiled on Jan 16 2022, 09:59:26
[10:00:35][C][wifi:501]: WiFi:
...
[10:00:35][C][adc:072]: ADC Sensor 'VCC'
[10:00:35][C][adc:072]: Device Class: 'voltage'
[10:00:35][C][adc:072]: State Class: 'measurement'
[10:00:35][C][adc:072]: Unit of Measurement: 'V'
[10:00:35][C][adc:072]: Accuracy Decimals: 2
[10:00:35][C][adc:075]: Pin: VCC
[10:00:35][C][adc:099]: Update Interval: 30.0min
...
[10:00:35][C][template.sensor:022]: Template Sensor 'esp8266-01.battery_level'
[10:00:35][C][template.sensor:022]: State Class: ''
[10:00:35][C][template.sensor:022]: Unit of Measurement: '%'
[10:00:35][C][template.sensor:022]: Accuracy Decimals: 1
[10:00:35][C][template.sensor:023]: Update Interval: 30.0min
Soon after, you should see log messages such as these:
[10:01:13][D][adc:104]: 'VCC': Got voltage=3.2V
[10:01:13][D][sensor:121]: 'VCC': Sending state 3.25176 V with 2 decimals of accuracy
[10:00:54][D][sensor:121]: 'esp8266-01.voltage': Sending state 3.25176 V with 1 decimals of accuracy
[10:01:14][D][sensor:121]: 'esp8266-01.battery': Sending state 100.62903 % with 1 decimals of accuracy
Tests and Experiments with VCC Measuring
I measured the VCC continuously with an always active board to which a motion sensor was connected. For about two days, the graphs showed a constant 3.2V and 100 % charge. Then, on the next day the dashboard showed this:
The measurement graph shows that the battery dropped from 95% to about 72,3% - and stayed dead then:
The multimeter showed a remaining voltage of 1.3V. I learned a lot from this try. First of all, a major caveat: The battery shield has no protection against deep discharge. Luckily, my battery was not damaged at all. Second, VCC measurements are very tightly scoped, so a drop of only 0.2 - 0.4V could already mean that the battery is discharged. In my example, the discharge was also severe: From 7am until 2pm. No time to react on a normal working day, even raising an alert would not help. Overall, the measurement is too coarse and the available reaction time to dense.
For these reasons, I tried the second approach too: Measure the remaining battery voltage directly.
Battery Measurement of V+ Pin on the Battery Shield
Voltage Divider
The voltage divider consists of two resistors, connected to a ground, with a power outlet in between. First, use this voltage divider calculator to define the value of the resistors so the voltage drops to the required amount. Then, build a circuit like this:
Source: www.mischianti.org/
The input to the voltage device is a wire soldered to the V+ pin on the battery shield, and the output is directly connected to the A0 pin of the board. My final design is this:
ESP Home Configuration
When using a voltage divider, you will measure the input value of the analog pin. The other two templates stay the same.
- An
adc
sensor that reads the raw 10Bit granular value of the analog input pin - A custom
template
sensor that translates this value to a voltage value - Another custom
template
sensor that calculates the battery percentage
For calculating the battery percentage value, I used the table from this article.
As before: Please use this configuration only as a blueprint and customize it your specific hardware.
# Chip Info:
# - Chip Family: ESP8266
# - Chip Model: ESP8266EX
esphome:
name: esp8266-02
platform: ESP8266
board: d1_mini
# ...
sensor:
- platform: adc
pin: A0
id: "ANALOG"
internal: true
filters:
- multiply: 4.2
- platform: template
name: "esp8266-02.battery_voltage"
unit_of_measurement: 'V'
update_interval: 60s
accuracy_decimals: 2
lambda: |-
return (id(ANALOG).state);
- platform: template
name: "esp8266-02.battery_charge"
update_interval: 60s
accuracy_decimals: 2
lambda: |-
return (id(ANALOG).state) - 1.2) * 33.33;
sensor:
- platform: adc
pin: A0
id: "ANALOG"
internal: true
- multiply: 4.2
Using this configuration, my ESP Home board outputs these messages:
[18:57:56][D][adc:104]: 'ANALOG': Got voltage=1.00V
[18:57:56][D][sensor:121]: 'ANALOG': Sending state 4.20000 V with 2 decimals of accuracy
[18:58:01][D][sensor:121]: 'esp8266-02.battery_voltage': Sending state 4.20000 V with 2 decimals of accuracy
[18:58:03][D][sensor:121]: 'esp8266-02.battery_charge': Sending state 99.99 % with 2 decimals of accuracy
Tests and Experiments with VCC Measuring
For the second experiment, I connected an air quality sensor and set the board to a deep sleep rhythm of 30 minutes, then 3 minutes for sending sensor data. This time, the battery lasted for over 1 week.
On a Friday, I saw the first drop from 4.2 to, and then on the next morning, a steady decrease to 3.2.
This gave me plenty of advanced warning, I could change the battery in time.
Home Assistant Visualization
Home Assistant offers you several ways to visualize the battery measurement data. I prefer to show the remaining battery as a gauge. It can be configured to have different threshold values that rank the battery in categories like charged, used, depleted. You add these directly as part of the Lovelace card:
First, you can add the raw battery voltage as a sensor value and show this is an absolute number and
Conclusion
In your home automation setup, measuring the remaining battery power of sensors can be challenging. This article showed you a step-by-step manual, beginning from the hardware, assembly, and soldering, continuing to the ESPHome configuration and finishing with Home Assistant visualizations. In essence, you have two options: You can either measure the battery voltage directly by building a voltage divider and feeding it to an analog pin, or by measuring the onboard voltage. The first option is more reliable and gives values in the range of max voltage of battery to board operating voltage - 0.2 Volt, the second option is simpler to implement, but gives only values in the range of the boards operating voltage - 0.2 Volt, and the measurements will flap greatly. From my experience, I strongly suggest using the first approach, or even to use an external, dedicated voltage reading sensor. But independent of that, getting the raw voltage and/or battery percentage from ESP Home to Home Assistant, and visualizing them there, is very helpful to maintain a fleet of sensors available.
Top comments (0)