From 9b796531b2ddb3b2bc1de58003e406f2022b0790 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Sun, 23 May 2021 18:49:23 +0200 Subject: [PATCH] Fixed Sunrise calculation (atan_t approx. used outside of value range) --- CHANGELOG.md | 5 +++ wled00/mqtt.cpp | 2 +- wled00/wled_math.h | 81 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56c722e2..a989eaf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ### Builds after release 0.12.0 +#### Build 2105230 + +- No longer retain MQTT `/v` topic to alleviate storage loads on MQTT broker +- Fixed Sunrise calculation (atan_t approx. used outside of value range) + #### Build 2105200 - Fixed WS281x output on ESP32 diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 79de0afb..8540335b 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -137,7 +137,7 @@ void publishMqtt() XML_response(nullptr, apires); strcpy(subuf, mqttDeviceTopic); strcat_P(subuf, PSTR("/v")); - mqtt->publish(subuf, 0, true, apires); + mqtt->publish(subuf, 0, false, apires); } diff --git a/wled00/wled_math.h b/wled00/wled_math.h index 88d24179..8629ea09 100644 --- a/wled00/wled_math.h +++ b/wled00/wled_math.h @@ -11,6 +11,8 @@ #include //PI constant +//#define WLED_DEBUG_MATH + #define modd(x, y) ((x) - (int)((x) / (y)) * (y)) float cos_t(float x) @@ -24,38 +26,58 @@ float cos_t(float x) } float xx = x * x; - return sign * (1 - ((xx) / (2)) + ((xx * xx) / (24)) - ((xx * xx * xx) / (720)) + ((xx * xx * xx * xx) / (40320)) - ((xx * xx * xx * xx * xx) / (3628800)) + ((xx * xx * xx * xx * xx * xx) / (479001600))); + float res = sign * (1 - ((xx) / (2)) + ((xx * xx) / (24)) - ((xx * xx * xx) / (720)) + ((xx * xx * xx * xx) / (40320)) - ((xx * xx * xx * xx * xx) / (3628800)) + ((xx * xx * xx * xx * xx * xx) / (479001600))); + #ifdef WLED_DEBUG_MATH + Serial.printf("cos: %f,%f\n",res,cos(x)); + #endif + return res; } float sin_t(float x) { - return cos_t(HALF_PI - x); + float res = cos_t(HALF_PI - x); + #ifdef WLED_DEBUG_MATH + Serial.printf("sin: %f,%f\n",res,sin(x)); + #endif + return res; } float tan_t(float x) { float c = cos_t(x); if (c==0.0) return 0; - return sin_t(x) / c; + float res = sin_t(x) / c; + #ifdef WLED_DEBUG_MATH + Serial.printf("tan: %f,%f\n",res,tan(x)); + #endif + return res; } //https://stackoverflow.com/questions/3380628 // Absolute error <= 6.7e-5 float acos_t(float x) { float negate = float(x < 0); - x = std::abs(x); + float xabs = std::abs(x); float ret = -0.0187293; - ret = ret * x; + ret = ret * xabs; ret = ret + 0.0742610; - ret = ret * x; + ret = ret * xabs; ret = ret - 0.2121144; - ret = ret * x; + ret = ret * xabs; ret = ret + HALF_PI; - ret = ret * sqrt(1.0-x); + ret = ret * sqrt(1.0-xabs); ret = ret - 2 * negate * ret; - return negate * PI + ret; + float res = negate * PI + ret; + #ifdef WLED_DEBUG_MATH + Serial.printf("acos,%f,%f,%f\n",x,res,acos(x)); + #endif + return res; } float asin_t(float x) { - return HALF_PI - acos_t(x); + float res = HALF_PI - acos_t(x); + #ifdef WLED_DEBUG_MATH + Serial.printf("asin,%f,%f,%f\n",x,res,asin(x)); + #endif + return res; } //https://stackoverflow.com/a/42542593 @@ -63,21 +85,54 @@ float asin_t(float x) { #define B -0.287434475393028 #define C ((HALF_PI/2) - A - B) +//polynominal factors for approximation between 1 and 5 +#define C0 0.089494f +#define C1 0.974207f +#define C2 -0.326175f +#define C3 0.05375f +#define C4 -0.003445f + float atan_t(float x) { - float xx = x * x; - return ((A*xx + B)*xx + C)*x; + bool neg = (x < 0); + #ifdef WLED_DEBUG_MATH + float xinput = x; + #endif + x = std::abs(x); + float res; + if (x > 5.0f) { //atan(x) converges to pi/2 - (1/x) for large values + res = HALF_PI - (1.0f/x); + } + else if (x > 1.0f) { //1 < x < 5 + float xx = x * x; + res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0; + } else { //this approximation is only for x <= 1 + float xx = x * x; + res = ((A*xx + B)*xx + C)*x; + } + if (neg) res = -res; + #ifdef WLED_DEBUG_MATH + Serial.printf("atan,%f,%f,%f\n",xinput,res,atan(xinput)); + #endif + return res; } float floor_t(float x) { bool neg = x < 0; int val = x; if (neg) val--; + #ifdef WLED_DEBUG_MATH + Serial.printf("floor: %f,%f\n",val,floor(x)); + #endif return val; } float fmod_t(float num, float denom) { int tquot = num / denom; - return num - tquot * denom; + float res = num - tquot * denom; + #ifdef WLED_DEBUG_MATH + Serial.printf("fmod: %f,%f\n",res,fmod(num,denom)); + #endif + return res; } #endif \ No newline at end of file