JChristensen / JC_Sunrise

Arduino library to calculate sunrise and sunset times.
GNU General Public License v3.0
8 stars 1 forks source link

Cannot understand failed sketch #1

Closed terrypin999 closed 8 months ago

terrypin999 commented 8 months ago

Have spent an entire day trying to discover the cause of my sketch failure. I was hoping to get some clues from Issues here. But there are none! Really, no one with any problems?

I based the following on your single Example. Changed it for my ‘near London’ location. But I can find no combination of parameters that delivers consistent results. Please see the examples I’ve compared sketch results with accurate ones from online sources.

Would much appreciate your taking a look please. I’m not a C/C++ programmer, but determined to get this working.

`/* Mon 12 Feb 2024 1049; studied timezone advice from https://github.com/JChristensen/Timezone/blob/master/examples/WorldClock/WorldClock.ino

BUT STILL STRANGE RESULTS

Mon 12 Feb 2024 1848; try -60 instead of 0

Define a TimeChangeRule as follows:

TimeChangeRule myRule = {abbrev, week, dow, month, hour, offset}; Where: abbrev is a character string abbreviation for the time zone; it must be no longer than five characters. week is the week of the month that the rule starts. dow is the day of the week that the rule starts. hour is the hour in local time that the rule starts (0-23). offset is the UTC offset in minutes for the time zone being defined.

For convenience, the following symbolic names can be used: week: First, Second, Third, Fourth, Last dow: Sun, Mon, Tue, Wed, Thu, Fri, Sat month: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec

For the Eastern US time zone, the TimeChangeRules could be defined as follows:

TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -240}; //UTC - 4 hours TimeChangeRule usEST = {"EST", First, Sun, No

So for UK? TimeChangeRule usEDT = {"BST", Last, Sun, Mar, 1, 60}; // GMT + 1 hr TimeChangeRule usEST = {"GMT", Last, Sun, Oct, 1, 0};

Corrected by adding JC_Sunrise.h> */

include // https://github.com/PaulStoffregen/Time

include // https://github.com/JChristensen/Timezone

include // https://github.com/JChristensen/JC_Sunrise

include // https://github.com/janelia-arduino/Streaming

// Location parameters float myLat = 51.1287; // N 51.1278 float myLon = -0.0145; // W 0.0145

// UK (London, Belfast) copied from WorldClock.ino TimeChangeRule BST = {"BST", Last, Sun, Mar, 1, 60}; // BST starts

// Tried various changes //TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 1, 0}; // GMT resumes //TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 1, 0}; // GMT resumes TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 1, -60}; // GMT resumes Timezone UK(BST, GMT); /////////////////////////////////////////////////////// void setup() { Serial.begin(115200); delay(500);

// Input examples int doy2024 = 1; // First day of year, 1 January (GMT) should be calculateSunriseSunset(doy2024); // Sunrise 08:07 Sunset: 19:32

doy2024 = 43; // Today, 12 February (GMT) should be calculateSunriseSunset(doy2024);

doy2024 = 60; // Leap Year Day, 29 February (GMT) calculateSunriseSunset(doy2024);

doy2024 = 91; // First day of BST, 31 March (BST) calculateSunriseSunset(doy2024);

doy2024 = 160; // 8 June (BST) calculateSunriseSunset(doy2024);

doy2024 = 301; // 25 November (GMT) calculateSunriseSunset(doy2024);

doy2024 = 330; // First day back to GMT, 27 October (GMT) calculateSunriseSunset(doy2024);

doy2024 = 366 ; // New Years Eve, 31 December (GMT) calculateSunriseSunset(doy2024); } /////////////////////////////////////////////////////// void calculateSunriseSunset(int doy) { JC_Sunrise sun {myLat, myLon, JC_Sunrise::officialZenith};

tmElements_t tm; tm.Year = CalendarYrToTm(2024); tm.Month = 1; tm.Day = doy; tm.Hour = 12; tm.Minute = 0; tm.Second = 0; time_t utcNow = makeTime(tm);

TimeChangeRule *tcr; time_t locNow = UK.toLocal(utcNow, &tcr); // UK timezone adjustment time_t rise, set; sun.calculate(locNow, tcr->offset, rise, set);

int sunriseHour = hour(rise); int sunriseMinute = minute(rise); int sunsetHour = hour(set); int sunsetMinute = minute(set);

Serial.print(F("\nDay of Year: ")); Serial.println(doy); // ? doy2024 ? Serial.print(F("Sunrise: ")); printHHMM(sunriseHour, sunriseMinute); Serial.print(F(" Sunset: ")); printHHMM(sunsetHour, sunsetMinute); Serial.println(); } /////////////////////////////////////////////////////// // Print time in "hh:mm" format void printHHMM(int hour, int minute) { if (hour < 10) Serial.print('0'); Serial.print(hour); Serial.print(':'); if (minute < 10) Serial.print('0'); Serial.print(minute); Serial.print(' '); } ////////////////////////////////// void loop() { }

///////////////////////////////// /*/ Results with TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 2, 0};

Day of Year: 1, Start of year, 1 Jan, GMT ONLINE Sunrise: 08:05 Sunset: 16:03 SKETCH Sunrise: 08:04 Sunset: 16:03 GOOD

Day of Year: 43, Today, 12 Feb, GMT ONLINE Sunrise: 07:21 Sunset: 17:40 SKETCH Sunrise: 07:20 Sunset: 17:10 GOOD

Day of Year: 60, Leap Year day, 29 Feb, GMT ONLINE Sunrise: 06:47 Sunset: 17:40 SKETCH Sunrise: 06:46 Sunset: 17:40 GOOD

Day of Year: 91, First day of BST, 29 March, BST ONLINE Sunrise: 06:38 Sunset: 19:32 SKETCH Sunrise: 06:37 Sunset: 19:32 GOOD

Day of Year: 160, 8 June, BST ONLINE Sunrise: 04:45 Sunset: 21:16 SKETCH Sunrise: 04:46 Sunset: 21:13 GOOD

Day of Year: 301, GMT resumes, 27 October, GMT ONLINE Sunrise: 06:46 Sunset: 16:44 SKETCH Sunrise: 07:16 Sunset: 17:14 WRONG Both +30

Day of Year: 330, 25 November, GMT ONLINE Sunrise: 07:35 Sunset: 16:02 SKETCH 2 Sunrise: 06:15 Sunset: 18:04 WRONG -79 / +60 !

Day of Year: 366, End of year, 31 December, GMT ONLINE Sunrise: 08:05 Sunset: 16:02 SKETCH Sunrise: 05:55 Sunset: 20:04 WRONG +240!

Sketch uses 8432 bytes (26%) of program storage space. Maximum is 32256 bytes. Global variables use 275 bytes (13%) of dynamic memory, leaving 1773 bytes for local

*/ `

