@@ -25,14 +25,17 @@ See more at https://thingpulse.com
2525#include < time.h>
2626#include " Astronomy.h"
2727
28+ /* pi/180 */
29+ #define RPD 1.74532925199e-2
30+
2831Astronomy::Astronomy () {
2932
3033}
3134
3235/* *
33- * Convenience method to calculate moonphase by unix time stamp.
34- * See calculateMoonPhase(int year, int month, int day) for more details.
35- */
36+ * Convenience method to calculate moon phase by unix time stamp. See calculateMoonPhase(int year, int month, int day)
37+ * for details.
38+ */
3639uint8_t Astronomy::calculateMoonPhase (time_t timestamp) {
3740 struct tm * timeInfo;
3841 timeInfo = localtime (×tamp);
@@ -78,3 +81,84 @@ uint8_t Astronomy::calculateMoonPhase(uint16_t year, uint8_t month, uint8_t day)
7881 phase = phase & 7 ; // 0 and 8 are the same so turn 8 into 0
7982 return phase;
8083}
84+
85+ /* *
86+ * Convenience method to calculate moon phase and illumination by unix time stamp. See
87+ * calculateMoonData(int year, int month, int day) for details.
88+ */
89+ Astronomy::MoonData Astronomy::calculateMoonData (time_t timestamp) {
90+ struct tm * timeInfo;
91+ timeInfo = localtime (×tamp);
92+ return calculateMoonData (timeInfo->tm_year + 1900 , timeInfo->tm_mon + 1 , timeInfo->tm_mday );
93+ }
94+ /* *
95+ * Calculates the moon phase and illumination for a given date, accurate to 1 segment.
96+ * The result is in the range 0..7 for the phase.
97+ * 0 => new moon
98+ * 4 => full moon
99+ * Illumination ranges from 0.0 (new moon) to 1.0 (full moon).
100+ *
101+ * Source: Hugh from https://www.voidware.com
102+ */
103+ Astronomy::MoonData Astronomy::calculateMoonData (uint16_t year, uint8_t month, uint8_t day) {
104+
105+ MoonData moonData;
106+
107+ // from Gregorian year, month, day, calculate the Julian Day number
108+ uint8_t c;
109+ uint32_t jd;
110+ if (month < 3 ) {
111+ --year;
112+ month += 10 ;
113+ } else month -= 2 ;
114+
115+ c = year / 100 ;
116+ jd += 30.59 * month;
117+ jd += 365.25 * year;
118+ jd += day;
119+ jd += c / 4 - c;
120+
121+ // adjust to Julian centuries from noon, the day specified.
122+ double t = (jd - 730455.5 ) / 36525 ;
123+
124+ // following calculation from Astronomical Algorithms, Jean Meeus
125+ // D, M, MM from (47.2, 47.3, 47.3 page 338)
126+
127+ // mean elongation of the moon
128+ double D = 297.8501921 + t * (445267.1114034 +
129+ t * (-0.0018819 + t * (1.0 / 545868 - t / 113065000 )));
130+
131+ // suns mean anomaly
132+ double M = 357.5291092 + t * (35999.0502909 + t * (-0.0001536 + t / 24490000 ));
133+
134+ // moons mean anomaly
135+ double MM = 134.9633964 +
136+ t * (477198.8675055 + t * (0.0087414 + t * (1.0 / 69699 - t / 14712000 )));
137+
138+ // (48.4 p346)
139+ double i = 180 - D
140+ - 6.289 * sin (MM * RPD)
141+ + 2.100 * sin (M * RPD)
142+ - 1.274 * sin ((2 * D - MM) * RPD)
143+ - 0.658 * sin (2 * D * RPD)
144+ - 0.214 * sin (2 * MM * RPD)
145+ - 0.110 * sin (D * RPD);
146+
147+ if (i < 0 ) i = -i;
148+ if (i >= 360 ) i -= floor (i / 360 ) * 360 ;
149+
150+ // (48.1 p 345)
151+ // this is the proportion illuminated calculated from `i`, the phase angle
152+ double k = (1 + cos (i * RPD)) / 2 ;
153+
154+ // but for the `phase` don't use the phase angle
155+ // instead just consider the 0-360 cycle to get equal parts per phase
156+ uint8_t ki = i / 22.5 ;
157+ if (++ki == 16 ) ki = 0 ;
158+ ki = (ki / 2 + 4 ) & 7 ;
159+
160+ moonData.phase = ki;
161+ moonData.illumination = k;
162+
163+ return moonData;
164+ }
0 commit comments