Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Battery monitor feature #847

Open
wants to merge 14 commits into
base: beta
Choose a base branch
from

Conversation

gvidinski
Copy link
Contributor

@gvidinski gvidinski commented Dec 9, 2020

I would like to introduce to you a small feature as an addition to the main functionality. I called it “Battery monitor”. It allows you to monitor the state of the battery if UPS topology is used to power the board by showing current battery capacity percentage and its voltage which might be useful for many advanced users I believe.

The feature can be enabled through the configuration menu. When enabled user will have to enter few parameters – threshold voltage for both, the discharged [Battery U min (mV)] and the fully charged [Battery U max (mV)] state along with the maximum input voltage at the voltage divider [ADC divider U max]. In case when NodeMCU1) is used and battery voltage is greater than 3.3V user will have to add additional resistor (R1) to the monitor line, in series with the positive terminal and the A0 input of the board (Figure 1):

Figure 1.

The value of the R1 can be found by solving the following equation (1):

(1),

where R2 = 220kΩ and R3 = 100kΩ both forming the internal voltage divider provided inside the NodeMCU1) board; Vin is the voltage at the battery’s positive terminal; Vout is the maximum input voltage of the ESP8266’s 10-bits ADC which is always 1V. Internal voltage divider provides sufficient solution for input voltages ≤ 3.3V without having the need of R1 to be installed. But having for instance a Li-Polymer single cell battery we will need to be able to read voltage of at least 4.2V. For example solving equation (1) for Vin = 5V will give us a standard value for the R1 resistor of 180kΩ.

Of course there could be another approach especially if we do not have a resistor with the exact value of 180kΩ for R1 on hand but we have one with value of 155kΩ instead. By simply using the values of all the resistors in the voltage divider and solving (2):

(2),

where Vout = 1V; R1 = 155kΩ; R2 = 220kΩ; R3 = 100kΩ will give us the [ADC divider U max] value for the configuration – VinMAX = 4.75V.

The code takes into account if we build it for ESP8266 or ESP32 platform. For ESP32 platform I’ve used a definition where pin 36 (GPIO36) is selected for the battery monitor input which corresponds to the ADC1 channel 0 (ADC0) of the ESP32. (By the time I was writing this I didn’t have any available Node322 so the definition needs to be tested and eventually changed.) In this case user will have to implement his own voltage divider by using only two resistors as shown in Figure 2:

Figure 2.

Then the following equation (3) have to be used:

(3),

where Vin is the voltage at the battery positive terminal; Vout = 3.3V (the maximum meaningful input voltage for the 12-bit ADC’s analog inputs of the ESP32); R1 & R2 by your choice. Just pick large enough value in order of hundreds kilo Ohms to keep the current that will be drawn from the battery at insignificant levels. I would suggest using 220kΩ (R1) and 330kΩ (R2) standard 1% resistors. This will give readings of maximum 5.5V with small enough current draw (7.6 µA @ 4.2V).

In Table 1 are shown different solutions for different input voltage ranges for both platforms using standard resistors of 1% tolerance and will draw current as low as 10µA form the battery.

Table 1.

Board NodeMCU1) Node322)
VinMAX 5V 10V 15.2V 19.2V 5V 10V 15.2V 19.2V
R1 180k 680k 1.2M 1.6M 180k 680k 1.2M 1.6M
R2 220k 220k 220k 220k 330k 330k 330k 330k
R3 100k 100k 100k 100k - - - -
Applications 3) 4) 5) 6) 3) 4) 5) 6)

The UI is organized in the following manner. All the settings for the Battery monitor have to be entered form the “Configuration” page, “More settings” tab, under the “Enable battery monitor” checkbox (Figure 3.). By enabling it another three more input fields will become visible. For the Battery discharged, fully charged voltage and for the maximum input voltage at the divider (Figure 4). Then the actual battery state can be obtained at the “Device status” page in the form of “Capacity: [%]([V])” (Figure 5.).

Figure 3. Figure 4.
Figure 5.

All the measurements are done by averaging 3 consecutive readings taken in periods of 1 second, then followed by 10 seconds pause period. Also no reading will be taken during the report period, when data has to be send to the external web resources (taking into account the “send_now” state). In addition the Battery state data is added to the json result. This way users can track the state of the battery and also may develop customized battery state charts on their platforms.

Build and testing was done using the PlatformIO under the Visual Studio Code IDE following the “Contributing Guidelines”.


1) Developments boards based on ESP8266 chips – NoneMCU v2 & v3.
2) Development boards based on ESP32 chip – Node32.
3) Single cell (1S) Li-Ion or Li-Polymer 3.7V batteries (2.8V ~ 4.2V).
4) Double cell (2S) Li-Ion or Li-Polymer 7.2V battery packs (5.6V ~ 8.4V).
5) Six cell lead acid 12V battery (10.5V ~ 13.8V).
6) Four cell (4S) Li-Ion or Li-Polymer 14.4V battery packs (11.2V ~ 16.8V).

