Sunrise/sunset times

Hi Mary,
Thanks, not sure about being a php whizz tho…
Glad the softpac issue was reproduced.
I am using 9.2a in an R2.

I think I might get my R2 a nice firmware upgrade for Christmas.

Did you try it with Temecula data to see if the times are correct?

Ah! You ran into this issue KB82023 which has a work-around – minor adjustment needed to your header (I added this [0] element):

 
stGetHeader[0] = "host:" + sHostname;
stGetHeader[1] = "Accept: text/html"; //set content type

I plugged in 33.4936 & 117.1475 (Temecula) but that comes back with:
<br><p>Sunrise- 10:04<br>Sunset- 20:05

Hmm. Maybe user error on my part?

Ah thanks Mary. I will apply the fix. Should have checked the kb’s before coding the old school way… Never mind

Did you specify a gmt offset as well? I think I hard coded it to 11. I’m not sure what Temeculas offset is. Also remember the lat is east referenced and long is north referenced (I see you know that but for any one else giving it a shot…). So if you are 147.89W it would mean -147.89.

Thanks again mary

Ah! That was it. I threw the minus sign in there and fixed my offset and got:

<br><p>Sunrise- 07:04<br>Sunset- 17:05

Weather.com reported this for yesterday:
Sunrise: 6:42 am
Sunset: 4:41 pm

Maybe they’re talking about the “crack” of dawn and yours is for the completion? :wink:

Very nice! Thanks again!

Ok great Mary. If you add a type to the get request (type=1, 2 or 3. Check the php script to see what type is what) you may get back corresponding times. As you say, they might have firrst light and last light as opposed to official sr/ss

Great glad it worked, kinda…

Interesting topic in a thread regarding ‘php sun functions’

I have looked further into calculating the values of sunrise and set using a Taylor Series
sin x = x - x3/3! + x5/5! - x7/7! + …,

and to the use of the simpler COrdinate Rotation DIgital Computer (CORDIC) method to see if it would give any advantages.

Both require some number crunching of sorts - the former multiplication and division, the latter only using addition, subtraction and bitshifts. This leads us to a question that has been asked before - that of the number CPU/Controller Cycles to carry out commands to guesstimate how long calculating a number would take and then to see which method would be quicker.

In our case, we normally have a computer close by and so I think for us the php script method is ideal as we already use php to talk to the controller. (Although running Python also looks interesting.)

Thanks for all of your input guys.

Hate to lose a challenge so I think I will be back!

