Pages: [1] 2   Go Down
Author Topic: Automated Chicken Coop Door  (Read 3987 times)
0 Members and 1 Guest are viewing this topic.
South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I see most of my coding has been done before, saving me a lot of time!

In this article:
http://arduino.cc/forum/index.php/topic,8705.0.html

There are the lines:
Code:
sunrise = int(350 + (90*cos(((((month-1)*30.5)+dayOfMonth)+8)/58.1)));
  sunset = int(1075 + (90*sin(((((month-1)*30.5)+dayOfMonth)-83)/58.1)));
Where did this come from, and how do I know if it will work for my location (Hopkinsville, KY)
Logged

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 360
I'm 15. I like making things. I like breaking things better.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Any equation to find sunrise sunset is based on location. In order to rewrite it for your location, take a look at this: take a look at this: http://williams.best.vwh.net/sunrise_sunset_algorithm.htm . One question: why not use a light sensor to figure out sunrise/sunset instead of an expensive RTC and lots of math? IMHO, that makes a lot more sense.
Logged

Alice asked the Chesire Cat, who was sitting in a tree, "What road do I take?"
The cat asked, "Where do you want to go?"
"I don't know," Ali

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley    (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!!!
« Last Edit: October 27, 2012, 03:41:55 am by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Left Coast, CA (USA)
Online Online
Brattain Member
*****
Karma: 331
Posts: 16553
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
One question: why not use a light sensor to figure out sunrise/sunset instead of an expensive RTC and lots of math? IMHO, that makes a lot more sense.

Overcast days, fogged in mornings or evenings, full moon Vs new moon, stormy weather? I would think ambient light level would be a very unreliable indications of exact sunrise and sunset times?

Lefty

« Last Edit: July 13, 2011, 01:36:32 pm by retrolefty » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


BTW an automated chicken door could also be based upon a microphone checking the morning call of the rooster smiley-wink
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



* image.jpg (15.32 KB, 394x128 - viewed 90 times.)
Logged

South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IT'LL TAKE ME 2 WEEKS TO GET OVER THE ANSWER TO THIS QUESTION!
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


OK,

- exact numbers  for Hopkinsville, KY  based upon - http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html

Sunrise @23 jun = 4:32= 60 * 4 + 32= 272
Sunrise @23 dec = 7:00 = 60 * 7 + 00 = 420
delta = 420- 272 = 148 => divide by 2 makes 74
average = (420+272)/2 = 346

Sunset @23 jun = 19:13 = 60 * 19 + 23= 1163
Sunset @23 dec = 16:38 = 60 * 16 + 38= 998
delta = 1163 - 998 = 165 => divide by 2 makes 82
average = (1163 + 998)/2 = 1080

So the formulas for Hopkinsville, KY will be:   
Code:
void getRiseSet()
{
  float common = cos( ((month-1)*30.5+dayOfMonth + 8 ) / 58.091554) ; 
  sunrise = 346 + 74 * common;
  sunset =  1080 - 82 * common;   
}

I hope I saved you two weeks, but please spent an hour or so to understand the story, maybe I have bugged up somewhere and you should be able to fix it smiley-wink

@ SouthernAtHeart,  don't read below this line smiley-wink


What amazed me is that the sunset has a bigger spread (delta is 8 minutes larger) than the sunrise. can't explain this yet ...????


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the original code (what I posted in #1)
Code:
sunrise = int(350 + (90*cos(((((month-1)*30.5)+dayOfMonth)+8)/58.1)));
  sunset = int(1075 + (90*sin(((((month-1)*30.5)+dayOfMonth)-83)/58.1)));
it has 350 + ....
and 1075 + ....

but yours has

346 + ...
1080 - ....
should that be 1080 + ...
???
I haven't spent an hour on it, but 20 minutes or so.  I understand the jist of it, but doubt I could troubleshoot your formula. If you made a mistake, you're going to here from my chickens! (if they can get out of the pen)


 
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but yours has

346 + ...
1080 - ....
should that be 1080 + ...

The change of sign is introduced as I rewrote the sin(x) with a  -cos(x + 90) ;   (and yes I smuggled 1 day )


If I apply the above rewriteing on the original formula the sign will change.

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

To explain it otherwise, first note that the whole long part (90*....)  is the same now due to the rewrite

If it becomes summer that long part will go to -1
sunrise = 350 + 90 * -1  => sinrise is earlier
sunset = 1075 - 90 * -1  => sunset is later     
days are becoming longer.

If it becomes winter that long part will go to 1
sunrise = 350 + 90 * 1  => sunrise is later and later
sunset = 1075 - 90 * -1  => sunset is earlier and earlier
days are becoming shorter


The formula is in essence :   sunrise = average sunrise +  Func(dayOfTheYear);    // idem for sunset

more clear now?


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's VERY clear that you understand it!  I follow the jist of it, but it's a little gray yet.
 I'll move on now to something simpler like watching the little 1-wire temperature sensor, and turning an AC relay on if it gets too hot or too cold (for a fan, or a drinking water heater)
I'll be back when I run into trouble!
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


write a small sketch that uses the formula and let it generate a list of sunrises and sunsets. You see that it will be reasonable correct (+_ 5 minutes)

Quote
I'll be back when I run into trouble!
If you have problems with this one, PM me.  Add a link to this discussion.

Quote
I'll move on now to something simpler like watching the little 1-wire temperature sensor, and turning an AC relay on if it gets too hot or too cold
Also a fun project, familiar with - http://www.milesburton.com/Dallas_Temperature_Control_Library - ??
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

South East USA
Online Online
God Member
*****
Karma: 4
Posts: 636
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, robtillaart, I've gone thru this code a few more times, and have understood it enough to redo it for another GPS location!  It's not too complicated once you understand it,  and I DO much prefer to understand the code I use, rather than use it and not know how it does what it does...

My next question:
This one has me stumped.   I'm using an RTC to get my date info.  Each time I get the date, I want to check to see if it is:
1) after the second Sunday in March, &
2) before the first Sunday in November

I thought I use a boolean function that returns TRUE if it is DST, or FALSE if it's not DST

Code:
boolean CheckDST(){
/*
Starts: Second Sunday in March
Ends: First Sunday in November
*/
    if (month >= 3 && dayOfWeek <= 11) {    //It's a DST month
         ...not sure here...
       
   
    }

month, dayOfWeek, dayOfMonth, etc are all global variables that are updated to the current date
Logged

Dallas, Texas
Offline Offline
Sr. Member
****
Karma: 3
Posts: 267
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I see most of my coding has been done before, saving me a lot of time!

Having previously written a sunrise/sunset algorithm (+-1 minute, based on current GPS location) before, whereby it took an embarrassingly long time to write/debug, I tip my hat to you for a dramatically simplified approximation. Nicely done.

If anyone cares, my implementation was used to automatically brighten and dim the display of an android device while providing considerable power savings over that of the common auto adjust logic. If you have an android device and struggle with battery life, turning off auto brightness typically saves a fair amount.
Logged


New Jersey
Online Online
Faraday Member
**
Karma: 50
Posts: 3432
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just curious - why does it matter whether it's DST? I'd assumed that you're opening the coop at astronomical sunrise - are there other functions that are affected by what time people think it is?
Logged

Pages: [1] 2   Go Up
Jump to: