Analysis: The assumption here is that the sunrise/set timetable is one sinus wave, the rest is scaling and translating a bit

sunrise = int (350 + ( 90*cos( ((((month-1)*30.5)+dayOfMonth)+8) /58.1) )); The part:

(month-1)*30.5 + dayOfMonth + 8 This is a formula for dayoftheyear with a small offset 8 days.

If you fill in the days and months of the year, you will get approx. 23 march = 90; 23 june = 180; 23 sept = 270 and 23 dec = 360 (=0) . These are the solstice and equinoxes.

Note the +8 is the offset between 1 jan and 23 dec (shortest day in NH = Northern Hemisphere)

so now we can bring back the formula to:

sunrise = 350 + 90*cos( dayofyear/58.1) ; As the cos() needs a value between 0..2PI the dayof year must be divided by a value so that 0 is mapped on 0 and 365 is mapped upon 2PI. simple math: 365/2PI = 58.0915542... which is rounded to 58.1. This is a very small error but one better uses 58.091554 (the approx limit of Arduino float) to keep error to a minimum

This brings the formula to:

sunrise = 350 + 90 * cos(); where cos() varies between from [-1, 1];

90 is the half of the difference between the sunrise on 23 dec and 23 june.

350 is the middle between the two sunrises, approx the sunrise @23 march/sept

OK, now take some time to reread the analysis above.

Back to the question :

* Where did this come from, and how do I know if it will work for my location (Hopkinsville, KY)*We now know where it comes from - see above - and we have the means to adapt the formulas.

OK, to change this formula to the lattitude of Hopkinsville, KY

step 1: Google EARTH => 36.51 north 87.29 E

step 2: http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html

-- update -- the numbers below are to be checked, this are just how its done

Sunrise @23 june = 4:32 = 60 * 4 + 32 = 272

Sunrise @23 dec = 7:21 = 60 * 7 + 21 = 441

delta = 441- 272 = 169 => divide by 2 makes 85

average = (441+272)/2 = 356

So the sunrise formula for Hopkinsville, KY will be:

sunrise = 356 + 85 * cos( ((month-1)*30.5+dayOfMonth+8) /58.1); // removed some unneeded ()

The sunset formula can be done in same way, left as an exercise for the reader.

Some programming/optimizing hints:

As sin() and cos() are quite equal I would change the formulas a bit so it only uses cos().

as : sin(x) = -cos(x+90);

one could convert the formulas to :

void getRiseSet()

{

int doy = (month-1)*30.5+dayOfMonth;

sunrise = 350 + 90*cos(( doy + 8 )/58.1);

sunset = 1075 - 90*cos(( doy + 8 )/58.1); // OK, I smuggled 1 day

(83+8 = 91 not 90 but as there are more rounding errors allready...

}

or max optimized to

void getRiseSet()

{

float common = 90 * cos( ((month-1)*30.5+dayOfMonth + 8 ) / 58.091554) ;

sunrise = 350 + common;

sunset = 1075 - common;

}

update 2012-10-27 :

void getRiseSet()

{

float common = 90 * cos( ((month-1)*30.5+dayOfMonth + 8 ) * 0.017214206) ; // replace division with faster multiplication

sunrise = 350 + common;

sunset = 1075 - common;

}

90 * 0.017214206 can be precalculated too but they have a different semantic meaning and the compiler might optimize it anyway.

Some interesting link I found during this exercise: - http://www.astro.uu.nl/~strous/AA/en/antwoorden/zonpositie.html -

and of course wikipedia - http://en.wikipedia.org/wiki/Sunrise_equation -

Note 1: beware that this formulas are approximations (quite good ones I think)

Note 2: these formulas don't take DST into account.

fun!!!