JChristensen commented 8 months ago

Greetings,

I do not usually debug other folks' code, but I did have a look after verifying that the library was working correctly for London.

The issue may be passing int doy to the calculateSunriseSunset() function and then assigning it to tm.Day.

tm.Day is the day of the month (1-31), and it is a single unsigned byte (uint8_t). So once doy exceeds the capacity of one byte (i.e. 255), things go off the track. I am a bit surprised it worked up until then.

Hope this helps.

Cheers ... Jack

void calculateSunriseSunset(int doy)
{
    JC_Sunrise sun {myLat, myLon, JC_Sunrise::officialZenith};

    tmElements_t tm;
    tm.Year = CalendarYrToTm(2024);
    tm.Month = 1;
    tm.Day = doy;   // oops, assigning int value to uint8_t causes truncation
terrypin999 commented 8 months ago

Thanks so much for your response to my debugging issue, appreciate the exception. Unsure how to acknowledge a closed issue, so using this.

Your example WorldClock.ino uses '2' as the fifth parameter for the time zone UK code. But AFAICT from some searches, our clocks resume GMT at "1 am" (as usual) on 27th October 2024. Or is '2' technically correct? Of trivial consequence for all but insomniacs anyway - just curious ;-)

JChristensen commented 8 months ago

Hi again,

I saw that and wondered too. A TimeChangeRule describes when the given change occurs, and the hour is in the local time that is currently in effect.

I would read the following as: "BST starts at 01:00 GMT on the last Sunday in March," and "GMT starts at 02:00 BST on the last Sunday in October."

TimeChangeRule BST = {"BST", Last, Sun, Mar, 1, 60};
TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 2, 0};

I believe this agrees with the tz database (see below) and also with timeanddate.com. If you think differently, please let me know, as I do want to be clear on this.

Good luck with your project. Always nice to hear from England. Here in Michigan USA we are enjoying a fairly mild winter although we may get some more snow later this week.

$ zdump -V -c 2024,2025 Europe/London
Europe/London  Sun Mar 31 00:59:59 2024 UT = Sun Mar 31 00:59:59 2024 GMT isdst=0 gmtoff=0
Europe/London  Sun Mar 31 01:00:00 2024 UT = Sun Mar 31 02:00:00 2024 BST isdst=1 gmtoff=3600
Europe/London  Sun Oct 27 00:59:59 2024 UT = Sun Oct 27 01:59:59 2024 BST isdst=1 gmtoff=3600
Europe/London  Sun Oct 27 01:00:00 2024 UT = Sun Oct 27 01:00:00 2024 GMT isdst=0 gmtoff=0
$