gan_canny
Junior Member
Offline
Posts: 89
Thank You
-Given: 101
-Receive: 26
|
|
« Reply #4 on: December 02, 2010, 11:30:53 23:30 » |
|
The goal if I understand is to determine the date and time using daylight duration. The calculation of sunrise and sunset for a specific latitude and longitude is basic mathematics below is some pascal code function sunsetrise(slat:string;slong:string):string; var
month,day,year,zenith,n1,n2,n3,n,lnghour,ts,tr,lat,lon,Mr,Ms,Lr,ls,RAs,RAr, Lquadrants,RAquadrants,Lquadrantr,RAquadrantr, sindecs,cosdecs,sindecr,cosdecr,cosHs,cosHr,Hs,Hr,MTs,MTr,UTs,UTr, localOffset,localTr,localTs,d_r,r_d,
d_m_y,temp_date,ds_start_date,ds_end_date:Tdatetime; wYear,wDay,WMonth: word; localTr_hr,localTs_hr,localTr_min,localTs_min:integer; ds_start_day, ds_end_day:integer; daylight_savings:boolean; sunrise,sunset:TdateTime; mystring:string; begin /////////////////////////////////////////////////////////////////////////// //////////////////date input ///////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// d_m_y:=Now; DecodeDate(d_m_y,wYear, wMonth, wDay); Year:=wYear; Day:=wDay; Month:=wMonth;
//// for 2007 daylight savings clocks forward 2am 2nd Sunday in march //// clocks fallback 2am 1st Sunday in november
/// find the dow of the 2nd Sun of March
temp_date:=EncodeDate(wYear,3,1); ds_start_day:=DayofWeek(temp_date); /// dow of Ist of March /// calc the first sunday /// if dow of first of month is 1(Sun) we are done /// 2(Mon) Ist sun is the 7th /// 3(Tue) 6
if ds_start_day>1 then ds_start_day:=9-ds_start_day; ds_start_day:=ds_start_day+7; /// 2nd sunday ds_start_date:=EncodeDate(wYear,3,ds_start_day); /// calc first Sunday temp_date:=EncodeDate(wYear,11,1); ds_end_day:=DayofWeek(temp_date); /// dow of Ist of March if ds_end_day>1 then ds_end_day:=9-ds_end_day; /// set daylight savings in effect flag ds_end_date:=EncodeDate(wYear,11,ds_end_day); if (d_m_y>=ds_start_date) and (d_m_y<ds_end_date) then daylight_savings:=true else daylight_savings:=false;
////////////////////////////////////////////////////////////////////// /////////////////////Lat lon input /////////////////////// lat:=strtofloat('26.90506' ); lon:=strtofloat('-82.07817' ); ///// Punta Gorda
lat:=strtofloat(slat ); lon:=strtofloat(slong ); ///// Punta Gorda
// lat:=40.9; // lon:=-74.3; // first calculate the day of the year
n1:=floor(275*month/9); n2:=floor((month+9)/12); n3:=1+floor((year-4*Int(year/4)+2)/3); n:=n1-(n2*n3)+day-30;
//convert the longitude to hour value and calculate an approximate time
d_r:=pi/180; /// deg to radians r_d:=180/pi; /// radians to degrees lngHour := lon / 15;
// if rising time is desired: tr := N + ((6 - lngHour) / 24); // if setting time is desired: ts := N + ((18 - lngHour) / 24); // calculate the Sun's mean anomaly
Mr := (0.9856 * tr) - 3.289; Ms := (0.9856 * ts) - 3.289; //calculate the Sun's true longitude
Lr := Mr + (1.916 * sin(Mr*d_r)) + (0.020 * sin(2 * Mr*d_r)) + 282.634 ; if Lr>360 then Lr:=Lr-360; if Lr<0 then Lr:=Lr+360; Ls := Ms + (1.916 * sin(Ms*d_r)) + (0.020 * sin(2 * Ms*d_r)) + 282.634 ; if Ls>360 then Ls:=Ls-360; if Ls<0 then Ls:=Ls+360;
// NOTE: L potentially needs to be adjusted into the range [0,360) // by adding/subtracting 360
// calculate the Sun's right ascension
RAs:= arctan(0.91764* tan(Ls*d_r))*r_d; RAr := arctan(0.91764* tan(Lr*d_r))*r_d; // NOTE: RA potentially needs to be adjusted into the range [0,360) by adding/subtracting
// right ascension value needs to be in the same quadrant as L
Lquadrants := (floor( Ls/90)) * 90 ; RAquadrants := (floor(RAs/90)) * 90 ;
RAs := RAs + (Lquadrants - RAquadrants);
Lquadrantr := (floor( Lr/90)) * 90 ; RAquadrantr := (floor(RAr/90)) * 90 ;
RAr := RAr + (Lquadrantr - RAquadrantr); // right ascension value needs to be converted into hours
RAs := RAs / 15; RAr := RAr / 15; // calculate the Sun's declination
sinDecr := 0.39782 * sin(Lr*d_r); cosDecr := cos(arcsin(sinDecr)); sinDecs := 0.39782 * sin(Ls*d_r); cosDecs := cos(arcsin(sinDecs));
// calculate the Sun's local hour angle zenith:=90.83; cosHs := (cos(zenith*d_r) - (sinDecs * sin(lat*d_r))) / (cosDecs * cos(lat*d_r)); cosHr := (cos(zenith*d_r) - (sinDecr * sin(lat*d_r))) / (cosDecr * cos(lat*d_r)); // if (cosH > 1) // the sun never rises on this location (on the specified date) // if (cosH < -1) // the sun never sets on this location (on the specified date)
// finish calculating H and convert into hours
// if rising time is desired: Hr:= 360 - arccos(cosHr)*r_d; // if setting time is desired: Hs := arccos(cosHs)*r_d;
Hr := Hr / 15 ; Hs := Hs / 15; // calculate local mean time of rising/setting
MTr := Hr + RAr - (0.06571 * tr) - 6.622 ; MTs := Hs + RAs - (0.06571 * ts) - 6.622 ; // adjust back to UTC
UTr := MTr - lngHour ; if UTr<0 then UTr:=UTr+24; if UTr>24 then UTr:=UTr-24;
UTs := MTs - lngHour ; if UTs<0 then UTs:=UTs+24; if UTs>24 then UTs:=UTs-24;
// NOTE: UT potentially needs to be adjusted into the range [0,24) // by adding/subtracting 24
//convert UT value to local time zone of latitude/longitude
if daylight_savings then localOffset:=-4 else localOffset:=-5; localTs := UTs + localOffset; if localTs <0 then localTs :=localTs +24; if localTs >24 then localTs :=localTs -24; localTs_hr:=Trunc(localTs); localTs_min:=Trunc((localTs-localTs_hr)*60 ); localTs_hr:=localTs_hr-12; localTr := UTr + localOffset; if localTr <0 then localTr :=localTr +24; if localTr >24 then localTr :=localTr -24; localTr_hr:=Trunc(localTr); localTr_min:=Trunc((localTr-localTr_hr)*60 ); if daylight_savings then mystring:='Daylight savings in effect GMT -4hr' else mystring:='Standard Time GMT -5hr'; sunrise:=EncodeTime( localTr_hr, localTr_min,0,0); sunset:=EncodeTime( localTs_hr, localTs_min,0,0);
mystring:=mystring+' Sunrise at '+ FormatDateTime('hh:nn "AM"',sunrise)+' '+ 'Sunset at '+FormatDateTime('hh:nn "PM"',sunset); result:=mystring; end; I implemented this in a PIC that controls timed switches. Now the PIC is not good for high precision floating point so the the sunrise and sunset times for a set location were stored in a table . The PIC kept the time via its xtal and a timer interrupt that was converted to hours mins and seconds. The pic timer would drift from true UT time and was corrected via photo detection of night time duration. Night time is better since clouds don't effect the timing. Oh by the way this won't work if there is no sunset or sunrise like in northern Alaska. The position of the sun using sensors has issues since the earth's orbit is elliptical and the velocity of the earth varies throughout the year this affects the transit of the sun across the sky. Our time is based on the mean sun not the transit position.
|