Merge pull request #3116 from Erwin-Repolust/main
Changing voltage calculation to a weighted running average
This commit is contained in:
commit
fb14bc6016
@ -26,6 +26,15 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//the default ratio for the voltage divider
|
||||||
|
#ifndef USERMOD_BATTERY_VOLTAGE_MULTIPLIER
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#define USERMOD_BATTERY_VOLTAGE_MULTIPLIER 2.0f
|
||||||
|
#else //ESP8266 boards
|
||||||
|
#define USERMOD_BATTERY_VOLTAGE_MULTIPLIER 4.2f
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USERMOD_BATTERY_MAX_VOLTAGE
|
#ifndef USERMOD_BATTERY_MAX_VOLTAGE
|
||||||
#define USERMOD_BATTERY_MAX_VOLTAGE 4.2f
|
#define USERMOD_BATTERY_MAX_VOLTAGE 4.2f
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,6 +29,10 @@ class UsermodBattery : public Usermod
|
|||||||
float rawValue = 0.0f;
|
float rawValue = 0.0f;
|
||||||
// calculated voltage
|
// calculated voltage
|
||||||
float voltage = maxBatteryVoltage;
|
float voltage = maxBatteryVoltage;
|
||||||
|
// between 0 and 1, to control strength of voltage smoothing filter
|
||||||
|
float alpha = 0.05f;
|
||||||
|
// multiplier for the voltage divider that is in place between ADC pin and battery, default will be 2 but might be adapted to readout voltages over ~5v ESP32 or ~6.6v ESP8266
|
||||||
|
float voltageMultiplier = USERMOD_BATTERY_VOLTAGE_MULTIPLIER;
|
||||||
// mapped battery level based on voltage
|
// mapped battery level based on voltage
|
||||||
int8_t batteryLevel = 100;
|
int8_t batteryLevel = 100;
|
||||||
// offset or calibration value to fine tune the calculated voltage
|
// offset or calibration value to fine tune the calculated voltage
|
||||||
@ -110,6 +114,17 @@ class UsermodBattery : public Usermod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float readVoltage()
|
||||||
|
{
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
// use calibrated millivolts analogread on esp32 (150 mV ~ 2450 mV default attentuation) and divide by 1000 to get from milivolts to volts and multiply by voltage multiplier and apply calibration value
|
||||||
|
return (analogReadMilliVolts(batteryPin) / 1000.0f) * voltageMultiplier + calibration;
|
||||||
|
#else
|
||||||
|
// use analog read on esp8266 ( 0V ~ 1V no attenuation options) and divide by ADC precision 1023 and multiply by voltage multiplier and apply calibration value
|
||||||
|
return (analogRead(batteryPin) / 1023.0f) * voltageMultiplier + calibration;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//Functions called by WLED
|
//Functions called by WLED
|
||||||
|
|
||||||
@ -126,6 +141,7 @@ class UsermodBattery : public Usermod
|
|||||||
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
||||||
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
|
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
|
||||||
success = true;
|
success = true;
|
||||||
|
voltage = readVoltage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@ -135,8 +151,8 @@ class UsermodBattery : public Usermod
|
|||||||
pinMode(batteryPin, INPUT);
|
pinMode(batteryPin, INPUT);
|
||||||
}
|
}
|
||||||
#else //ESP8266 boards have only one analog input pin A0
|
#else //ESP8266 boards have only one analog input pin A0
|
||||||
|
|
||||||
pinMode(batteryPin, INPUT);
|
pinMode(batteryPin, INPUT);
|
||||||
|
voltage = readVoltage();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nextReadTime = millis() + readingInterval;
|
nextReadTime = millis() + readingInterval;
|
||||||
@ -176,22 +192,12 @@ class UsermodBattery : public Usermod
|
|||||||
|
|
||||||
initializing = false;
|
initializing = false;
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
rawValue = readVoltage();
|
||||||
// use calibrated millivolts analogread on esp32 (150 mV ~ 2450 mV)
|
// filter with exponential smoothing because ADC in esp32 is fluctuating too much for a good single readout
|
||||||
rawValue = analogReadMilliVolts(batteryPin);
|
voltage = voltage + alpha * (rawValue - voltage);
|
||||||
// calculate the voltage
|
|
||||||
voltage = (rawValue / 1000.0f) + calibration;
|
|
||||||
// usually a voltage divider (50%) is used on ESP32, so we need to multiply by 2
|
|
||||||
voltage *= 2.0f;
|
|
||||||
#else
|
|
||||||
// read battery raw input
|
|
||||||
rawValue = analogRead(batteryPin);
|
|
||||||
|
|
||||||
// calculate the voltage
|
// check if voltage is within specified voltage range, allow 10% over/under voltage - removed cause this just makes it hard for people to troubleshoot as the voltage in the web gui will say invalid instead of displaying a voltage
|
||||||
voltage = ((rawValue / getAdcPrecision()) * maxBatteryVoltage) + calibration;
|
//voltage = ((voltage < minBatteryVoltage * 0.85f) || (voltage > maxBatteryVoltage * 1.1f)) ? -1.0f : voltage;
|
||||||
#endif
|
|
||||||
// check if voltage is within specified voltage range, allow 10% over/under voltage
|
|
||||||
voltage = ((voltage < minBatteryVoltage * 0.85f) || (voltage > maxBatteryVoltage * 1.1f)) ? -1.0f : voltage;
|
|
||||||
|
|
||||||
// translate battery voltage into percentage
|
// translate battery voltage into percentage
|
||||||
/*
|
/*
|
||||||
@ -363,6 +369,7 @@ class UsermodBattery : public Usermod
|
|||||||
battery[F("max-voltage")] = maxBatteryVoltage;
|
battery[F("max-voltage")] = maxBatteryVoltage;
|
||||||
battery[F("capacity")] = totalBatteryCapacity;
|
battery[F("capacity")] = totalBatteryCapacity;
|
||||||
battery[F("calibration")] = calibration;
|
battery[F("calibration")] = calibration;
|
||||||
|
battery[F("voltage-multiplier")] = voltageMultiplier;
|
||||||
battery[FPSTR(_readInterval)] = readingInterval;
|
battery[FPSTR(_readInterval)] = readingInterval;
|
||||||
|
|
||||||
JsonObject ao = battery.createNestedObject(F("auto-off")); // auto off section
|
JsonObject ao = battery.createNestedObject(F("auto-off")); // auto off section
|
||||||
@ -375,6 +382,9 @@ class UsermodBattery : public Usermod
|
|||||||
lp[FPSTR(_threshold)] = lowPowerIndicatorThreshold;
|
lp[FPSTR(_threshold)] = lowPowerIndicatorThreshold;
|
||||||
lp[FPSTR(_duration)] = lowPowerIndicatorDuration;
|
lp[FPSTR(_duration)] = lowPowerIndicatorDuration;
|
||||||
|
|
||||||
|
// read voltage in case calibration or voltage multiplier changed to see immediate effect
|
||||||
|
voltage = readVoltage()
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Battery config saved."));
|
DEBUG_PRINTLN(F("Battery config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +449,7 @@ class UsermodBattery : public Usermod
|
|||||||
setMaxBatteryVoltage(battery[F("max-voltage")] | maxBatteryVoltage);
|
setMaxBatteryVoltage(battery[F("max-voltage")] | maxBatteryVoltage);
|
||||||
setTotalBatteryCapacity(battery[F("capacity")] | totalBatteryCapacity);
|
setTotalBatteryCapacity(battery[F("capacity")] | totalBatteryCapacity);
|
||||||
setCalibration(battery[F("calibration")] | calibration);
|
setCalibration(battery[F("calibration")] | calibration);
|
||||||
|
setVoltageMultiplier(battery[F("voltage-multiplier")] | voltageMultiplier);
|
||||||
setReadingInterval(battery[FPSTR(_readInterval)] | readingInterval);
|
setReadingInterval(battery[FPSTR(_readInterval)] | readingInterval);
|
||||||
|
|
||||||
JsonObject ao = battery[F("auto-off")];
|
JsonObject ao = battery[F("auto-off")];
|
||||||
@ -595,21 +606,7 @@ class UsermodBattery : public Usermod
|
|||||||
totalBatteryCapacity = capacity;
|
totalBatteryCapacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the choosen adc precision
|
|
||||||
* esp8266 = 10bit resolution = 1024.0f
|
|
||||||
* esp32 = 12bit resolution = 4095.0f
|
|
||||||
*/
|
|
||||||
float getAdcPrecision()
|
|
||||||
{
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
// esp32
|
|
||||||
return 4096.0f;
|
|
||||||
#else
|
|
||||||
// esp8266
|
|
||||||
return 1024.0f;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the calculated voltage
|
* Get the calculated voltage
|
||||||
@ -647,6 +644,23 @@ class UsermodBattery : public Usermod
|
|||||||
calibration = offset;
|
calibration = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the voltage multiplier value
|
||||||
|
* A multiplier that may need adjusting for different voltage divider setups
|
||||||
|
*/
|
||||||
|
void setVoltageMultiplier(float multiplier)
|
||||||
|
{
|
||||||
|
voltageMultiplier = multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the voltage multiplier value
|
||||||
|
* A multiplier that may need adjusting for different voltage divider setups
|
||||||
|
*/
|
||||||
|
float getVoltageMultiplier()
|
||||||
|
{
|
||||||
|
return voltageMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get auto-off feature enabled status
|
* Get auto-off feature enabled status
|
||||||
|
Loading…
Reference in New Issue
Block a user