找回密码
 立即注册
查看: 764|回复: 2

32F通过经纬度坐标与日期计算当天日出日落时间

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2024-09-20 15:50:00

3

主题

4

回帖

87

积分

注册会员

积分
87
发表于 2024-9-10 16:57:26 | 显示全部楼层 |阅读模式
本帖最后由 DebugLab 于 2024-9-11 10:56 编辑




(1)先计算出从格林威治时间公元2000年1月1日到计算日天数days;

(2)计算从格林威治时间公元2000年1月1日到计算日的世纪数t, 则t=(days+UTo/360)/36525;(一个世纪的分数日)
(3)计算太阳的平黄径 : L=280.460+36000.770×t;
(4)计算太阳的平近点角 :G=357.528+35999.050×t
(5)计算太阳的黄道经度 :λ=L+1.915×sinG+0.020xsin(2G);
(6)计算地球的倾角     ε=23.4393-0.0130×t;
(7)计算太阳的偏差     δ=arcsin(sinε×sinλ);
(8)计算格林威治时间的太阳时间角GHA: GHA=UTo-180-1.915×sinG-0.020×sin(2G)   +2.466×sin(2λ)-0.053×sin(4λ)
(9)计算修正值e: e=arcos{[   sinh-sin(Glat)sin(δ)]/cos(Glat)cos(δ)}
(10)计算新的日出日落时间 :UT=UTo-(GHA+Long±e); 其中“+”表示计算日出时间,“-”表示计算日落时间;
(11)比较UTo和UT之差的绝对值,如果大于0.1°即0.007小时,把UT作为新的日出日落时间值,重新从第(2)步开始进行迭代计算,如果UTo和UT之差的绝对值小于0.007小时,则UT即为所求的格林威治日出日落时间;
(12)上面的计算以度为单位,即180°=12小时,因此需要转化为以小时表示的时间,再加上所在的时区数Zone,即要计算地的日出日落时间为 :T=UT/15+Zone
上面的计算日出日落时间方法适用于小于北纬60°和南纬60°之间的区域,如果计算位置为西半球时,经度Long为负数。
                         计算结果和查询网站的结果会有1~2分钟左右的误差   

不足之处是STC32_FPMU_LARGE库无法运算asin函数,所以无法使用STC32_FPMU_LARGE库运算

同时由于keil与单片机无法运行double双精度数据。只能运算float,所以输出数值略有误差。但是不影响时钟分钟数据。
适合用于路灯控制,与太阳能灯照明。降低非必要时间照明!

打印输出数据与网上查询的日出日落时间对比

输出数据.bmp 网上查询.bmp






STC32F12K54-日出日落计算.rar