@gvidinski gvidinski marked this pull request as ready for review December 10, 2020 06:17
@DeeKey
Copy link
Contributor

DeeKey commented Dec 23, 2020

Great job done!
Small remarks from me:
To my mind the BATTERY_CAPACITY should be renamed to BATTERY_CHARGE. Capacity will slowly degrade over time due to natural reasons. But what you want to show is not capacity, but the charge left in the battery.
Also to simplify the understanding I propose:
const char INTL_BATTERY_U_MIN[] PROGMEM = "Discharged voltage (mV)";
const char INTL_BATTERY_U_MAX[] PROGMEM = "Charged voltage (mV)";
const char INTL_ADC_DIVIDER_U_MAX[] PROGMEM = "ADC divider max voltage (mV)";

@glosair
Copy link

glosair commented Dec 27, 2020

Updated

Just been looking at this and all the devices listed linear regulators rather than switching regulators so are very inefficient.

Will design a board with switching regulator and a voltage divider connected to the ESP8266, my aim is for a universal sensor board that can work from 12V, 5V, Battery, Solar/battery and have the option for fitting a Lora radio for the data.

This will of course be open sourced.

Interested?

@gvidinski
Copy link
Contributor Author

Thank you @DeeKey for your remarks. You are right. Battery charge is the right definition and I just was not sure. I'll try to update the code in the next few days along with the updated labels proposed by. Listen, can you send me an email in order to get in touch? I would like to discuss a few things with you. Thanks.

@git-user44
Copy link

"battery_last_value" isn't used anywhere. Why not sum the analogue reading straight into "battery_sum" and save a few bytes ?

@DeeKey
Copy link
Contributor

DeeKey commented Dec 28, 2020

@gvidinski if it is not something which need private discussion, then better ask question on the official forum. So that others can join discussion and add valuable information:
forum.sensor.community

@gvidinski
Copy link
Contributor Author

Update

Hello everyone!
Sorry for the delay.
I've done some changes as they were suggested by @DeeKey & @git-user44. Still I left without changing a few of them though. I think they need a little bit of discussion. For instance the two of them - 'Discharged voltage (mV)' and 'Charged voltage (mV)' - as they describe to particular properties of the battery in use, to be exact: 1)The maximum voltage when the the battery is fully charged and where the most Over-voltage protection circuits will cut-of charging; 2) The minimum voltage when the battery is considered to be fully discharged and where more protection boards will cut-of any drain form the battery. So on one hand probably it should sound something like "Maximum voltage when fully charged (mV)" and "Minimum voltage when fully discharged (mV)". But will that be too long for those strings where every byte counts? On other hand the meaning of "Charged voltage" and "Discharged voltage" does not exactly explain the two properties. Not to mention that it cannot be translated at all in my native language so the "Charged voltage" should be e.g. "Максимално напрежение при напълно заредена батерия (mV)". Too long, right? My intention using just "Battery U max" & "Battery U min" instead was to keep it simple while it is still meaningful enough.
I'm just saying my concerns.
Of course there is possibility for having totally different phrases for every language instance. Some additional help will be welcome.

@DeeKey
Copy link
Contributor

DeeKey commented Nov 15, 2021

Sorry, as per discussion with core developers I had to admit that this pull request will not be accepted upstream.
There is a constant strive to minimize the memory footprint and make it easier for non qualified users to add hardware.

Thus it is better to add some i2c hardware monitor sensor than to add such a heavy and hard for ordinal user solution.

Still let it be as a pull request for advanced users and hackers :)

@stewecar
Copy link
Contributor

i am sad about considering that feature an hacker advanced user's request, but the project has space limits and i have to cope with that :).
I am on a 700mAh battery powered by a 10W solar panel and trying to let it working 24h per day is a pain..also if i live in Italy.
Cheers!

@glosair
Copy link

glosair commented Nov 19, 2021

There are several problems with the battery system you are proposing.

Firstly you are providing Vin of 5V that is stepped up from the LiPo cell or stepped down from a LiPo battery, this has loses.

As Vin is a regulated 5V any measurement of Vin as apposed to the actual cell voltage is meaningless.

Secondly the LDO (Low Drop Out) regulator supplying the 3.3V for the ESP8266 is dumping 33% of the chips consumption as heat.

Thirdly you are powering a USB to serial chip constantly draws power.

My suggestion would be to use a LiFo cell and dump the LDO regulator and serial to usb chip, use a small efficient boost converter to power the dust sensor and you are all good.

@gvidinski
Copy link
Contributor Author

Thanks @DeeKey for the answer!

Guys, we can continue at my discussion board in order not to make it too noisy here.
gvidinski#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants