Update Usermod: Battery

Issue:
When taking the initial voltage reading after first powering on, voltage hasn't had chance to stabilize so the reading can be inaccurate, which in turn may incorrectly trigger the low-power preset. (Manifests when the user has selected a low read interval and/or is using a capacitor).

Resolution:
A non-blocking, fixed 10 second delay has been added to the initial voltage reading to give the voltage time to stabilize.

This is a reworked version of the (now closed) PR here:
https://github.com/Aircoookie/WLED/pull/3959

- Rebased the update for 0_15.

- Added a constant so the delay can be modified via my_config.h.

- Small adjustments to make the PR compatible again after the recent restructuring in this PR: (https://github.com/Aircoookie/WLED/pull/3003).

Thankyou!
This commit is contained in:
Adam Matthews 2024-05-09 23:09:45 +01:00
parent b88c300d04
commit bc5aadff7d
3 changed files with 36 additions and 3 deletions

View File

@ -14,6 +14,12 @@
#endif
#endif
// The initial delay before the first battery voltage reading after power-on.
// This allows the voltage to stabilize before readings are taken, improving accuracy of initial reading.
#ifndef USERMOD_BATTERY_INITIAL_DELAY
#define USERMOD_BATTERY_INITIAL_DELAY 10000 // (milliseconds)
#endif
// the frequency to check the battery, 30 sec
#ifndef USERMOD_BATTERY_MEASUREMENT_INTERVAL
#define USERMOD_BATTERY_MEASUREMENT_INTERVAL 30000

View File

@ -37,6 +37,7 @@ define `USERMOD_BATTERY` in `wled00/my_config.h`
| ----------------------------------------------- | ----------- |-------------------------------------------------------------------------------------- |
| `USERMOD_BATTERY` | | define this (in `my_config.h`) to have this usermod included wled00\usermods_list.cpp |
| `USERMOD_BATTERY_MEASUREMENT_PIN` | | defaults to A0 on ESP8266 and GPIO35 on ESP32 |
| `USERMOD_BATTERY_INITIAL_DELAY` | ms | delay before initial reading. defaults to 10 seconds to allow voltage stabilization
| `USERMOD_BATTERY_MEASUREMENT_INTERVAL` | ms | battery check interval. defaults to 30 seconds |
| `USERMOD_BATTERY_{TYPE}_MIN_VOLTAGE` | v | minimum battery voltage. default is 2.6 (18650 battery standard) |
| `USERMOD_BATTERY_{TYPE}_MAX_VOLTAGE` | v | maximum battery voltage. default is 4.2 (18650 battery standard) |
@ -88,6 +89,10 @@ Specification from: [Molicel INR18650-M35A, 3500mAh 10A Lithium-ion battery, 3.
2024-04-30
- improved initial reading accuracy by delaying initial measurement to allow voltage to stabilize at power-on
2024-04-30
- integrate factory pattern to make it easier to add other / custom battery types
- update readme

View File

@ -22,6 +22,10 @@ class UsermodBattery : public Usermod
UMBattery* bat = new UnkownUMBattery();
batteryConfig cfg;
// Initial delay before first reading to allow voltage stabilization
unsigned long initialDelay = USERMOD_BATTERY_INITIAL_DELAY;
bool initialDelayComplete = false;
bool isFirstVoltageReading = true;
// how often to read the battery voltage
unsigned long readingInterval = USERMOD_BATTERY_MEASUREMENT_INTERVAL;
unsigned long nextReadTime = 0;
@ -137,7 +141,6 @@ class UsermodBattery : public Usermod
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
success = true;
bat->setVoltage(readVoltage());
}
if (!success) {
@ -148,10 +151,10 @@ class UsermodBattery : public Usermod
}
#else //ESP8266 boards have only one analog input pin A0
pinMode(batteryPin, INPUT);
bat->setVoltage(readVoltage());
#endif
nextReadTime = millis() + readingInterval;
// First voltage reading is delayed to allow voltage stabilization after powering up
nextReadTime = millis() + initialDelay;
lastReadTime = millis();
initDone = true;
@ -178,6 +181,25 @@ class UsermodBattery : public Usermod
lowPowerIndicator();
// Handling the initial delay
if (!initialDelayComplete && millis() < nextReadTime)
return; // Continue to return until the initial delay is over
// Once the initial delay is over, set it as complete
if (!initialDelayComplete)
{
initialDelayComplete = true;
// Set the regular interval after initial delay
nextReadTime = millis() + readingInterval;
}
// Make the first voltage reading after the initial delay has elapsed
if (isFirstVoltageReading)
{
bat->setVoltage(readVoltage());
isFirstVoltageReading = false;
}
// check the battery level every USERMOD_BATTERY_MEASUREMENT_INTERVAL (ms)
if (millis() < nextReadTime) return;