78.37 KB, 下载次数: 50

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2024-9-10 17:47:57 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <math.h>
  3. #define PI 3.1415926
  4. //返回全局变量 sunrize sunset
  5. double sunrizetime,sunsettime;
  6. void CalSunRise(double year,double month,double day,double jingdu,double weidu)
  7. {
  8. double rssj;//日升时间
  9. double rlsj;//日落时间
  10. double ztsj;//中天时间
  11. double rszztsj;//日升至中天时间
  12. double ztzrlsj;//中天至日落时间
  13. double jsc;//均时差(小时)
  14. double shiqu;//时区8
  15. double JD1;//儒略日中间值
  16. double JD2;//儒略日
  17. double G4;//参考A
  18. double H4;//参考B
  19. double D8,D9,D10,D11,D12,D13,D14,D15,D16,D17,D18,D19,D20,D21,D22;
  20. double F10,F11,F12,F13,F14,F15,F16,F17,F18,F19,F20,F21,F22;
  21. double D25,D26,F26,H26;
  22. double K8,K9,K10,K11,K12,K13,K14,K15,K16,K17,K18,K19,K20,K21,K22;
  23. double M10,M11,M12,M13,M14,M15,M16,M17,M18,M19,M20,M21,M22;
  24. double rzsjdyb;//日照时间的一半
  25. double weiduhudu;//纬度弧度
  26. double xzlzxz;//修正量正弦值
  27. double R8,R9,R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R20,R21,R22;
  28. double T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22;
  29. //jingdu=DFM(116,23,29);//天安门
  30. //weidu=DFM(39,54,20);
  31. shiqu=8;
  32. day=day 0.5;
  33. if(year>0)
  34. {
  35. year=year;
  36. }
  37. else
  38. {
  39. year=year-1;
  40. }
  41. if(month>2)
  42. {
  43. year=year;
  44. month=month;
  45. }
  46. else
  47. {
  48. year=year-1;
  49. month=month 12;
  50. }
  51. weiduhudu=weidu/180*PI;
  52. G4=floor(year/100);
  53. H4=2-G4 floor(G4/4);
  54. JD1=floor(365.25*(year 4716)) floor(30.6001*(month 1)) day H4-1524.5;
  55. if(JD1>=2299160.5)
  56. {
  57. JD2=JD1;
  58. }
  59. else
  60. {
  61. JD2=JD1-H4;
  62. }
  63. D8=JD2-jingdu/360;
  64. D9=(D8-2451545)/36525;
  65. D10=84381.448-46.815*D9-0.00059*D9*D9 0.001813*D9*D9*D9;
  66. F10=D10/3600*PI/180;
  67. D11=280.46645 36000.76983*D9 0.0003032*D9*D9;
  68. F11=D11*PI/180;
  69. D12=357.5291 35999.0503*D9 - 0.0001559*D9*D9 -0.00000048*D9*D9*D9;
  70. F12=D12*PI/180;
  71. D13=0.016708617 - 0.000042037*D9 - 0.0000001236*D9*D9;
  72. F13=D13;
  73. D14=(1.9146 - 0.004817*D9 -0.000014*D9*D9)*sin(F12) (0.019993 - 0.000101*D9)*sin(2*F12) 0.00029*sin(3*F12);
  74. F14=D14*PI/180;
  75. D15=D11 D14;
  76. F15=D15*PI/180;
  77. D16=D12 D14;
  78. F16=D16*PI/180;
  79. D17= 1.000001018*(1-F13*F13) / (1 F13*cos(F16));
  80. F17=D17;
  81. D18= 125.04 - 1934.136*D9;
  82. F18=D18*PI/180;
  83. D19=D15 - 0.00569 -0.00478*sin(D18);
  84. F19=D19*PI/180;
  85. F20=asin(sin(F10)*sin(F15));
  86. D20=F20*180/PI;
  87. D21=D10/3600 0.00256*cos(F18);
  88. F21=D21/180*PI;
  89. F22=asin(sin(F21)*sin(F19));
  90. D22=F21/PI*180;
  91. D25=(tan(F10/2))*(tan(F10/2));//sin/cos
  92. D26=D25*sin(2*F11)-2*F13*sin(F12) 4*F13*D25*sin(F12)*cos(2*F11)-(D25*D25/2)*sin(4*F11)-(5/4*F13*F13)*sin(2*F12);
  93. F26=D26*180/PI;
  94. H26=F26*4;
  95. //================
  96. //xzlzxz=sin((16/F17 34)*-1/60*PI/180);//34大气折射修正 单位:分
  97. xzlzxz=sin((16/F17 34)*-1/60*PI/180);
  98. rzsjdyb=acos((xzlzxz-sin(F22)*sin(weiduhudu))/(cos(F22)*cos(weiduhudu)))/PI*12;
  99. K8=D8-rzsjdyb/24;
  100. K9=(K8-2451545)/36525;
  101. K10=84381.448-46.815*K9-0.00059*K9*K9 0.001813*K9*K9*K9;
  102. M10=K10/3600*PI/180;
  103. K11=280.46645 36000.76983*K9 0.0003032*K9*K9;
  104. M11=K11*PI/180;
  105. K12=357.5291 35999.0503*K9 - 0.0001559*K9*K9 -0.00000048*K9*K9*K9;
  106. M12=K12*PI/180;
  107. K13=0.016708617 - 0.000042037*K9 - 0.0000001236*K9*K9;
  108. M13=K13;
  109. K14=(1.9146 - 0.004817*K9 -0.000014*K9*K9)*sin(M12) (0.019993 - 0.000101*K9)*sin(2*M12) 0.00029*sin(3*M12);
  110. M14=K14*PI/180;
  111. K15=K11 K14;
  112. M15=K15*PI/180;
  113. K16=K12 K14;
  114. M16=K16*PI/180;
  115. K17= 1.000001018*(1-M13*M13) / (1 M13*cos(M16));
  116. M17=K17;
  117. K18= 125.04 - 1934.136*K9;
  118. M18=K18*PI/180;
  119. K19=K15 - 0.00569 -0.00478*sin(K18);
  120. M19=K19*PI/180;
  121. M20==asin(sin(M10)*sin(M15));
  122. K20=M20*180/PI;
  123. K21=K10/3600 0.00256*cos(M18);
  124. M21=K21/180*PI;
  125. M22=asin(sin(M21)*sin(M19));
  126. K22=M22/PI*180;
  127. //============================================
  128. R8=D8 rzsjdyb/24;
  129. R9=(R8-2451545)/36525;
  130. R10=84381.448-46.815*R9-0.00059*R9*R9 0.001813*R9*R9*R9;
  131. T10=R10/3600*PI/180;
  132. R11=280.46645 36000.76983*R9 0.0003032*R9*R9;
  133. T11=R11*PI/180;
  134. R12=357.5291 35999.0503*R9 - 0.0001559*R9*R9 -0.00000048*R9*R9*R9;
  135. T12=R12*PI/180;
  136. R13=0.016708617 - 0.000042037*R9 - 0.0000001236*R9*R9;
  137. T13=R13;
  138. R14=(1.9146 - 0.004817*R9 -0.000014*R9*R9)*sin(T12) (0.019993 - 0.000101*R9)*sin(2*T12) 0.00029*sin(3*T12);
  139. T14=R14*PI/180;
  140. R15=R11 R14;
  141. T15=R15*PI/180;
  142. R16=R12 R14;
  143. T16=R16*PI/180;
  144. R17= 1.000001018*(1-T13*T13) / (1 T13*cos(T16));
  145. T17=R17;
  146. R18= 125.04 - 1934.136*R9;
  147. T18=R18*PI/180;
  148. R19=R15 - 0.00569 -0.00478*sin(R18);
  149. T19=R19*PI/180;
  150. T20=asin(sin(T10)*sin(T15));
  151. R20=T20/PI*180;
  152. R21=R10/3600 0.00256*cos(T18);
  153. T21=R21/180*PI;
  154. T22=asin(sin(T21)*sin(T19));
  155. R22=T22/180*PI;
  156. rszztsj=acos((xzlzxz-sin(M22)*sin(weiduhudu))/(cos(M22)*cos(weiduhudu)))/PI*12;
  157. ztzrlsj=acos((xzlzxz-sin(T22)*sin(weiduhudu))/(cos(T22)*cos(weiduhudu)))/PI*12;
  158. //? jsc;//均时差(小时)
  159. jsc=H26/60;
  160. //? ztsj;//中天时间
  161. ztsj=12-jsc-(jingdu-shiqu*15)*4/60;
  162. rssj=ztsj-rszztsj;//日升时间=中天时间-日升至中天时间
  163. rlsj=ztsj ztzrlsj;//日落时间=中天时间 中天至日落时间
  164. sunrizetime=rssj;
  165. sunsettime=rlsj;
  166. }
  167. void printtime(double t)
  168. {
  169. printf("%d:%d:%d\n",(int)(floor(t)),(int)floor((t-floor(t))*60),(int)floor((t*60-floor(t*60))*60));
  170. }
  171. double DFM(double d,double f,double m)
  172. {
  173. return d f/60 m/3600;
  174. }
  175. void main()
  176. {
  177. CalSunRise(2013,11,11,DFM(116,23,29),DFM(39,54,20));
  178. printtime(sunrizetime);
  179. printtime(sunsettime);
  180. }
