# Better battery reporting

• Hello,
A modification I implemented starting from the "battery sensor" sketch, in order to improve battery % reporting; wrapped up in a small library. Please be kind with my code, I'm merely a hobbyist.
Why:
1- LiPo cells can't get under 3.3v without damage risk, AA cells are leak proof down to 0.7v, I wanted my battery reporting to implement this: LiPo: 100% = 4.15v, 0% = 3.3v // AA: 100% = 1.5v, 0% = 0.8v
2 - Voltage divider precision relies on resistors accuracy, I wanted a way to "calibrate" my divider in order to get proper battery reporting
3 - For fun Please note that the voltage divider is not the same for LiPo and AA battery (explained in cpp's comments)

Feel free to copy, paste, modify, criticize!

Test sketch

``````#include <BatteryManager.h>

const int BatteryType = 1; // 1 for 1S LiPo, 2 for 2xAA
const uint8_t BatterySensorPin = A0;
const float VoltageDividerCalibration = 1; // default 1, can be calibrated by measurement

BatteryManager bms;

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
bms.begin(BatteryType, BatterySensorPin,VoltageDividerCalibration);
}

void loop() {
// put your main code here, to run repeatedly:
Serial.print("Voltage: ");
Serial.println(bms.reportVoltage());
Serial.print("Percent: ");
Serial.println(bms.reportPercent());
delay(3000);
}
``````

``````/*
* Battery Manager
*/

#ifndef BatteryManager_h
#define BatteryManager_h

#include <Arduino.h>

class BatteryManager {
public:
BatteryManager();
void begin(int BatteryType, uint8_t SensePin, float Compensation);
int reportPercent();
float reportVoltage();
private:
int _BatteryType; //1 for 1S LiPO, 2 for 2x AA
uint8_t _SensePin;
float _Compensation;
float Battery_Min_V;
float Battery_Max_V;
float Battery_Sense_Pin_Resolution;
};
#endif
``````

cpp

``````#include <Arduino.h>
#include <BatteryManager.h>

BatteryManager::BatteryManager() { }

void BatteryManager::begin(int BatteryType, uint8_t SensePin, float Compensation)
{
_SensePin = SensePin;
_Compensation = Compensation;
pinMode(_SensePin, INPUT);
// Battery use the 1.1 V internal reference
#if defined(__AVR_ATmega2560__)
analogReference(INTERNAL1V1);
#else
analogReference(INTERNAL);
#endif
// check battery type and feed related variables
if (BatteryType == 1) {
/* LiPo voltage need to be measured up to 4.2V hence using internal ADC ref of 1.1V,
*  divider across battery needs to be 1M, 330K,
*  which allows a range of 0 to ((1e6+330e3)/330e3)*1.1 = 4.433 Volts
*  resolution: 4.4333/1023 = Volts per bit = 0.004333659
*  sense point can be bypassed with 0.1 uF cap to reduce noise at that point
*  LiPo is full @ 4.2V and risks damage below 3.3v
*  => LiPo usable range is 3.3 to 4.2 volts so the goal is to report
*  100% @ 4.2 volts
*  0% @ 3.3 volts
*/
Battery_Min_V = 3.3;
Battery_Max_V = 4.15;
Battery_Sense_Pin_Resolution = 4.333659; //mv per bit
}
if (BatteryType == 2) {
/* 2 x AA Alkaline voltage need to be measured up to 3V hence using internal ADC ref of 1.1V,
*  divider across battery needs to be 1M, 470K,
*  which allows a range of 0 to ((1e6+470e3)/470e3)*1.1 = 3.44 Volts
*  resolution: 3.44/1023 = Volts per bit = 0.003363075
*  sense point can be bypassed with 0.1 uF cap to reduce noise at that point
*  AA is normally leak proof down to 0.7V, I add an extra 0.1V to avoid any issue
*  => AA usable range is 1.5 to 0.8 volts so the goal is to report
*  100% @ 2x1.5 = 3 volts
*  0% @ 2x0.8 = 1.6 volts
*/
Battery_Min_V = 1.6;
Battery_Max_V = 3;
Battery_Sense_Pin_Resolution = 3.363075; //mv per bit
}
}

int BatteryManager::reportPercent() {
// get the battery Voltage
Serial.println(sensorValue);
float batteryV  = sensorValue * Battery_Sense_Pin_Resolution * _Compensation / 1000;
// map to 0 -- 100 according to boundaries
// need to multiply voltages by 10 as map function processes long variables
return map(10*batteryV,10*Battery_Min_V, 10*Battery_Max_V, 0, 100);;
}

float BatteryManager::reportVoltage() {
// get the battery Voltage
Serial.println(sensorValue);
return sensorValue * Battery_Sense_Pin_Resolution * _Compensation / 1000;
}
``````

• @thierryd Nice idea.

Two remarks:

You write in the cpp file:

if (BatteryType == 2) {
/* LiPo voltage ...

You probably mean here "AA voltage"

The AA batteries you talk about are Alkaline (not rechargeable)?
The values are different for NiMH rechargeable (which I always use).

• Thank you for your answer, indeed there's a mistake in the comment, I'll edit that right away!
Yes for AA i mean Alkaline, I implemented the "battery type" feature even if I'm not yet using it, as I currently only power my gadget with LiPo cells. But as it is explained well enough (I hope), anybody can add his battery type in the code! I guess for NiMH boundaries would be 0.9v to 1.3v

• I chose a different approach to this problem (but only with 1 power supply).

That was to replace the resistor pair of 1M0 and 470K with 9M1 and 0.5M preset (trimmer). This reduces the current flow by about 90%+ and by adjusting the preset I can 'calibrate' it to 100%. Changing batteries doesn't seem to require retweeking if the same type are used.

So far it is working well for me.

79

20

21

7

2

17

5
{"ft_lang_label":"__label__en","ft_lang_prob":0.76877946,"math_prob":0.8700681,"size":5461,"snap":"2020-45-2020-50","text_gpt3_token_len":1553,"char_repetition_ratio":0.12937512,"word_repetition_ratio":0.11791907,"special_character_ratio":0.29902947,"punctuation_ratio":0.17248061,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9559779,"pos_list":[0,1,2],"im_url_duplicate_count":[null,null,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-11-24T05:57:59Z\",\"WARC-Record-ID\":\"<urn:uuid:6515d1ac-f698-455a-8eba-f721e863325f>\",\"Content-Length\":\"129654\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:704a10ae-b00d-4603-902a-e90b919df0a1>\",\"WARC-Concurrent-To\":\"<urn:uuid:b275b765-f7b0-4c7a-a01a-7507f472345c>\",\"WARC-IP-Address\":\"185.92.221.81\",\"WARC-Target-URI\":\"https://forum.mysensors.org/topic/7114/better-battery-reporting\",\"WARC-Payload-Digest\":\"sha1:PSCB2I3V3ROISTPDSPB43JKJURWZTOOO\",\"WARC-Block-Digest\":\"sha1:52LFAGJGOU6A5J2SD7W4UJT4VD6CB7KL\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-50/CC-MAIN-2020-50_segments_1606141171126.6_warc_CC-MAIN-20201124053841-20201124083841-00026.warc.gz\"}"}