Switch trigonometric implementation, saves 460b memory
This commit is contained in:
parent
5751d5c1b0
commit
f3b84f1365
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
### Builds after release 0.12.0
|
### Builds after release 0.12.0
|
||||||
|
|
||||||
|
#### Build 2104141
|
||||||
|
|
||||||
|
- Reduced memory usage by 540b by switching to a different trigonometric approximation
|
||||||
|
|
||||||
#### Build 2104140
|
#### Build 2104140
|
||||||
|
|
||||||
- Added dynamic location-based Sunrise/Sunset macros (PR #1889)
|
- Added dynamic location-based Sunrise/Sunset macros (PR #1889)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "src/dependencies/timezone/Timezone.h"
|
#include "src/dependencies/timezone/Timezone.h"
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#include "wled_math.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquires time from NTP server
|
* Acquires time from NTP server
|
||||||
@ -316,8 +317,8 @@ void checkTimers()
|
|||||||
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location
|
// get sunrise (or sunset) time (in minutes) for a given day at a given geo location
|
||||||
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false) {
|
||||||
//1. first calculate the day of the year
|
//1. first calculate the day of the year
|
||||||
float N1 = floor(275 * month / 9);
|
float N1 = 275 * month / 9;
|
||||||
float N2 = floor((month + 9) / 12);
|
float N2 = (month + 9) / 12;
|
||||||
float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
|
float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
|
||||||
float N = N1 - (N2 * N3) + day - 30;
|
float N = N1 - (N2 * N3) + day - 30;
|
||||||
|
|
||||||
@ -329,10 +330,10 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
|||||||
float M = (0.9856 * t) - 3.289;
|
float M = (0.9856 * t) - 3.289;
|
||||||
|
|
||||||
//4. calculate the Sun's true longitude
|
//4. calculate the Sun's true longitude
|
||||||
float L = fmod(M + (1.916 * sin(DEG_TO_RAD*M)) + (0.020 * sin(2*DEG_TO_RAD*M)) + 282.634, 360.0);
|
float L = fmod(M + (1.916 * sin_t(DEG_TO_RAD*M)) + (0.020 * sin_t(2*DEG_TO_RAD*M)) + 282.634, 360.0);
|
||||||
|
|
||||||
//5a. calculate the Sun's right ascension
|
//5a. calculate the Sun's right ascension
|
||||||
float RA = fmod(RAD_TO_DEG*atan(0.91764 * tan(DEG_TO_RAD*L)), 360.0);
|
float RA = fmod(RAD_TO_DEG*atan_t(0.91764 * tan_t(DEG_TO_RAD*L)), 360.0);
|
||||||
|
|
||||||
//5b. right ascension value needs to be in the same quadrant as L
|
//5b. right ascension value needs to be in the same quadrant as L
|
||||||
float Lquadrant = floor( L/90) * 90;
|
float Lquadrant = floor( L/90) * 90;
|
||||||
@ -343,16 +344,16 @@ int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunse
|
|||||||
RA /= 15.;
|
RA /= 15.;
|
||||||
|
|
||||||
//6. calculate the Sun's declination
|
//6. calculate the Sun's declination
|
||||||
float sinDec = 0.39782 * sin(DEG_TO_RAD*L);
|
float sinDec = 0.39782 * sin_t(DEG_TO_RAD*L);
|
||||||
float cosDec = cos(asin(sinDec));
|
float cosDec = cos_t(asin_t(sinDec));
|
||||||
|
|
||||||
//7a. calculate the Sun's local hour angle
|
//7a. calculate the Sun's local hour angle
|
||||||
float cosH = (sin(DEG_TO_RAD*ZENITH) - (sinDec * sin(DEG_TO_RAD*lat))) / (cosDec * cos(DEG_TO_RAD*lat));
|
float cosH = (sin_t(DEG_TO_RAD*ZENITH) - (sinDec * sin_t(DEG_TO_RAD*lat))) / (cosDec * cos_t(DEG_TO_RAD*lat));
|
||||||
if (cosH > 1 && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
if (cosH > 1 && !sunset) return 0; // the sun never rises on this location (on the specified date)
|
||||||
if (cosH < -1 && sunset) return 0; // the sun never sets on this location (on the specified date)
|
if (cosH < -1 && sunset) return 0; // the sun never sets on this location (on the specified date)
|
||||||
|
|
||||||
//7b. finish calculating H and convert into hours
|
//7b. finish calculating H and convert into hours
|
||||||
float H = sunset ? RAD_TO_DEG*acos(cosH) : 360 - RAD_TO_DEG*acos(cosH);
|
float H = sunset ? RAD_TO_DEG*acos_t(cosH) : 360 - RAD_TO_DEG*acos_t(cosH);
|
||||||
H /= 15.;
|
H /= 15.;
|
||||||
|
|
||||||
//8. calculate local mean time of rising/setting
|
//8. calculate local mean time of rising/setting
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2104140
|
#define VERSION 2104141
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
71
wled00/wled_math.h
Normal file
71
wled00/wled_math.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef WLED_MATH_H
|
||||||
|
#define WLED_MATH_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains some trigonometric functions.
|
||||||
|
* The ANSI C equivalents are likely faster, but using any sin/cos/tan function incurs a memory penalty of 460 bytes on ESP8266, likely for lookup tables.
|
||||||
|
* This implementation has no extra static memory usage.
|
||||||
|
*
|
||||||
|
* Source of the cos_t() function: https://web.eecs.utk.edu/~azh/blog/cosine.html (cos_taylor_literal_6terms)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h> //PI constant
|
||||||
|
|
||||||
|
#define modd(x, y) ((x) - (int)((x) / (y)) * (y))
|
||||||
|
|
||||||
|
double cos_t(double x)
|
||||||
|
{
|
||||||
|
x = modd(x, TWO_PI);
|
||||||
|
char sign = 1;
|
||||||
|
if (x > PI)
|
||||||
|
{
|
||||||
|
x -= PI;
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
double 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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double sin_t(double x) {
|
||||||
|
return cos_t(HALF_PI - x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double tan_t(double x) {
|
||||||
|
double c = cos_t(x);
|
||||||
|
if (c==0.0) return 0;
|
||||||
|
return sin_t(x) / c;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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 ret = -0.0187293;
|
||||||
|
ret = ret * x;
|
||||||
|
ret = ret + 0.0742610;
|
||||||
|
ret = ret * x;
|
||||||
|
ret = ret - 0.2121144;
|
||||||
|
ret = ret * x;
|
||||||
|
ret = ret + HALF_PI;
|
||||||
|
ret = ret * sqrt(1.0-x);
|
||||||
|
ret = ret - 2 * negate * ret;
|
||||||
|
return negate * PI + ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
float asin_t(float x) {
|
||||||
|
return HALF_PI - acos_t(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://stackoverflow.com/a/42542593
|
||||||
|
#define A 0.0776509570923569
|
||||||
|
#define B -0.287434475393028
|
||||||
|
#define C ((HALF_PI/2) - A - B)
|
||||||
|
|
||||||
|
double atan_t(double x) {
|
||||||
|
double xx = x * x;
|
||||||
|
return ((A*xx + B)*xx + C)*x;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user