复制代码
  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <math.h>
  4. #define RADEG     ( 180.0 / M_PI )
  5. #define sind(x)  sin((x)*DEGRAD)
  6. #define cosd(x)  cos((x)*DEGRAD)
  7. #define tand(x)  tan((x)*DEGRAD)
  8. #define DEGRAD    ( M_PI / 180.0 )
  9. #define atand( x )    (RADEG*atan(x))
  10. #define asind(x)    (RADEG*asin(x))
  11. #define acosd(x)    (RADEG*acos(x))
  12. #define atan2d(y,x) (RADEG*atan2(y,x))
  13. #define days_since_2000_Jan_0(y,m,d) \
  14.     (367*(y)-((7*((y)+(((m)+9)/12)))/4)+((275*(m))/9)+(d)-730530)
  15. void sunriset( int year, int month, int day, double lon,
  16.                double lat, double *rise, double *set );
  17. //year, month, date = calendar date, 1801-2099 only.
  18. //Eastern longitude positive, Western longitude negative
  19. //Northern latitude positive, Southern latitude negative
  20. //The longitude value is critical in this function!
  21. //*rise = where to store the rise time
  22. //*set  = where to store the set  time
  23. void sunpos( double d, double *lon, double *r );
  24. //Computes the Sun's ecliptic longitude and distance at an instant given in d
  25. //number of days since 2000 Jan 1
  26. //The Sun's ecliptic latitude is not computed, it's always very near 0.
  27. void sun_RA_dec( double d, double *RA, double *dec, double *r );
  28. //Compute Sun's ecliptic longitude add slant
  29. double revolution( double x );
  30. //Reduce angle to within 0..360 degrees
  31. double rev180( double x );
  32. //Reduce angle to within -180..+180 degrees
  33. double GMST0( double d );
  34. //This function computes the Greenwich Mean Sidereal Time at 0h UT
  35. //GMST is then the sidereal time at Greenwich at any time of the day
  36. //GMST = (GMST0) + UT * (366.2422/365.2422)
  37. int main()
  38. {
  39.     //get system time
  40.     time_t t;
  41.     t = time( NULL );
  42.     struct tm *local = localtime( &t );
  43.     int year = local->tm_year + 1900;
  44.     int month = local->tm_mon+1;
  45.     int day = local->tm_mday;
  46.     int hour = local->tm_hour;
  47.     int minute;
  48.     //get coordinate
  49.     double lon, lat;
  50.     printf("Eastern longitude positive, Western longitude negative\n");
  51.     printf("Northern latitude positive, Southern latitude negative\n");
  52.     printf("such as:114.31667 30.51667\n");
  53.     printf("please input longitude and latitude:\n");
  54.     //this coordinate is Wuhan
  55.     scanf("%lf %lf", &lon, &lat);
  56.     double sunrise, sunset;
  57.     sunriset( year, month, day, lon, lat,
  58.               &sunrise, &sunset );
  59.     //calculate time zone
  60.     struct tm *gmt = gmtime( &t );
  61.     int zone = hour - gmt->tm_hour + (day - gmt->tm_mday)*24;
  62.     //calcute sunrise and sunset time
  63.     hour = sunrise+zone;
  64.     minute = (sunrise - hour+zone)*60;
  65.     if( hour > 24 ) hour -= 24;
  66.     else if( hour < 0 ) hour += 24;
  67.     printf("sunrise:%2d:%2d\n", hour, minute);
  68.     hour = sunset+zone;
  69.     minute = (sunset - hour+zone)*60;
  70.     if( hour > 24 ) hour -= 24;
  71.     else if( hour < 0 ) hour += 24;
  72.     printf("sunset: %2d:%2d\n", hour, minute);
  73.     return 0;
  74. }
  75. void sunriset( int year, int month, int day, double lon, double lat, double *rise, double *set )
  76. {
  77.     double sr;           //sun's distance
  78.     double sRA;          //sun's ecliptic longitude
  79.     double sdec;         //slant of the sun
  80.     double t;            //offset
  81.     double d = days_since_2000_Jan_0( year, month, day ) + 0.5 - lon / 360.0;
  82.     //Compute d of 12h local mean solar time, from 2000 Jan 1 to now
  83.     double sidtime = revolution( GMST0(d) + 180.0 + lon );
  84.     //Compute local sidereal time of this moment
  85.     double altit = -35.0/60.0;
  86.     //Compute Sun's RA + Decl at this moment
  87.     sun_RA_dec( d, &sRA, &sdec, &sr );
  88.     //Compute time when Sun is at south - in hours UT
  89.     double tsouth = 12.0 - rev180(sidtime - sRA)/15.0;
  90.     //Compute the Sun's apparent radius, degrees
  91.     double sradius = 0.2666 / sr;
  92.     //Do correction to upper limb, if necessary
  93.     altit -= sradius;
  94.     //Compute the diurnal arc that the Sun traverses to reach
  95.     //the specified altitude altit:
  96.     double cost = ( sind(altit) - sind(lat) * sind(sdec) ) /
  97.            ( cosd(lat) * cosd(sdec) );
  98.     if ( cost >= 1.0 )
  99.         t = 0.0;       //Sun always below altit
  100.     else if ( cost <= -1.0 )
  101.         t = 12.0;      //Sun always above altit
  102.     else
  103.         t = acosd(cost)/15.0;   //The diurnal arc, hours
  104.     //Store rise and set times - in hours UT
  105.     *rise = tsouth - t;
  106.     *set  = tsouth + t;
  107. }
  108. void sunpos( double d, double *lon, double *r )
  109. {
  110.     //Compute mean elements
  111.     double M = revolution( 356.0470 + 0.9856002585 * d ); //anomaly
  112.     double w = 282.9404 + 4.70935E-5 * d;                 //sun's ecliptic longitude
  113.     double e = 0.016709 - 1.151E-9 * d;                   //earth's offset
  114.     //Compute true longitude and radius vector
  115.     double E = M + e * RADEG * sind(M) * ( 1.0 + e * cosd(M) ); //eccentric anomaly
  116.     double x = cosd(E) - e;
  117.     double y = sqrt( 1.0 - e*e ) * sind(E); //orbit coordinate
  118.     *r = sqrt( x*x + y*y );                 //Solar distance
  119.     double v = atan2d( y, x );              //True anomaly
  120.     *lon = v + w;                           //True solar longitude
  121.     if ( *lon >= 360.0 )
  122.         *lon -= 360.0;                      //Make it 0..360 degrees
  123. }
  124. void sun_RA_dec( double d, double *RA, double *dec, double *r )
  125. {
  126.     double lon;
  127.     //Compute Sun's ecliptical coordinates
  128.     sunpos( d, &lon, r );
  129.     //Compute ecliptic rectangular coordinates (z=0)
  130.     double x = *r * cosd(lon);
  131.     double y = *r * sind(lon);
  132.     /* Compute obliquity of ecliptic (inclination of Earth's axis) */
  133.     double obl_ecl = 23.4393 - 3.563E-7 * d;
  134.     /* Convert to equatorial rectangular coordinates - x is unchanged */
  135.     double z = y * sind(obl_ecl);
  136.     y = y * cosd(obl_ecl);
  137.     /* Convert to spherical coordinates */
  138.     *RA = atan2d( y, x );
  139.     *dec = atan2d( z, sqrt(x*x + y*y) );
  140. }
  141. double revolution( double x )
  142. {
  143.     return( x - 360.0 * floor( x / 360 ) );
  144. }
  145. double rev180( double x )
  146. {
  147.     return( x - 360.0 * floor( x / 360 + 0.5 ) );
  148. }
  149. double GMST0( double d )
  150. {
  151.     //Sidtime at 0h UT = L (Sun's mean longitude) + 180.0 deg
  152.     //L = M + w, as defined in sunpos().
  153.     //Any decent C compiler will add the constants at compile time
  154.     double sidtim0 = revolution( ( 180.0 + 356.0470 + 282.9404 ) +
  155.                           ( 0.9856002585 + 4.70935E-5 ) * d );
  156.     return sidtim0;
  157. }
复制代码


DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:467
  • 最近打卡:2025-06-15 22:44:24
已绑定手机

19

主题

3231

回帖

5281

积分

论坛元老

积分
5281
发表于 2024-9-10 18:50:49 | 显示全部楼层
用FPU计算的吗
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-16 18:20 , Processed in 0.135849 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表