diff --git a/usermods/battery_status_basic/assets/battery_connection_schematic_01.png b/usermods/battery_status_basic/assets/battery_connection_schematic_01.png new file mode 100644 index 000000000..5ce01de68 Binary files /dev/null and b/usermods/battery_status_basic/assets/battery_connection_schematic_01.png differ diff --git a/usermods/battery_status_basic/assets/battery_connection_schematic_02.png b/usermods/battery_status_basic/assets/battery_connection_schematic_02.png new file mode 100644 index 000000000..03f41ca0d Binary files /dev/null and b/usermods/battery_status_basic/assets/battery_connection_schematic_02.png differ diff --git a/usermods/battery_status_basic/assets/battery_info_screen.png b/usermods/battery_status_basic/assets/battery_info_screen.png new file mode 100644 index 000000000..50eb53465 Binary files /dev/null and b/usermods/battery_status_basic/assets/battery_info_screen.png differ diff --git a/usermods/battery_status_basic/readme.md b/usermods/battery_status_basic/readme.md index 7bff98f46..276b23c19 100644 --- a/usermods/battery_status_basic/readme.md +++ b/usermods/battery_status_basic/readme.md @@ -2,16 +2,25 @@ This Usermod allows you to monitor the battery level of your battery powered project. -You can see the battery level in the `info modal` right under the `estimated current`. +You can see the battery level and voltage in the `info modal`. For this to work the positive side of the (18650) battery must be connected to pin `A0` of the d1mini/esp8266 with a 100k ohm resistor (see [Useful Links](#useful-links)). If you have a esp32 board it is best to connect the positive side of the battery to ADC1 (GPIO32 - GPIO39) +

+ +

+ ## Installation define `USERMOD_BATTERY_STATUS_BASIC` in `my_config.h` +### Basic wiring diagram +

+ +

+ ### Define Your Options * `USERMOD_BATTERY_STATUS_BASIC` - define this (in `my_config.h`) to have this user mod included wled00\usermods_list.cpp @@ -45,6 +54,11 @@ Specification from: [Molicel INR18650-M35A, 3500mAh 10A Lithium-ion battery, 3. * https://arduinodiy.wordpress.com/2016/12/25/monitoring-lipo-battery-voltage-with-wemos-d1-minibattery-shield-and-thingspeak/ ## Change Log +2021-09-02 +* added "Battery voltage" to info +* added circuit diagram to readme +* added MQTT support, sending battery voltage +* minor fixes 2021-08-15 * changed `USERMOD_BATTERY_MIN_VOLTAGE` to 2.6 volt as default for 18650 batteries diff --git a/usermods/battery_status_basic/usermod_v2_battery_status_basic.h b/usermods/battery_status_basic/usermod_v2_battery_status_basic.h index f6271c272..ab9cba3bc 100644 --- a/usermods/battery_status_basic/usermod_v2_battery_status_basic.h +++ b/usermods/battery_status_basic/usermod_v2_battery_status_basic.h @@ -29,7 +29,7 @@ #endif -// the frequency to check the battery, 1 minute +// the frequency to check the battery, 30 sec #ifndef USERMOD_BATTERY_MEASUREMENT_INTERVAL #define USERMOD_BATTERY_MEASUREMENT_INTERVAL 30000 #endif @@ -53,7 +53,8 @@ class UsermodBatteryBasic : public Usermod int8_t batteryPin = USERMOD_BATTERY_MEASUREMENT_PIN; // how often to read the battery voltage unsigned long readingInterval = USERMOD_BATTERY_MEASUREMENT_INTERVAL; - unsigned long lastTime = 0; + unsigned long nextReadTime = 0; + unsigned long lastReadTime = 0; // battery min. voltage float minBatteryVoltage = USERMOD_BATTERY_MIN_VOLTAGE; // battery max. voltage @@ -68,6 +69,7 @@ class UsermodBatteryBasic : public Usermod // mapped battery level based on voltage long batteryLevel = 0; bool initDone = false; + bool initializing = true; // strings to reduce flash memory usage (used more than twice) @@ -82,6 +84,19 @@ class UsermodBatteryBasic : public Usermod return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } + float truncate(float val, byte dec) + { + float x = val * pow(10, dec); + float y = round(x); + float z = x - y; + if ((int)z == 5) + { + y++; + } + x = y / pow(10, dec); + return x; + } + public: @@ -107,6 +122,9 @@ class UsermodBatteryBasic : public Usermod pinMode(batteryPin, INPUT); #endif + nextReadTime = millis() + readingInterval; + lastReadTime = millis(); + initDone = true; } @@ -129,26 +147,38 @@ class UsermodBatteryBasic : public Usermod { if(strip.isUpdating()) return; - unsigned long now = millis(); - // check the battery level every USERMOD_BATTERY_MEASUREMENT_INTERVAL (ms) - if (now - lastTime >= readingInterval) { + if (millis() < nextReadTime) return; - // read battery raw input - rawValue = analogRead(batteryPin); - // calculate the voltage - voltage = (rawValue / adcPrecision) * maxBatteryVoltage ; + nextReadTime = millis() + readingInterval; + lastReadTime = millis(); + initializing = false; - // translate battery voltage into percentage - /* - the standard "map" function doesn't work - https://www.arduino.cc/reference/en/language/functions/math/map/ notes and warnings at the bottom - */ - batteryLevel = mapf(voltage, minBatteryVoltage, maxBatteryVoltage, 0, 100); + // read battery raw input + rawValue = analogRead(batteryPin); - lastTime = now; + // calculate the voltage + voltage = (rawValue / adcPrecision) * maxBatteryVoltage ; + // check if voltage is within specified voltage range + voltage = voltagemaxBatteryVoltage?-1.0f:voltage; + + // translate battery voltage into percentage + /* + the standard "map" function doesn't work + https://www.arduino.cc/reference/en/language/functions/math/map/ notes and warnings at the bottom + */ + batteryLevel = mapf(voltage, minBatteryVoltage, maxBatteryVoltage, 0, 100); + + + // SmartHome stuff + if (WLED_MQTT_CONNECTED) { + char subuf[64]; + strcpy(subuf, mqttDeviceTopic); + strcat_P(subuf, PSTR("/voltage")); + mqtt->publish(subuf, 0, false, String(voltage).c_str()); } + } @@ -163,9 +193,31 @@ class UsermodBatteryBasic : public Usermod JsonObject user = root["u"]; if (user.isNull()) user = root.createNestedObject("u"); - JsonArray battery = user.createNestedArray("Battery level"); - battery.add(batteryLevel); - battery.add(F(" %")); + // info modal display names + JsonArray batteryPercentage = user.createNestedArray("Battery level"); + JsonArray batteryVoltage = user.createNestedArray("Battery voltage"); + + if (initializing) { + batteryPercentage.add((nextReadTime - millis()) / 1000); + batteryPercentage.add(" sec"); + batteryVoltage.add((nextReadTime - millis()) / 1000); + batteryVoltage.add(" sec"); + return; + } + + if(batteryLevel < 0) { + batteryPercentage.add(F("invalid")); + } else { + batteryPercentage.add(batteryLevel); + } + batteryPercentage.add(F(" %")); + + if(voltage < 0) { + batteryVoltage.add(F("invalid")); + } else { + batteryVoltage.add(truncate(voltage, 2)); + } + batteryVoltage.add(F(" V")); }