## Introduction: Calculating Sunset and Sunrise for a Microcontroller

Knowing the hours of sunset and sunrise may be handy in a variety of situations, an automated chicken coop door is only one example.

There are several ways to get the proper times: a lookup table in EEPROM, the Timelord library or one of its successors, the Dusk2Dawn library, a rather complicated calculation including the Julian calender, use the code for this startracker, pull it from Internet (if conected) or a fairly simple approximation that I will discuss here.

This method uses the average of the earliest and latest sunset and then for any given day adds or subtracts a certain amount of time with a maximum of half of the difference between the earliest and latest sunrise.

Rob Tillaert discusses the method here. It presumes that the sunrise time follows a (co)sinoidal function. I will try to visualize it with a simple example:

Say that on June 23 the earliest sunrise of the year occurs at 4am, and that the latest sunrise of the year occurs at 23 December at 6 am.

Then you know that on any other day the sunrise is between 4 and 6 am. If you take the average that is 5 am, then you know that every other sunrise that year is either 0-1 hr later than 5 am or 0-1 hr earlier than 5 am.

It is the latter that is captured in the formula:

t=avg+0.5Δ*cos((doy+8)/58.09)

- avg is average sunrise time, in minutes since midnight
- Δ the difference between the earliest and latest sunrise time
- doy is the day of the year
- the 8 is there because we start on the wintersolstice: 23 December is 8 days before jan 1
- 58.09 is 365/2π. That is necessary because the cosinusfunction has max 2π as input.

If you live in a DST zone, the earliest sunrise wil be under DST, however you need the non-DST corrected time: the sun knows no DST. Calculate first, then add DST later

For my location the earliest and latest sunrise are:

earliest sunrise is at 4.19 am

latest sunrise is at 8.51

in order to use them in our equation, we have to calculate them in minutes past midnight:

4.19= 4x60+19=259

8.51= 8*60+51=531

The average is (259+531)/2=395

the difference or delta is 531-259=272. We need half of that which is 137.

The equation then becomes:

395+137*cos((doy+8)/58.09)

To check the accuracy of the approximation, I plotted the actual sunrise times (blue curve) against the calculated sunrise time (red curve).

As it shows, the first half of the year is a perfect fit, the second half of the year seems to follow a more linear curve with the max deviation being 20 minutes, that may or may not be accurate enough for your project. With the aid of this curve though I could opt for a linear approximation for the 2nd half of the year.

For sunset we can practically use the same formula, be it that we now have to subtract the variable part rather than add it. For my location the sunset is as follows:

latest: 22:07 =1327 minutes (22*60+7)

earliest: 16:27= 987 minutes 16*60+27

avg=2287/2=1144 minutes

delta=240 ->170 minutes

sunset=1144-170*cos((doy+8)/58.09)

That gives the following graph:

This time I didnt bother to enter all the real sunset times, but it is clearly visible that there is a reasonable fit that could maybe be enhanced a bit by shifting it slightly more to left or decreasing the delta a bit. Again Red graph is the calculated sunset, the blue is the actual sunset. None of the graphs has been corrected for DST. In order to correct for DST you need to subtract an hour from the calculated sunrise and sunset during the time the DST is active

A procedure for the Arduino would look as follows:

Where DST is a byte indicating whether DST is active (1) or not active (0). The day of the year I pull from my RTC library but it can also be calculated as follows: int(((month-1)*30.5)+dayOfMonth)

The sunrise and sunset are both given in minutes after midnight. The hour and minutes of the sunrise (and mutatis mutandis sunset) can be calculated by:

hour=sunrise/60

minute=sunrise%60

## 6 Comments

6 years ago

Why use an approximation when an accurate calculation is available?

http://stjarnhimlen.se/comp/sunriset.c

This may be helpful in getting an approximate lat/lon for use with the above: curl -s "https://freegeoip.net/csv/`curl -s v4.ident.me`"|tr ',' '\n'|tail -3|head -2|tr '\n' ' '

Reply 6 years ago

Well, for one reason that it is shorter ;-)

Anyway, jokes aside, I didn' t know this piece of code but I do know the method it is following. It is given in a step by step explanation here. In fact it is also an approximation. It is fairly accurate, but the accuracy becomes smaller at higher latitudes.

But yes it is certainly a very good alternative as well and I am happy you pointed it out. I will run some tests against my cosinus approximation.

The startracker here on instructables

https://www.instructables.com/id/Two-Axis-Star-Trac...

follows the same principle I think.

Latitude and longitude can usually be gotten pretty accurately from google maps or from various websites such as this one:

https://www.gps-latitude-longitude.com/

6 years ago

This might come in handy for a project in near future! I thought about using the embedded functions in the time.h library for avr chips, do you know of any advantages/ disadvantages?

Reply 6 years ago

I never used those functions, but I presume this here method uses a bit less memory. In the end the time.h functions will just be calculation too, maybe a bit more extensive than this one. In my case I was not unhappy with the results. The max deviation (mainly in the second half of the year) was 18 min. I can work with that

Reply 6 years ago

Indeed, 18min should be more than good enough for my project. I'll experience a bit and report back if I got any interesting results. Thanks for the 'ible :)

Reply 6 years ago

ok looking forward to that. Good luck