c日出日落时间
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c日出日落时间相关的知识,希望对你有一定的参考价值。
在我的C应用程序中,我想计算给定日期,纬度和经度的日出/日落时间。我一直在网上搜索,但我找不到工作样本。
我试图实现这个样本:http://souptonuts.sourceforge.net/code/sunrise.c.html
但是这个样本没有正常工作。
是否有一个简单的C源代码或方法,我可以在我的应用程序中轻松实现?
编辑: 我在这个link上实现了代码,但它给了我错误的日落/日出值。我也尝试了Saul的链接here,但它也给了我错误的结果。 我有41N,28E的位置。当我尝试这些代码时,两个样本都说日出值大约是10:13而日落是23:24。但正确的值是06:06,20:13。 我无法理解这个问题。
示例代码似乎在VC ++ 2010中有一些小的更改:
- 将其编译为C ++文件而不是C.
- 删除
#include <sys/time.h>
线。 - 在文件顶部添加
#define _USE_MATH_DEFINES
,以便定义M_PI。 - 将
%T
调用中的两个strftime()
更改为%X
。
既然您有一个工作样本,您可以调试工作版本和您的版本,以查看计算开始不同的地方并缩小问题范围。无论是单步执行程序还是自由使用临时printf()
调用就像样本一样。
如果您需要特定帮助,则必须发布您的代码(指向整个文件的链接或您需要帮助的特定代码段)。
这是适应性的,非常准确。您将获得所有组件,然后您需要计算的是Zenith到Horizon角度的反余弦。是的,有更简单的方法,但你不是基本上想跟踪太阳?它有朝一日会派上用场。 http://www.nrel.gov/midc/spa/
//a practical approximation for a microcontroller using lookup table
//seems to only use a small fraction of the resources required by the trigonometric functions
//ignores daylight saving: idea is for the device to approximate and trigger actual sunrise, sunset event as opposed to actual (politically correct local hhmm)
//using globals gps.Lat gps.LatDir(0:S 1:N) gps.Day (day of month) gps.Mth
//needs solar noon offset,latitude,dayOfMonth,Month
//LocalNoon-SolarNoon (may be off +/- up to ?? 2 hours) depending on local timezone and longitude (? typical discrepancy about 20min)
void SunriseSunsetCalculations(u8 SolarNoonOffsetInDeciHours,u8 SolarNoonOffsetDirection){
if(SolarNoonOffsetInDeciHours>20){SolarNoonOffsetInDeciHours=0;}//limit offest to 2 hours: discard offset on error
//--------references:
//https://www.orchidculture.com/COD/daylength.html
//http://aa.usno.navy.mil/data/docs/Dur_OneYear.php
//SolarTime is up two two hours off in either direction depending on timezone:
//http://blog.poormansmath.net/how-much-is-time-wrong-around-the-world/
//------------------
//lookUpTable Of daylength in decihours(6min)(fits well in u8) - 15day And 5 DegLat resolution
//SolarNoonOffsetDirection: 0: negative(b4 local noon), 1: +ve (solar noon after local noon)
u8 a[13][12]={//length of day in decihours
// Dec Nov Oct Sep Aug Jul
//Jan Feb Mar Apr May June
{120,120,120,120,120,120,120,120,120,120,120,120}, //lat 0____0
{126,125,124,123,122,121,119,118,116,115,115,114}, //lat 10____1
{129,128,127,125,123,121,119,117,115,113,112,111}, //lat 15____2
{132,131,129,127,124,121,118,115,113,110,109,108}, //lat 20____3
{135,134,131,128,125,122,118,114,111,108,106,105}, //lat 25____4
{139,137,134,130,127,122,117,113,108,105,102,101}, //lat 30____5
{143,141,137,133,128,123,117,111,106,102, 98, 97}, //lat 35____6
{148,145,141,135,130,123,116,109,103, 98, 94, 92}, //lat 40____7
{154,150,145,138,132,124,115,107,100, 93, 88, 86}, //lat 45____8
{161,157,150,142,134,124,114,105, 96, 88, 82, 79}, //lat 50____9
{170,165,156,146,137,125,113,102, 91, 81, 73, 69}, //lat 55___10
{183,176,165,152,140,126,112, 98, 84, 72, 61, 56}, //lat 60___11
{200,185,171,152,134,121,101, 84, 65, 53, 40, 33} //lat 65___12
};
u8 b[]={6,12,17,22,27,32,37,42,47,52,57,62,90}; // latitude limit cutoffs to get index of lookUpTable
u8 lat=gps.Lat/10000000; //lat stored in u32 to 7 decimals resolution (32bit unsigned integer)
u8 i=0; while(b[i]<lat){i++;} //get row index for daylength table
u8 k,ix; //k: 15 day offset; ix: column index for daylength table
k=gps.Day/15;if(k){k=1;}//which half of the month (avoid k=2 eg:31/15)
if(!gps.LatDir){ //0:southern latitudes
if(gps.Mth<7){
ix=(gps.Mth-1)*2+k; //2 fields per month (k to select)
}else{ //beyond june, use row in reverse
ix=11-(gps.Mth-7)*2-k; //2 fields per month (k to select)
}
}else{ //1:northern latitudes
if(gps.Mth<7){ //with first six month read rows in reverse
ix=11-(gps.Mth-1)*2-k; //2 fields per month (k to select)
}else{ //beyond june, use same row forward
ix=(gps.Mth-7)*2+k; //2 fields per month (k to select)
}
}
//debug only:...dcI("
i", i ,Blue,Red,1);dcI("ix", ix ,Blue,Red,1);dcI("a[i][ix]", a[i][ix] ,Blue,Red,1);
u8 h=a[i][ix]/2; //HalfTheDayLightLength in deciHours
u8 j[]={-1,1}; //multiplier: 0:(-) 1:(+)
u8 sn=120+SolarNoonOffsetInDeciHours*j[SolarNoonOffsetDirection]; //Solar noon
u8 srdh=sn-h; //sunrise in deciHours = solarNoon minus HalfTheDayLightLength
u8 ssdh=sn+h; //sunset in deciHours = solarNoon plus HalfTheDayLightLength
//debug only:...dcI("
SunRiseDeciHours", srdh ,Blue,Red,1);dcI("SunSetDeciHours", ssdh ,Blue,Red,1);
gps.HmSunRise=deciHourTohhmm(srdh);
gps.HmSunSet =deciHourTohhmm(ssdh);
}
u16 deciHourTohhmm(u8 dh){ //return unsigned integer from 0 to 2400
u16 h=(dh/10)*100; //hours: hh00
u8 r= dh%10; //fraction hour remainder to be converted to minutes
u8 m= 6*r; //60*r/10
return(h+m);
}
/*
Example Output: (!!! solarNoonOffset kept at 0(ignored) for the below example)
:_(08474300)___:_(A)___:_(381234567)___:_(S)___:_(1431234567)___:_(E)___
:_(GPS OK)___:_(Sat)___:_(12)___:_(Aug)___:_(2017)___hhmm:_(847)___
//...........
i:_(7)___ix:_(9)___a[i][ix]:_(98)___
SunRiseDeciHours:_(71)___SunSetDeciHours:_(169)___
HmSunRise:_(706)___
HmSunSet:_(1654)___
//............same as above but change LatDir to 1 (northern hemisphere)
i:_(7)___ix:_(2)___a[i][ix]:_(141)___
SunRiseDeciHours:_(50)___SunSetDeciHours:_(190)___
HmSunRise:_(500)___
HmSunSet:_(1900)___
..........ignore dcI(...) it's just a custom function printing through the serial port
*/
给出日期,纬度和经度,计算sunrise / sunset time的十个简单步骤
- 首先计算一年中的哪一天 N1 =楼层(275 *月/ 9)N2 =楼层((月+ 9)/ 12)N3 =(1 +楼层((年 - 4 *楼(年/ 4)+ 2)/ 3))N = N1 - (N2 * N3)+天 - 30
- 将经度转换为小时值并计算大致时间 lngHour =经度/ 15 如果需要上升时间:t = N +((6 - lngHour)/ 24)如果需要设定时间:t = N +((18 - lngHour)/ 24)
- 计算太阳的平均异常 M =(0.9856 * t) - 3.289
- 计算太阳的真实经度 L = M +(1.916 * sin(M))+(0.020 * sin(2 * M))+ 282.634注:L可能需要通过加/减360调整到[0,360]范围内
5A。计算太阳的正确提升
RA = atan(0.91764 * tan(L))
NOTE: RA potentially needs to be adjusted into the range [0,360) by adding/subtracting 360
5B。右提升值需要与L在同一象限
Lquadrant = (floor( L/90)) * 90
RAquadrant = (floor(RA/90)) * 90
RA = RA + (Lquadrant - RAquadrant)
5C。正确的提升值需要转换成小时
RA = RA / 15
- 计算太阳的赤纬 sinDec = 0.39782 * sin(L)cosDec = cos(asin(sinDec))
7A。计算太阳的当地小时角
cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude))
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)
7B。完成计算H并转换为小时
if if rising time is desired:
H = 360 - acos(cosH)
if setting time is desired:
H = acos(cosH)
H = H / 15
- 计算当地平均上升/设定时间 T = H + RA - (0.06571 * t) - 6.622
- 调整回UTC UT = T - lngHour注意:UT可能需要通过添加/减去24来调整到[0,24]范围内
- 将UT值转换为纬度/经度的本地时区 localT = UT + localOffset
这似乎很容易实现: http://edwilliams.org/sunrise_sunset_algorithm.htm
有一个c解决方案,其中包含日出/设置的目标c包装:https://gith 以上是关于c日出日落时间的主要内容,如果未能解决你的问题,请参考以下文章