From 512f681c3aa75e99b0cfed7ca1cb24a531c4ad65 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Thu, 2 Jan 2025 17:24:05 +0800 Subject: [PATCH 1/8] add usermod : Brightness Follow Sun --- .../README.md | 29 +++++ .../usermod_v2_brightness_follow_sun.h | 114 ++++++++++++++++++ wled00/const.h | 1 + wled00/usermods_list.cpp | 8 ++ 4 files changed, 152 insertions(+) create mode 100644 usermods/usermod_v2_brightness_follow_sun/README.md create mode 100644 usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h diff --git a/usermods/usermod_v2_brightness_follow_sun/README.md b/usermods/usermod_v2_brightness_follow_sun/README.md new file mode 100644 index 0000000000..9fffe7f2e9 --- /dev/null +++ b/usermods/usermod_v2_brightness_follow_sun/README.md @@ -0,0 +1,29 @@ +# Update Brightness Follow Sun + + +## Installation + +define `USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` e.g. + +`#define USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` in my_config.h + +or add `-D USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` to `build_flags` in platformio_override.ini + +### Define Your Options + +Open Usermod Settings in WLED to change settings: + +`Update Interval(sec)` - update interval for change brightness +`Min Brightness` - set brightness by map of min-max-min : sunrise-suntop-sunset +`Max Brightness` - as as +`Relax Hour` - before sunrise and after sunset, maintain the min brightness for several hours + + +### PlatformIO requirements + +No special requirements. + +## Change Log + +2025-01-02 +* init diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h new file mode 100644 index 0000000000..479a85f14b --- /dev/null +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -0,0 +1,114 @@ +#pragma once + +#include "wled.h" + +//v2 usermod that allows to change brightness and color using a rotary encoder, +//change between modes by pressing a button (many encoders have one included) +class UsermodBrightnessFollowSun : public Usermod +{ +private: + static const char _name[]; + static const char _enabled[]; + static const char _update_interval[]; + static const char _min_bri[]; + static const char _max_bri[]; + static const char _relax_hour[]; + +private: + bool enabled = false; //WLEDMM + unsigned long update_interval = 60; + int min_bri = 0; + int max_bri = 255; + int relax_hour = 0; + int relaxSec = 0; + unsigned long lastUMRun = 0; +public: + float mapFloat(float inputValue, float inMin, float inMax, float outMin, float outMax) { + if (inMax == inMin) + return outMin; + + inputValue = constrain(inputValue, inMin, inMax); + + return ((inputValue - inMin) * (outMax - outMin) / (inMax - inMin)) + outMin; + } + + uint16_t getId() override + { + return USERMOD_ID_BRIGHTNESS_FOLLOW_SUN; + } + + void loop() override + { + if (!enabled || strip.isUpdating() || sunrise == 0 || sunset == 0 || localTime == 0) + return; + + if (millis() - lastUMRun > (update_interval*1000)) + return; + lastUMRun = millis(); + + int sunriseSec = elapsedSecsToday(sunrise); + int sunsetSec = elapsedSecsToday(sunset); + int sunMiddleSec = sunriseSec + (sunsetSec-sunriseSec)/2; + int curSec = elapsedSecsToday(localTime); + + int relaxSecH = sunriseSec-relaxSec; + int relaxSecE = sunsetSec+relaxSec; + + int briSet = 0; + if (curSec >= relaxSecH && curSec <= relaxSecE) { + briSet = curSec < sunMiddleSec ? + mapFloat(curSec, sunriseSec, sunMiddleSec, min_bri, max_bri) : + mapFloat(curSec, sunMiddleSec, sunsetSec, max_bri, min_bri) ; + } + + bri = briSet; + stateUpdated(CALL_MODE_DIRECT_CHANGE); +} + + void addToConfig(JsonObject& root) + { + JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname + + top[FPSTR(_enabled)] = enabled; + top[FPSTR(_update_interval)] = update_interval; + top[FPSTR(_min_bri)] = min_bri; + top[FPSTR(_max_bri)] = max_bri; + top[FPSTR(_relax_hour)] = relax_hour; + } + + bool readFromConfig(JsonObject& root) + { + JsonObject top = root[FPSTR(_name)]; + if (top.isNull()) { + DEBUG_PRINTF("[%s] No config found. (Using defaults.)\n", _name); + return false; + } + + bool configComplete = true; + + configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false); + configComplete &= getJsonValue(top[FPSTR(_update_interval)], update_interval, 60); + configComplete &= getJsonValue(top[FPSTR(_min_bri)], min_bri, 0); + configComplete &= getJsonValue(top[FPSTR(_max_bri)], max_bri, 255); + configComplete &= getJsonValue(top[FPSTR(_relax_hour)], relax_hour, 0); + + update_interval = constrain(update_interval, 1, SECS_PER_HOUR); + _min_bri = constrain(_min_bri, 0, 255); + _max_bri = constrain(_max_bri, 0, 255); + _relax_hour = constrain(_relax_hour, 0, 3); + + relaxSec = SECS_PER_HOUR*_relax_hour; + + lastUMRun = millis()-(update_interval*1000); + + return configComplete; + } +}; + + +const char UsermodBrightnessFollowSun::_name[] PROGMEM = "Brightness Follow Sun"; +const char UsermodBrightnessFollowSun::_enabled[] PROGMEM = "Enabled"; +const char UsermodBrightnessFollowSun::_update_interval[] PROGMEM = "Update Interval(sec)"; +const char UsermodBrightnessFollowSun::_min_bri[] PROGMEM = "Min Brightness"; +const char UsermodBrightnessFollowSun::_max_bri[] PROGMEM = "Max Brightness"; +const char UsermodBrightnessFollowSun::_relax_hour[] PROGMEM = "Relax Hour"; diff --git a/wled00/const.h b/wled00/const.h index 928b150dac..f4de314335 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -203,6 +203,7 @@ #define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h" #define USERMOD_ID_POV_DISPLAY 53 //Usermod "usermod_pov_display.h" #define USERMOD_ID_PIXELS_DICE_TRAY 54 //Usermod "pixels_dice_tray.h" +#define USERMOD_ID_BRIGHTNESS_FOLLOW_SUN 55 //Usermod "usermod_v2_brightness_follow_sun.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 3283e013b2..46ef63b1c8 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -242,6 +242,10 @@ #include "../usermods/LD2410_v2/usermod_ld2410.h" #endif +#ifdef USERMOD_BRIGHTNESS_FOLLOW_SUN + #include "../usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h" +#endif + void registerUsermods() { /* @@ -470,4 +474,8 @@ void registerUsermods() #ifdef USERMOD_POV_DISPLAY UsermodManager::add(new PovDisplayUsermod()); #endif + + #ifdef USERMOD_BRIGHTNESS_FOLLOW_SUN + UsermodManager::add(new UsermodBrightnessFollowSun()); + #endif } From c5405f34a5c7d6aca359c9888108a6445328cf29 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Thu, 2 Jan 2025 17:52:02 +0800 Subject: [PATCH 2/8] change int relax_hour to float --- .../usermod_v2_brightness_follow_sun.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index 479a85f14b..b1eed70e8d 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -19,7 +19,7 @@ class UsermodBrightnessFollowSun : public Usermod unsigned long update_interval = 60; int min_bri = 0; int max_bri = 255; - int relax_hour = 0; + float relax_hour = 0; int relaxSec = 0; unsigned long lastUMRun = 0; public: From 4d4fda8ca276a29550168480a81a454c486d0301 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Sun, 12 Jan 2025 22:17:51 +0800 Subject: [PATCH 3/8] improve usermod brightness follow sun --- .../README.md | 6 +-- .../usermod_v2_brightness_follow_sun.h | 44 ++++++++++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/README.md b/usermods/usermod_v2_brightness_follow_sun/README.md index 9fffe7f2e9..da4116eae6 100644 --- a/usermods/usermod_v2_brightness_follow_sun/README.md +++ b/usermods/usermod_v2_brightness_follow_sun/README.md @@ -3,11 +3,11 @@ ## Installation -define `USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` e.g. +define `USERMOD_BRIGHTNESS_FOLLOW_SUN` e.g. -`#define USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` in my_config.h +`#define USERMOD_BRIGHTNESS_FOLLOW_SUN` in my_config.h -or add `-D USERMOD_ID_BRIGHTNESS_FOLLOW_SUN` to `build_flags` in platformio_override.ini +or add `-D USERMOD_BRIGHTNESS_FOLLOW_SUN` to `build_flags` in platformio_override.ini ### Define Your Options diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index b1eed70e8d..3b61e9a6cf 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -17,12 +17,16 @@ class UsermodBrightnessFollowSun : public Usermod private: bool enabled = false; //WLEDMM unsigned long update_interval = 60; - int min_bri = 0; + unsigned long update_interval_ms = 60000; + int min_bri = 1; int max_bri = 255; float relax_hour = 0; int relaxSec = 0; unsigned long lastUMRun = 0; public: + + void setup() {}; + float mapFloat(float inputValue, float inMin, float inMax, float outMin, float outMax) { if (inMax == inMin) return outMin; @@ -37,19 +41,15 @@ class UsermodBrightnessFollowSun : public Usermod return USERMOD_ID_BRIGHTNESS_FOLLOW_SUN; } - void loop() override + void update() { - if (!enabled || strip.isUpdating() || sunrise == 0 || sunset == 0 || localTime == 0) + if (sunrise == 0 || sunset == 0 || localTime == 0) return; - if (millis() - lastUMRun > (update_interval*1000)) - return; - lastUMRun = millis(); - + int curSec = elapsedSecsToday(localTime); int sunriseSec = elapsedSecsToday(sunrise); int sunsetSec = elapsedSecsToday(sunset); int sunMiddleSec = sunriseSec + (sunsetSec-sunriseSec)/2; - int curSec = elapsedSecsToday(localTime); int relaxSecH = sunriseSec-relaxSec; int relaxSecE = sunsetSec+relaxSec; @@ -65,6 +65,18 @@ class UsermodBrightnessFollowSun : public Usermod stateUpdated(CALL_MODE_DIRECT_CHANGE); } + void loop() override + { + if (!enabled || strip.isUpdating()) + return; + + if (millis() - lastUMRun > update_interval_ms) + return; + lastUMRun = millis(); + + update(); + } + void addToConfig(JsonObject& root) { JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname @@ -88,18 +100,20 @@ class UsermodBrightnessFollowSun : public Usermod configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false); configComplete &= getJsonValue(top[FPSTR(_update_interval)], update_interval, 60); - configComplete &= getJsonValue(top[FPSTR(_min_bri)], min_bri, 0); + configComplete &= getJsonValue(top[FPSTR(_min_bri)], min_bri, 1); configComplete &= getJsonValue(top[FPSTR(_max_bri)], max_bri, 255); configComplete &= getJsonValue(top[FPSTR(_relax_hour)], relax_hour, 0); update_interval = constrain(update_interval, 1, SECS_PER_HOUR); - _min_bri = constrain(_min_bri, 0, 255); - _max_bri = constrain(_max_bri, 0, 255); - _relax_hour = constrain(_relax_hour, 0, 3); + min_bri = constrain(min_bri, 1, 255); + max_bri = constrain(max_bri, 1, 255); + relax_hour = constrain(relax_hour, 0, 6); - relaxSec = SECS_PER_HOUR*_relax_hour; + update_interval_ms = update_interval*1000; + relaxSec = SECS_PER_HOUR*relax_hour; - lastUMRun = millis()-(update_interval*1000); + lastUMRun = 0; + update(); return configComplete; } @@ -108,7 +122,7 @@ class UsermodBrightnessFollowSun : public Usermod const char UsermodBrightnessFollowSun::_name[] PROGMEM = "Brightness Follow Sun"; const char UsermodBrightnessFollowSun::_enabled[] PROGMEM = "Enabled"; -const char UsermodBrightnessFollowSun::_update_interval[] PROGMEM = "Update Interval(sec)"; +const char UsermodBrightnessFollowSun::_update_interval[] PROGMEM = "Update Interval Sec"; const char UsermodBrightnessFollowSun::_min_bri[] PROGMEM = "Min Brightness"; const char UsermodBrightnessFollowSun::_max_bri[] PROGMEM = "Max Brightness"; const char UsermodBrightnessFollowSun::_relax_hour[] PROGMEM = "Relax Hour"; From ab9b49ccfb0fd2d34ce1356ff91b2fdbf0d5115d Mon Sep 17 00:00:00 2001 From: yangminglong Date: Sun, 12 Jan 2025 22:59:29 +0800 Subject: [PATCH 4/8] Update usermod_v2_brightness_follow_sun.h --- .../usermod_v2_brightness_follow_sun.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index 3b61e9a6cf..22e53b66ca 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -70,7 +70,7 @@ class UsermodBrightnessFollowSun : public Usermod if (!enabled || strip.isUpdating()) return; - if (millis() - lastUMRun > update_interval_ms) + if (millis() - lastUMRun < update_interval_ms) return; lastUMRun = millis(); From 4c2c6ee1a0d573dbc9aeb7547f2844eaf726f989 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Tue, 21 Jan 2025 14:18:51 +0800 Subject: [PATCH 5/8] Update usermod_v2_brightness_follow_sun.h --- .../usermod_v2_brightness_follow_sun.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index 22e53b66ca..2c07fc3c4c 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -56,9 +56,11 @@ class UsermodBrightnessFollowSun : public Usermod int briSet = 0; if (curSec >= relaxSecH && curSec <= relaxSecE) { - briSet = curSec < sunMiddleSec ? - mapFloat(curSec, sunriseSec, sunMiddleSec, min_bri, max_bri) : - mapFloat(curSec, sunMiddleSec, sunsetSec, max_bri, min_bri) ; + float timeMapToAngle = curSec < sunMiddleSec ? + mapFloat(curSec, sunriseSec, sunMiddleSec, 0, M_PI/2.0) : + mapFloat(curSec, sunMiddleSec, sunsetSec, M_PI/2.0, M_PI); + float sinValue = sin(timeMapToAngle); + briSet = min_bri + (max_bri-min_bri)*sinValue; } bri = briSet; From 06ce989193c7a934c37e6ce58e20148770589933 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Tue, 21 Jan 2025 14:42:07 +0800 Subject: [PATCH 6/8] Update README.md --- .../usermod_v2_brightness_follow_sun/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/README.md b/usermods/usermod_v2_brightness_follow_sun/README.md index da4116eae6..2c4dba7c5a 100644 --- a/usermods/usermod_v2_brightness_follow_sun/README.md +++ b/usermods/usermod_v2_brightness_follow_sun/README.md @@ -1,22 +1,26 @@ # Update Brightness Follow Sun +This UserMod can set brightness by mapping [minimum-maximum-minimum] from [sunrise-suntop-sunset], I use this UserMod to adjust the brightness of my plant growth light (pwm led), and I think it will make my plants happy. -## Installation +This UserMod will adjust brightness from sunrise to sunset, reaching maximum brightness at the zenith of the sun. It can also maintain the lowest brightness within 0-6 hours before sunrise and after sunset according to the settings. -define `USERMOD_BRIGHTNESS_FOLLOW_SUN` e.g. +## Installation -`#define USERMOD_BRIGHTNESS_FOLLOW_SUN` in my_config.h +define `USERMOD_BRIGHTNESS_FOLLOW_SUN` e.g. `#define USERMOD_BRIGHTNESS_FOLLOW_SUN` in my_config.h or add `-D USERMOD_BRIGHTNESS_FOLLOW_SUN` to `build_flags` in platformio_override.ini -### Define Your Options +### Options Open Usermod Settings in WLED to change settings: -`Update Interval(sec)` - update interval for change brightness +`Update Interval Sec` - The unit is seconds, and the brightness will be automatically refreshed according to the set parameters. + `Min Brightness` - set brightness by map of min-max-min : sunrise-suntop-sunset -`Max Brightness` - as as -`Relax Hour` - before sunrise and after sunset, maintain the min brightness for several hours + +`Max Brightness` - It needs to be set to a value greater than `Min Brightness`, otherwise it will always remain at `Min Brightness`. + +`Relax Hour` - The unit is in hours, with an effective range of 0-6. According to the settings, maintain the lowest brightness for 0-6 hours before sunrise and after sunset. ### PlatformIO requirements From 39d19e33cd46df88c014a2bcd4728d5c7e867deb Mon Sep 17 00:00:00 2001 From: yangminglong Date: Wed, 5 Feb 2025 10:36:51 +0800 Subject: [PATCH 7/8] use sin_t() instead sin() which is a much smaller footprint sine approximation --- .../usermod_v2_brightness_follow_sun.h | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index 2c07fc3c4c..dd31154a15 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -36,6 +36,27 @@ class UsermodBrightnessFollowSun : public Usermod return ((inputValue - inMin) * (outMax - outMin) / (inMax - inMin)) + outMin; } + // Taylor series expansion implementation of sin_t + float sin_t(float angle) { + // Normalize the angle to the range of [-π, π] + // while (angle > M_PI) angle -= 2 * PI; + // while (angle < -M_PI) angle += 2 * PI; + + // Taylor series expansion for calculating sine values + float angle2 = angle * angle; + float angle3 = angle2 * angle; + float angle5 = angle3 * angle2; + float angle7 = angle5 * angle2; + + // Taylor series formula:sin(x) ≈ x - x^3/3! + x^5/5! - x^7/7! + float result = angle + - angle3 / 6.0f + + angle5 / 120.0f + - angle7 / 5040.0f; + + return result; + } + uint16_t getId() override { return USERMOD_ID_BRIGHTNESS_FOLLOW_SUN; @@ -59,7 +80,7 @@ class UsermodBrightnessFollowSun : public Usermod float timeMapToAngle = curSec < sunMiddleSec ? mapFloat(curSec, sunriseSec, sunMiddleSec, 0, M_PI/2.0) : mapFloat(curSec, sunMiddleSec, sunsetSec, M_PI/2.0, M_PI); - float sinValue = sin(timeMapToAngle); + float sinValue = sin_t(timeMapToAngle); briSet = min_bri + (max_bri-min_bri)*sinValue; } From c957a168860847f04ed5a4ea9d907238084fb7d7 Mon Sep 17 00:00:00 2001 From: yangminglong Date: Fri, 7 Feb 2025 10:20:04 +0800 Subject: [PATCH 8/8] use sin_t() from fcn_declare.h but not implement a new sin_t() function --- .../usermod_v2_brightness_follow_sun.h | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h index dd31154a15..99f646b216 100644 --- a/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h +++ b/usermods/usermod_v2_brightness_follow_sun/usermod_v2_brightness_follow_sun.h @@ -36,27 +36,6 @@ class UsermodBrightnessFollowSun : public Usermod return ((inputValue - inMin) * (outMax - outMin) / (inMax - inMin)) + outMin; } - // Taylor series expansion implementation of sin_t - float sin_t(float angle) { - // Normalize the angle to the range of [-π, π] - // while (angle > M_PI) angle -= 2 * PI; - // while (angle < -M_PI) angle += 2 * PI; - - // Taylor series expansion for calculating sine values - float angle2 = angle * angle; - float angle3 = angle2 * angle; - float angle5 = angle3 * angle2; - float angle7 = angle5 * angle2; - - // Taylor series formula:sin(x) ≈ x - x^3/3! + x^5/5! - x^7/7! - float result = angle - - angle3 / 6.0f - + angle5 / 120.0f - - angle7 / 5040.0f; - - return result; - } - uint16_t getId() override { return USERMOD_ID_BRIGHTNESS_FOLLOW_SUN;