Oh! This sounds like a good place for SoftPAC! I suspect that the addition/subtraction/bitshift difference would pale in comparison to which hardware you run it on. Some of the [URL=“http://www.opto22.com/lp/pc_based_controller.aspx”]SoftPAC tests we did were several orders of magnitude faster running the same code on a PC (of course, this varies widely depending on your PC)…

I totally agree with you Mary. But what I would say is that if you are running remotely you want something small light and reliable and so for me a PC is not such a good option as a PAC Controller. If you have a PC locally then yes, SoftPAC is ideal.

I remember a (few?) years ago when we were using assembler to code systems with 8080A processors we would pinch and scrape every single CPU sycle we could to improve execution times. You certainly learnt some neat unorthodox cheats/methods to get you want you wanted quickly!!

Can I just check that the 2 code samples here run with PAC Sim 9.3a? The reason I ask is that I am having problems getting them to run.

The PAC Sim ReadMe suggests that at R9.1b Http Get doesn’t work, but at 9.3a Http Get has had some bugs fixed, does it now work?

I’m still seeing that -443 error coming back from the HttpGet on both R9.3a SoftPAC and PAC Sim, unfortunately. I’ll spare you the gory details, and hope to post more/better news soon.

Just to be clear, though, Nick’s work-around of using the “old school” tcp comm handle works fine. And should work even on older firmware! (If you import his sample chart, you’ll see block 11 “get url and convert to numeric” connected which works fine, it’s his “http get” hanging out on the side that was getting the -443).
Thanks again, Nick!

Sorry, I meant the HttpGet. Spent a lot of time trying to get it to work yesterday using, among other things, the workaround and generally confusing myself!

I don’t know if I can’t see the wood for the trees but is there anywhere that explains some of the variables/terms and how they are used i.e. the Http Get commands like the Get Header/GET_SrcTblBody. (1700 and 1701 seem very scant in detail on some of the newer commands!)
nSendStatus = HttpGet(DstStrTblBody, DstStrTblHdr, GET_SrcStrTblBody, 0, StrCmd, nHttpStatus, nPort, StrHostname);

Hi All,

Here’s a little subroutine/example to grab a web page from a remote server and store it as a local file. A second subroutine parses the local file. (Similar to a previous weather example I posted, but a bit more versatile since I broke it into 2 parts, and used a tcp comm handle instead of HttpGet.)

This sample strategy grabs weather data, Nick’s sunrise/set, the Careers page of opto22.com, and the IP address of the device as seen from the web.

Also, it shows how you might parse a file by searching for strings in it.

Any/all feedback appreciated!

Thanks,
-OptoMary

p.s. I wrote this in PAC Control Basic 8.0 so it can be opened by anything since that.

Thanks Mary - nice complete example!

I know this thread is a few months old now but I finally got around to implementing it. I made a few customizations to Mary’s strategy to specifically suit my needs and it worked beautifully! Thanks to Nick Stephens for graciously hosting the sunrise/sunset data on his server!

Just came across this, and thought I would share some code I modified to run on a PAC many years ago that I’ve been using for astronomical clock use. The math doesn’t seem to be too much for the PAC. I don’t remember how accurate it is, but I use it for turning off and on lights and it works great for that and it’s more reliable than photo cells.

I have this running in a subroutine with the following parameters:

fLatitude - The Latitude where you want the sunrise/sunset time.
fLongitude
nDayOfYear - The number of days since 12/31 last year (So Jan 1 = 1 and Feb 1 = 32, etc.)
fUTCOffset - Adjust the result into the local time zone
nSunset - This is the output in seconds since midnight for sunset
nSunrise - This is the output in seconds since midnight for sunrise

The rest are all local subroutine variables.

The code:


//Calculate Sunset given the latitude, longitude and day of year
//Adapted from http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
//which came from the Almanac for Computers, 1990 USNO
//Define Pi and Degree and Radian conversion factors.
fPi = 3.14159265;
fDegToRad = .0174532925;
fRadToDeg = 57.2957795;
//Define Zenith (official sunset zenith)
fZenith = 90.83;




//Get the Longitude Hour
fLngHour = fLongitude / 15.0;


//Calculate an approximate sunset time for the longitude
fApproxTime = nDayOfYear + ((18.0 - fLngHour)/24.0);


//Sun Mean Anomaly
fSunMeanAnomaly = (.9856 * fApproxTime) - 3.289;


//Sun True Longitude
fSunTrueLongitude = fSunMeanAnomaly + (1.916 * Sine(fSunMeanAnomaly * fDegToRad)) + (.02 * Sine(2 * fSunMeanAnomaly * fDegToRad)) + 282.634;


//Make sure fSunTrueLongitude is between 0 and 360, adjust by 360.
if (fSunTrueLongitude>360.0) then
  fSunTrueLongitude = fSunTrueLongitude - 360.0;
elseif (fSunTrueLongitude < 0.0) then
  fSunTrueLongitude = fSunTrueLongitude + 360.0;
endif


//Sun Right Ascension (RA)
fSunRightAscension = Arctangent(0.91764 * Tangent(fSunTrueLongitude * fDegToRad)) * fRadToDeg + 360;
//Make sure fSunRightAscension is between 0 and 360, adjust by 360
if (fSunRightAscension>360.0) then
  fSunRightAscension = fSunRightAscension - 360.0;
elseif (fSunRightAscension < 0.0) then
  fSunRightAscension = fSunRightAscension + 360.0;
endif


//Put RA and L in the same quadrant
fSunTrueLongitudeQuadrant = Truncate(fSunTrueLongitude / 90.0) * 90.0;
fSunRAQuadrant = Truncate(fSunRightAscension / 90.0) * 90.0;


fSunRightAscension = fSunRightAscension + fSunTrueLongitudeQuadrant - fSunRAQuadrant;


//RA converted to Hours
fSunRAHours = fSunRightAscension / 15.0;


//Calc suns Declination
fSunSinDeclination = 0.39782 * Sine(fSunTrueLongitude * fDegToRad);
fSunCosDeclination = Cosine(Arcsine(fSunSinDeclination));




//Calc suns local hour angle
fSunLocalHourAngle = (Cosine(fZenith * fDegToRad) - (fSunSinDeclination * Sine(fLatitude * fDegToRad))) / (fSunCosDeclination * Cosine(fLatitude * fDegToRad));


if (fSunLocalHourAngle < -1.0) then //Check if the sun never sets on this date
  nSunset=-1; //No sunset
else
  fSunH = Arccosine(fSunLocalHourAngle) * fRadToDeg / 15.0;
  fLocalMeanTime = fSunH + fSunRAHours - (0.06571 * fApproxTime) - 6.622;
  fUTCTime = fLocalMeanTime - fLngHour;
  fSunsetTime = fUTCTime + fUTCOffset;
  //Adjust to be within 0 and 24
  if (fSunsetTime > 24.0) then
    fSunsetTime = fSunsetTime - 24.0;
  elseif (fSunsetTime < 0.0) then
    fSunsetTime = fSunsetTime + 24.0;
  endif
  nSunset = fSunsetTime * 3600;  //Put the result in seconds since midnight;
endif






/////////////Sunrise//////////////






//Calculate an approximate sunrise time for the longitude
fApproxTime = nDayOfYear + ((6.0 - fLngHour)/24.0);


//Sun Mean Anomaly
fSunMeanAnomaly = (.9856 * fApproxTime) - 3.289;


//Sun True Longitude
fSunTrueLongitude = fSunMeanAnomaly + (1.916 * Sine(fSunMeanAnomaly * fDegToRad)) + (.02 * Sine(2 * fSunMeanAnomaly * fDegToRad)) + 282.634;


//Make sure fSunTrueLongitude is between 0 and 360, adjust by 360.
if (fSunTrueLongitude>360.0) then
  fSunTrueLongitude = fSunTrueLongitude - 360.0;
elseif (fSunTrueLongitude < 0.0) then
  fSunTrueLongitude = fSunTrueLongitude + 360.0;
endif


//Sun Right Ascension (RA)
fSunRightAscension = Arctangent(0.91764 * Tangent(fSunTrueLongitude * fDegToRad)) * fRadToDeg + 360;
//Make sure fSunRightAscension is between 0 and 360, adjust by 360
if (fSunRightAscension>360.0) then
  fSunRightAscension = fSunRightAscension - 360.0;
elseif (fSunRightAscension < 0.0) then
  fSunRightAscension = fSunRightAscension + 360.0;
endif


//Put RA and L in the same quadrant
fSunTrueLongitudeQuadrant = Truncate(fSunTrueLongitude / 90.0) * 90.0;
fSunRAQuadrant = Truncate(fSunRightAscension / 90.0) * 90.0;


fSunRightAscension = fSunRightAscension + fSunTrueLongitudeQuadrant - fSunRAQuadrant;


//RA converted to Hours
fSunRAHours = fSunRightAscension / 15.0;


//Calc suns Declination
fSunSinDeclination = 0.39782 * Sine(fSunTrueLongitude * fDegToRad);
fSunCosDeclination = Cosine(Arcsine(fSunSinDeclination));




//Calc suns local hour angle
fSunLocalHourAngle = (Cosine(fZenith * fDegToRad) - (fSunSinDeclination * Sine(fLatitude * fDegToRad))) / (fSunCosDeclination * Cosine(fLatitude * fDegToRad));


if (fSunLocalHourAngle > 1.0) then //Check if the sun never rises on this date
  nSunrise=-1; //No sunrise
else
  fSunH = (360 - Arccosine(fSunLocalHourAngle) * fRadToDeg) / 15.0;
  fLocalMeanTime = fSunH + fSunRAHours - (0.06571 * fApproxTime) - 6.622;
  fUTCTime = fLocalMeanTime - fLngHour;
  fSunriseTime = fUTCTime + fUTCOffset;
  //Adjust to be within 0 and 24
  if (fSunriseTime > 24.0) then
    fSunriseTime = fSunriseTime - 24.0;
  elseif (fSunriseTime < 0.0) then
    fSunriseTime = fSunriseTime + 24.0;
  endif
  nSunrise = fSunriseTime * 3600;  //Put the result in seconds since midnight;
endif

1 Like

Attached the subroutine. It is in 9.0 Basic.

Ha! Proving once again that there is actually life outside of Internet. Instead of struggling with tcp comms handles and 443 errors, just use the good old United States Naval Observatory Basic program from 1990. Nice One Philip and thanks! :cool:

Yep, very nice Phillip… Just one question, how do you calculate the nDayOfYear?

Built-in function: GetJulianDay();