SunRise-SunSet & Noon time calculation - Library

General discussion on mikroBasic.
Post Reply
Author
Message
Bytex
Posts: 459
Joined: 23 Jun 2008 00:58
Location: Palmanova (UD), Italy
Contact:

SunRise-SunSet & Noon time calculation - Library

#1 Post by Bytex » 29 Sep 2008 22:09

Hi folks,
here is my last library for Solar calculations.
I use it for turn on/off my home garden lamps.

Enjoy,
Max

Code: Select all

'+-----------------------------------------------------------------------------+
'+ SunCalc_Library
'+
'+ Bytex (Italy)
'+ September 2008
'+
'+ Hardware configuration:
'+ Any PIC 18 family with 32KB ROM
'+ OSC: 8 ~ 20MHz
'+
'+ Features:
'+
'+ SunRise time calculation
'+ Noon time calculation
'+ SunSet time calculation
'+ Day of year calculation
'+ Day of week calculation
'+ Is Leap Year calculation
'+ Daylight Saving Time period, starting date, ending date calculation
'+
'+ web references from:
'+ http://www.srrb.noaa.gov/highlights/sunrise/sunrise.html
'+
'+-----------------------------------------------------------------------------+
module SunCalc_Library

'===============================================================================
' SC_ (SunCalc) GLOBAL INPUT VARIABLES
'===============================================================================

'+-------------------------------------+
'+ input parameters for local latitude +
'+ SC_in_LatDeg --> North +; South -;  +
'+-------------------------------------+
Dim SC_in_LatDeg        as Integer
Dim SC_in_LatMin        As Integer
Dim SC_in_LatSec        As Integer
Dim SC_in_LatSec100     As Integer
Dim SC_in_Latitude      as float

'+--------------------------------------+
'+ input parameters for local longitude +
'+ SC_in_LonDeg --> West +; East -;     +
'+--------------------------------------+
Dim SC_in_LonDeg        As Integer
Dim SC_in_LonMin        As Integer
Dim SC_in_LonSec        As Integer
Dim SC_in_LonSec100     As Integer
Dim SC_in_Longitude     as float

'+------------------------------------------------+
'+ input parameter for Greenwich Mean Time offset +
'+ SC_in_GMToffset --> West -; East +;            +
'+------------------------------------------------+
Dim SC_in_GMToffset     as integer

'+---------------------------------+
'+ input parameters for today date +
'+---------------------------------+
Dim SC_in_ThisDay       As Integer
Dim SC_in_ThisMonth     As Integer
Dim SC_in_ThisYear      As Integer

'+--------------------------------------------------+
'+ input parameters for Daylight Saving Time period +
'+ For Europe starting period --> march             +
'+ For Europe ending period ----> october           +
'+--------------------------------------------------+
Dim SC_in_dst_SMonth    as integer
Dim SC_in_dst_EMonth    as integer

'===============================================================================
' SC_ (SunCalc) GLOBAL OUTPUT VARIABLES
'===============================================================================

'+---------------------------------+
'+ Output values for SunRise event +
'+---------------------------------+
Dim SC_out_RiseTime_Hours       as byte
Dim SC_out_RiseTime_Minutes     as byte

'+--------------------------------+
'+ Output values for SunSet event +
'+--------------------------------+
Dim SC_out_SetTime_Hours        as byte
Dim SC_out_SetTime_Minutes      as byte

'+-----------------------------------+
'+ Output values for Noon time event +
'+-----------------------------------+
Dim SC_out_NoonTime_Hours       as byte
Dim SC_out_NoonTime_Minutes     as byte

'+---------------------------------------------+
'+ String output for SunRise, NoonTime, SunSet +
'+ showing hh:mm                               +
'+---------------------------------------------+
Dim SC_out_StrBuffer            as string[5]

'+----------------------------------------+
'+ Output value for numerical day of year +
'+ indicating 1..365                      +
'+----------------------------------------+
Dim SC_out_DayOfYear            as integer

'+-------------------------------------+
'+ String output value for day of week +
'+ 1=monday...7=sunday                 +
'+-------------------------------------+
Dim SC_out_StrDayOfWeek         as string[3]

'+------------------------------+
'+ Output value for day of week +
'+ 1=monday...7=sunday          +
'+------------------------------+
Dim SC_out_IntDayOfWeek         as integer

'+-----------------------------------+
'+ Output value for leap year result +
'+ yes=true; no=false                +
'+-----------------------------------+
Dim SC_out_IsLeapYear           as byte

'+-----------------------------------------------------+
'+ Output value for Daylight Saving Time period result +
'+ yes=true; no=false                                  +
'+-----------------------------------------------------+
Dim SC_out_DaylightSavingTime   as byte

'+----------------------------------------+
'+ Output values for Daylight Saving Time +
'+ starting date                          +
'+----------------------------------------+
Dim SC_out_DST_StartDay         as integer
Dim SC_out_DST_StartMonth       as integer
Dim SC_out_DST_StartYear        as integer

'+----------------------------------------+
'+ Output values for Daylight Saving Time +
'+ ending date                            +
'+----------------------------------------+
Dim SC_out_DST_EndDay           as integer
Dim SC_out_DST_EndMonth         as integer
Dim SC_out_DST_EndYear          as integer




implements

'//****************************************************************************/
'//* Name:    GetLocalLatitude                                                */
'//* Type:    Function                                                        */
'//* Purpose:                                                                 */
'//* Arguments:                                                               */
'//*                                                                          */
'//****************************************************************************/
Sub Function GetLocalLatitude(Dim SC_in_LatDeg As Integer,
                              Dim SC_in_LatMin As Integer,
                              Dim SC_in_LatSec As Integer,
                              Dim SC_in_LatSec100 As Integer) As float

    Dim w   As float
    Dim p   As float

    p = float(SC_in_LatSec) + float(SC_in_LatSec100) / 100.0

    If SC_in_LatDeg > 0 Then
        w = float(SC_in_LatDeg) / 1.0
        w = w + float(SC_in_LatMin) / 60.0
        w = w + p / 3600.0
    Else
        w = float(SC_in_LatDeg) / 1.0
        w = w - float(SC_in_LatMin) / 60.0
        w = w - p / 3600.0
    End If

    If w < -89.0 Then
        w = -89.0
    End If
    If w > 89.0 Then
        w = 89.0
    End If

    Result = w

End sub



'//****************************************************************************/
'//* Name:    GetSC_in_Longitude                                              */
'//* Type:    Function                                                        */
'//* Purpose:                                                                 */
'//* Arguments:                                                               */
'//*                                                                          */
'//****************************************************************************/
Sub Function GetLocalLongitude(Dim SC_in_LonDeg As Integer,
                               Dim SC_in_LonMin As Integer,
                               Dim SC_in_LonSec As Integer,
                               Dim SC_in_LonSec100 As Integer) as Float

    Dim w   as Float
    Dim p   as Float

    p = float(SC_in_LonSec) + float(SC_in_LonSec100) / 100.0

    If SC_in_LonDeg > 0 Then
        w = float(SC_in_LonDeg) / 1.0
        w = w + float(SC_in_LonMin) / 60.0
        w = w + p / 3600.0
    Else
        w = float(SC_in_LonDeg) / 1.0
        w = w - float(SC_in_LonMin) / 60.0
        w = w - p / 3600.0
    End If

    Result = w

End Sub



'//****************************************************************************/
'//* Name:    isLeapYear                                                      */
'//* Type:    Function                                                        */
'//* Purpose:                                                                 */
'//* Arguments:                                                               */
'//*                                                                          */
'//****************************************************************************/
Sub Function isLeapYear(Dim yr As Integer) As byte

        If ((yr Mod 4 = 0) And (yr Mod 100 <> 0)) Or (yr Mod 400 = 0) Then
           Result = True
        Else
           Result = False
        End If

End Sub

'=====================================================================
' Convert radian angle to degrees
'=====================================================================
Sub Function RadToDeg(Dim RadAngle as Float) as Float

    Result = (180.0 * RadAngle / 3.14159265358979)

End Sub

'=====================================================================
' Convert degree angle to radians
'=====================================================================
Sub Function DegToRad(Dim DegAngle as Float) as Float

    Result = (DegAngle * 3.14159265358979 / 180.0)

End Sub

'//****************************************************************************/
'//* Name:    calcDayOfYear                                                   */
'//* Type:    Function                                                        */
'//* Purpose: Finds numerical day-of-year from mn, day and lp year info       */
'//* Arguments:                                                               */
'//*   month: January = 1                                                     */
'//*   day  : 1 - 31                                                          */
'//*   lpyr : 1 if leap year, 0 if not                                        */
'//* Return value:                                                            */
'//*   The numerical day of year                                              */
'//****************************************************************************/
Sub Function calcDayOfYear(Dim mMonth As Integer,
                               Dim mday As Integer,
                               Dim lpyr As byte) As integer


    Dim k           As Integer

    If lpyr = True Then
        k = 1
    Else
        k = 2
    End If

    Result = integer(floor((275.0 * float(mMonth)) / 9.0) -
             float(k) * floor((float(mMonth) + 9.0) /
             12.0) + float(mday) - 30.0)

End Sub


'//***********************************************************************/
'//* Name:    calcDayOfWeek                                              */
'//* Type:    Function                                                   */
'//* Purpose: Derives weekday from Julian Day                            */
'//* Arguments:                                                          */
'//*   juld : Julian Day                                                 */
'//* Return value:                                                       */
'//*   String containing name of weekday                                 */
'//***********************************************************************/
Sub Procedure calcDayOfWeek(Dim JulD as Float,
                            Dim ByRef StrDayOfWeek as string[3],
                            Dim Byref IntDayOfWeek as integer)

    Dim a1,a2   as float
    Dim ba      as float
    Dim bc      as integer

    StrDayOfWeek = "   "
    IntDayOfWeek = 0


    a1 = JulD + 1.5
    a2 = a1 / 7.0
    ba = a1 - floor(a2) * 7.0
    bc = integer(ba)

    Select Case bc
        Case 0
            StrDayOfWeek = "Sun"
        Case 1
            StrDayOfWeek = "Mon"
        Case 2
            StrDayOfWeek = "Tue"
        Case 3
            StrDayOfWeek = "Wed"
        Case 4
            StrDayOfWeek = "Thu"
        Case 5
            StrDayOfWeek = "Fri"
        Case 6
            StrDayOfWeek = "Sat"
    End Select

    if bc > 0 then
        IntDayOfWeek = bc
    else
        IntDayOfWeek = 7
    end if

End Sub



'//*** [1] ***************************************************************/
'//* Name:    calcJD                                                     */
'//* Type:    Function                                                   */
'//* Purpose: Julian day from calendar day                               */
'//* Arguments:                                                          */
'//*   year : 4 digit year                                               */
'//*   month: January = 1                                                */
'//*   day  : 1 - 31                                                     */
'//* Return value:                                                       */
'//*   The Julian day corresponding to the date                          */
'//* Note:                                                               */
'//*   Number is returned for start of day.  Fractional days should be   */
'//*   added later.                                                      */
'//***********************************************************************/
Sub Function CalcJD(dim aYear As Integer,
                        dim aMonth As Integer,
                        dim aDay As Integer) As float

'+ Web references ---------------------------+
'+                                           +
'+ http://en.wikipedia.org/wiki/Julian_day   +
'+                                           +
'+-------------------------------------------+

    Dim cMonth      As integer
    Dim cYear       As integer
    Dim cDay        As integer
    Dim A           As integer
    Dim B           As integer

    If aMonth <= 2 Then
        cYear = aYear - 1
        cMonth = aMonth + 12
    Else
        cYear = aYear
        cMonth = aMonth
    End If

    cDay = aDay

    A = floor(cYear / 100.0)
    B = 2.0 - A + floor(A / 4.0)

    Result = floor(365.25 * (cYear + 4716)) +
             floor(30.6001 * (cMonth + 1)) +
             cDay + B - 1524.5

End Sub




'//*** [2] **************************************************************/
'//* Name:    calcTimeJulianCent                                        */
'//* Type:    Function                                                  */
'//* Purpose: convert Julian Day to centuries since J2000.0.            */
'//* Arguments:                                                         */
'//*   jd : the Julian Day to convert                                   */
'//* Return value:                                                      */
'//*   the value corresponding to the Julian Day                        */
'//**********************************************************************/
Sub Function CalcTimeJulianCent(Dim JD as Float) as Float

    Result = (JD - 2451545.0) / 36525.0

End Sub


'//**********************************************************************/
'//* Name:    calcJDFromJulianCent                                      */
'//* Type:    Function                                                  */
'//* Purpose: convert centuries since J2000.0 to Julian Day.            */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   the Julian Day corresponding to the t value                      */
'//**********************************************************************/
Sub Function CalcJDFromJulianCent(Dim t as Float) as Float

    Result = t * 36525.0 + 2451545.0

End Sub



'//**********************************************************************/
'//* Name:    calGeomMeanLongSun                                        */
'//* Type:    Function                                                  */
'//* Purpose: calculate the Geometric Mean SC_in_Longitude of the Sun   */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   the Geometric Mean SC_in_Longitude of the Sun in degrees         */
'//**********************************************************************/
Sub Function CalcGeomMeanLongSun(Dim t as Float) as Float

    Dim L0    as Float

    L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t)

    While (L0 > 360.0)
        L0 = L0 - 360.0
    Wend

    While (L0 < 0.0)
        L0 = L0 + 360.0
    Wend

    Result = L0

End Sub


'//**********************************************************************/
'//* Name:    calGeomAnomalySun                                         */
'//* Type:    Function                                                  */
'//* Purpose: calculate the Geometric Mean Anomaly of the Sun           */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   the Geometric Mean Anomaly of the Sun in degrees                 */
'//**********************************************************************/
Sub Function CalcGeomMeanAnomalySun(Dim t as Float) as Float

    Result = 357.52911 + t * (35999.05029 - 0.0001537 * t)

End Sub


'//**********************************************************************/
'//* Name:    calcEccentricityEarthOrbit                                */
'//* Type:    Function                                                  */
'//* Purpose: calculate the eccentricity of earth's orbit               */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   the unitless eccentricity                                        */
'//**********************************************************************/
Sub Function CalcEccentricityEarthOrbit(Dim t as Float) as Float

    Result = 0.016708634 - t * (0.000042037 + 0.0000001267 * t)

End Sub

'//**********************************************************************/
'//* Name:    calcMeanObliquityOfEcliptic                               */
'//* Type:    Function                                                  */
'//* Purpose: calculate the mean obliquity of the ecliptic              */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   mean obliquity in degrees                                        */
'//**********************************************************************/
Sub Function CalcMeanObliquityOfEcliptic(Dim t as Float) as Float

    Dim seconds     as Float

    seconds = 21.448 - t * (46.815 + t * (0.00059 - t * (0.001813)))
    Result = 23.0 + (26.0 + (seconds / 60.0)) / 60.0

End Sub



'//**********************************************************************/
'//* Name:    calcObliquityCorrection                                   */
'//* Type:    Function                                                  */
'//* Purpose: calculate the corrected obliquity of the ecliptic         */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   corrected obliquity in degrees                                   */
'//**********************************************************************/
Sub Function CalcObliquityCorrection(Dim t as Float) as Float

    Dim omega       as Float

    omega = 125.04 - 1934.136 * t
    Result = CalcMeanObliquityOfEcliptic(t) + 0.00256 * Cos(DegToRad(omega))

End Sub



'//**********************************************************************/
'//* Name:    calcEquationOfTime                                        */
'//* Type:    Function                                                  */
'//* Purpose: calculate the difference between true solar time and mean */
'//*     solar time                                                     */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   equation of time in minutes of time                              */
'//**********************************************************************/
Sub Function CalcEquationOfTime(Dim t as Float) as Float

    Dim Epsilon     as Float
    Dim L0          as Float
    Dim e           as Float
    Dim m           as Float
    Dim y           as Float
    Dim Sin2l0      as Float
    Dim Sinm        as Float
    Dim Cos2l0      as Float
    Dim Sin4l0      as Float
    Dim Etime       as Float

    Epsilon = CalcObliquityCorrection(t)
    L0 = CalcGeomMeanLongSun(t)
    e = CalcEccentricityEarthOrbit(t)
    m = CalcGeomMeanAnomalySun(t)
    y = Tan(DegToRad(Epsilon) / 2.0)
    y = y * y
    Sin2l0 = Sin(2.0 * DegToRad(L0))
    Sinm = Sin(DegToRad(m))
    Cos2l0 = Cos(2.0 * DegToRad(L0))
    Sin4l0 = Sin(4.0 * DegToRad(L0))

    Etime = y * Sin2l0 - 2.0 * e * Sinm +
                4.0 * e * y * Sinm *
                Cos2l0 - 0.5 * y * y *
                Sin4l0 - 1.25 * e * e *
                Sin(2.0 * DegToRad(m))

    Result = RadToDeg(Etime) * 4.0

End Sub


'//**********************************************************************/
'//* Name:    calcSolNoonUTC                                            */
'//* Type:    Function                                                  */
'//* Purpose: calculate the Universal Coordinated Time (UTC) of solar   */
'//*        noon for the given day at the given location on earth       */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//*   SC_in_Longitude : SC_in_Longitude of observer in degrees         */
'//* Return value:                                                      */
'//*   time in minutes from zero Z                                      */
'//**********************************************************************/
Sub Function CalcSolNoonUTC(Dim t as Float,
                                Dim SC_in_Longitude as Float) as Float

    Dim tnoon       as Float
    Dim eqTime      as Float
    Dim solNoonUTC  as Float
    Dim NewT        as Float

    tnoon = CalcTimeJulianCent(CalcJDFromJulianCent(t) + SC_in_Longitude / 360.0)
    eqTime = CalcEquationOfTime(tnoon)
    solNoonUTC = 720.0 + (SC_in_Longitude * 4.0) - eqTime    '// min

    NewT = CalcTimeJulianCent(CalcJDFromJulianCent(t) -
                 0.5 + solNoonUTC / 1440.0)

    eqTime = CalcEquationOfTime(NewT)

    solNoonUTC = 720.0 + (SC_in_Longitude * 4.0) - eqTime ' // min

    Result = solNoonUTC

End Sub


'//**********************************************************************/
'//* Name:    calcSunEqOfCenter                                         */
'//* Type:    Function                                                  */
'//* Purpose: calculate the equation of center for the sun              */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   in degrees                                                       */
'//**********************************************************************/
Sub Function CalcSunEqOfCenter(Dim t as Float) as Float

    Dim mRad    as Float
    Dim Sin1m   as Float
    Dim Sin2m   as Float
    Dim Sin3m   as Float
    Dim C       as Float

    mRad = DegToRad(CalcGeomMeanAnomalySun(t))
    Sin1m = Sin(mRad)
    Sin2m = Sin(mRad + mRad)
    Sin3m = Sin(mRad + mRad + mRad)

    C = Sin1m * (1.914602 - t * (0.004817 + 0.000014 * t)) +
        Sin2m * (0.019993 - 0.000101 * t) + Sin3m * 0.000289

    Result = C  ' in degrees

End Sub


'//**********************************************************************/
'//* Name:    calcSunTrueLong                                           */
'//* Type:    Function                                                  */
'//* Purpose: calculate the true SC_in_Longitude of the sun             */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun's true SC_in_Longitude in degrees                            */
'//**********************************************************************/
Sub Function CalcSunTrueLong(Dim t as Float) as Float

    Result = CalcGeomMeanLongSun(t) + CalcSunEqOfCenter(t)

End Sub


'//**********************************************************************/
'//* Name:    calcSunTrueAnomaly                                        */
'//* Type:    Function                                                  */
'//* Purpose: calculate the true anamoly of the sun                     */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun's true anamoly in degrees                                    */
'//**********************************************************************/
Sub Function CalcSunTrueAnomaly(Dim t as Float) as Float

    Result = CalcGeomMeanAnomalySun(t) + CalcSunEqOfCenter(t)

End Sub


'//**********************************************************************/
'//* Name:    calcSunRadVector                                          */
'//* Type:    Function                                                  */
'//* Purpose: calculate the distance to the sun in AU                   */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun radius vector in AUs                                         */
'//**********************************************************************/
Sub Function CalcSunRadVector(Dim t as Float) as Float

    Dim v       as Float
    Dim ee      as Float

    v = CalcSunTrueAnomaly(t)
    ee = CalcEccentricityEarthOrbit(t)

    Result = (1.000001018 * (1.0 - ee * ee)) / (1.0 + ee * Cos(DegToRad(v)))

End Sub


'//**********************************************************************/
'//* Name:    calcSunApparentLong                                       */
'//* Type:    Function                                                  */
'//* Purpose: calculate the apparent SC_in_Longitude of the sun         */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun's apparent SC_in_Longitude in degrees                        */
'//**********************************************************************/
Sub Function CalcSunApparentLong(Dim t as Float) as Float

    Result = CalcSunTrueLong(t) - 0.00569 -
             0.00478 * Sin(DegToRad(125.04 - 1934.136 * t))

End Sub





'//**********************************************************************/
'//* Name:    calcSunRtAscension                                        */
'//* Type:    Function                                                  */
'//* Purpose: calculate the right ascension of the sun                  */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun's right ascension in degrees                                 */
'//**********************************************************************/
Sub Function CalcSunRtAscension(Dim t as Float) as Float

    Dim e           as Float
    Dim lambda      as Float
    Dim tananum     as Float
    Dim tanadenom   as Float

    e = CalcObliquityCorrection(t)
    lambda = CalcSunApparentLong(t)
    tananum = (Cos(DegToRad(e)) * Sin(DegToRad(lambda)))
    tanadenom = (Cos(DegToRad(lambda)))
    Result = RadToDeg(Atan2(tananum, tanadenom))

End Sub


'//**********************************************************************/
'//* Name:    calcSunDeclination                                        */
'//* Type:    Function                                                  */
'//* Purpose: calculate the declination of the sun                      */
'//* Arguments:                                                         */
'//*   t : number of Julian centuries since J2000.0                     */
'//* Return value:                                                      */
'//*   sun's declination in degrees                                     */
'//**********************************************************************/
Sub Function CalcSunDeclination(Dim t as Float) as Float

    Dim e           as Float
    Dim lambda      as Float
    Dim sint        as Float

    e = CalcObliquityCorrection(t)
    lambda = CalcSunApparentLong(t)
    sint = Sin(DegToRad(e)) * Sin(DegToRad(lambda))
    Result = RadToDeg(Asin(sint))

End Sub





'//**********************************************************************/
'//* Name:    calcHourAngleSunrise                                      */
'//* Type:    Function                                                  */
'//* Purpose: calculate the hour angle of the sun at sunrise for the    */
'//*            SC_in_Latitude                                          */
'//* Arguments:                                                         */
'//*   lat : SC_in_Latitude of observer in degrees                      */
'//*    solarDec : declination angle of sun in degrees                  */
'//* Return value:                                                      */
'//*   hour angle of sunrise in radians                                 */
'//**********************************************************************/
Sub Function CalcHourAngleSunrise(Dim lat as Float,
                                      Dim SolarDec as Float) as Float

    Dim latrad      as Float
    Dim sdrad       as Float
    Dim HAarg       as Float

    latrad = DegToRad(lat)
    sdrad = DegToRad(SolarDec)
    HAarg = (Cos(DegToRad(90.833)) / (Cos(latrad) * Cos(sdrad)) -
             Tan(latrad) * Tan(sdrad))
    Result = (Acos(Cos(DegToRad(90.833)) / (Cos(latrad) * Cos(sdrad)) -
             Tan(latrad) * Tan(sdrad)))


End Sub



'//**********************************************************************/
'//* Name:    calcHourAngleSunset                                       */
'//* Type:    Function                                                  */
'//* Purpose: calculate the hour angle of the sun at sunset for the     */
'//*            SC_in_Latitude                                          */
'//* Arguments:                                                         */
'//*   lat : SC_in_Latitude of observer in degrees                      */
'//*    solarDec : declination angle of sun in degrees                  */
'//* Return value:                                                      */
'//*   hour angle of sunset in radians                                  */
'//**********************************************************************/
Sub Function CalcHourAngleSunset(Dim lat as Float,
                                     Dim SolarDec as Float) as Float

    Dim latrad      as Float
    Dim sdrad       as Float
    Dim HAarg       as Float
    Dim HA          as Float

    latrad = DegToRad(lat)
    sdrad = DegToRad(SolarDec)

    HAarg = (Cos(DegToRad(90.833)) / (Cos(latrad) * Cos(sdrad)) -
            Tan(latrad) * Tan(sdrad))

    HA = (Acos(Cos(DegToRad(90.833)) / (Cos(latrad) * Cos(sdrad)) -
            Tan(latrad) * Tan(sdrad)))

    Result = -HA

End Sub





'//*** [3] ********************************************************************/
'//* Name:    calcSunriseUTC                                                  */
'//* Type:    Function                                                        */
'//* Purpose: calculate the Universal Coordinated Time (UTC) of sunrise       */
'//*            for the given day at the given location on earth              */
'//* Arguments:                                                               */
'//*   JD  : julian day                                                       */
'//*   SC_in_Latitude : SC_in_Latitude of observer in degrees                 */
'//*   SC_in_Longitude : SC_in_Longitude of observer in degrees               */
'//* Return value:                                                            */
'//*   time in minutes from zero Z                                            */
'//****************************************************************************/
Sub Function CalcSunRiseUTC(Dim JD as Float,
                                Dim SC_in_Latitude as Float,
                                Dim SC_in_Longitude as Float) as float


    Dim t           as Float
    Dim noonmin     as Float
    Dim tnoon       as Float
    Dim eqTime      as Float
    Dim SolarDec    as Float
    Dim HourAngle   as Float
    Dim Delta       as Float
    Dim TimeDiff    as Float
    Dim TimeUTC     as Float
    Dim NewT        as Float


    t = CalcTimeJulianCent(JD)
    noonmin = CalcSolNoonUTC(t, SC_in_Longitude)
    tnoon = CalcTimeJulianCent(JD + noonmin / 1440.0)

    eqTime = CalcEquationOfTime(tnoon)
    SolarDec = CalcSunDeclination(tnoon)
    HourAngle = CalcHourAngleSunrise(SC_in_Latitude, SolarDec)

    Delta = SC_in_Longitude - RadToDeg(HourAngle)
    TimeDiff = 4.0 * Delta   '// in minutes of time
    TimeUTC = 720.0 + TimeDiff - eqTime  '// in minutes

    NewT = CalcTimeJulianCent(CalcJDFromJulianCent(t) + TimeUTC / 1440.0)
    eqTime = CalcEquationOfTime(NewT)
    SolarDec = CalcSunDeclination(NewT)
    HourAngle = CalcHourAngleSunrise(SC_in_Latitude, SolarDec)
    Delta = SC_in_Longitude - RadToDeg(HourAngle)
    TimeDiff = 4.0 * Delta
    TimeUTC = 720.0 + TimeDiff - eqTime  '// in minutes

    Result = TimeUTC

End Sub




'//**********************************************************************/
'//* Name:    calcSunsetUTC                                             */
'//* Type:    Function                                                  */
'//* Purpose: calculate the Universal Coordinated Time (UTC) of sunset  */
'//*            for the given day at the given location on earth        */
'//* Arguments:                                                         */
'//*   JD  : julian day                                                 */
'//*   SC_in_Latitude : SC_in_Latitude of observer in degrees           */
'//*   SC_in_Longitude : SC_in_Longitude of observer in degrees         */
'//* Return value:                                                      */
'//*   time in minutes from zero Z                                      */
'//**********************************************************************/
Sub Function CalcSunSetUTC(Dim JD as Float,
                               Dim SC_in_Latitude as Float,
                               Dim SC_in_Longitude as Float) as Float


    Dim t               as Float
    Dim noonmin         as Float
    Dim tnoon           as Float
    Dim eqTime          as Float
    Dim SolarDec        as Float
    Dim HourAngle       as Float
    Dim Delta           as Float
    Dim TimeDiff        as Float
    Dim TimeUTC         as Float
    Dim NewT            as Float

    t = CalcTimeJulianCent(JD)
    noonmin = CalcSolNoonUTC(t, SC_in_Longitude)
    tnoon = CalcTimeJulianCent(JD + noonmin / 1440.0)

    eqTime = CalcEquationOfTime(tnoon)
    SolarDec = CalcSunDeclination(tnoon)
    HourAngle = CalcHourAngleSunset(SC_in_Latitude, SolarDec)

    Delta = SC_in_Longitude - RadToDeg(HourAngle)
    TimeDiff = 4.0 * Delta
    TimeUTC = 720.0 + TimeDiff - eqTime

    NewT = CalcTimeJulianCent(CalcJDFromJulianCent(t) + TimeUTC / 1440.0)
    eqTime = CalcEquationOfTime(NewT)
    SolarDec = CalcSunDeclination(NewT)
    HourAngle = CalcHourAngleSunset(SC_in_Latitude, SolarDec)

    Delta = SC_in_Longitude - RadToDeg(HourAngle)
    TimeDiff = 4.0 * Delta
    TimeUTC = 720.0 + TimeDiff - eqTime  '// in minutes

    Result = TimeUTC

End Sub




Sub Procedure TimeToString(Dim fTime as Float,
                              Dim GMT As Integer,
                              Dim Byref Buffer as string[5],
                              Dim ByRef ThoursOut as byte,
                              Dim Byref TminutesOut as byte)


    Dim fHour       As float
    Dim fMin        As float
    Dim fSec        As float
    dim sHour       as string[17]
    dim sMin        as string[17]
    dim n           as byte
    dim k           as byte

    Buffer = "     "

    fSec = floor((fTime - floor(fTime)) * 60.0)
    fSec = fSec + floor(fTime) * 60.0
    fHour = floor(fSec / 3600.0)
    fMin = floor((fSec / 3600.0 - fHour) * 60.0)
    fSec = fSec - fHour * 3600.0 - fMin * 60.0

    If fSec >= 30.0 Then
        fMin = fMin + 1.0
    End If

    if SC_out_DaylightSavingTime then
        fHour = fHour + float(GMT) + 1.0
    else
        fHour = fHour + float(GMT)
    end if

    floatToStr(fHour,sHour)
    floatToStr(fMin,sMin)

    k = 0
    for n = 0 to 17
        if sHour[n] = "." then
           k = n
        end if
    next n
    if k = 1 then
       Buffer[0] = "0"
       Buffer[1] = sHour[0]
    end if
    if k = 2 then
       Buffer[0] = sHour[0]
       Buffer[1] = sHour[1]
    end if

    Buffer[2] = ":"

    k = 0
    for n = 0 to 17
        if sMin[n] = "." then
           k = n
        end if
    next n
    if k = 1 then
       Buffer[3] = "0"
       Buffer[4] = sMin[0]
    end if
    if k = 2 then
       Buffer[3] = sMin[0]
       Buffer[4] = sMin[1]
    end if

    ThoursOut = fHour
    TminutesOut = fMin

End Sub


'//**********************************************************************/
'//* Name:    GetLocalSunRiseTime                                       */
'//* Type:    Procedure                                                 */
'//* Purpose: calculate the local Sun Rise time                         */
'//*                                                                    */
'//* Arguments:                                                         */
'//*   JD  : julian day                                                 */
'//*   SC_in_Latitude : SC_in_Latitude of observer in degrees           */
'//*   SC_in_Longitude : SC_in_Longitude of observer in degrees         */
'//* Return value:                                                      */
'//*   time in minutes from zero Z                                      */
'//**********************************************************************/
Sub Procedure GetLocalSunRiseTime(Dim SC_in_Latitude as Float,
                                      Dim SC_in_Longitude as Float,
                                      Dim mYear As Integer,
                                      Dim mMonth As Integer,
                                      Dim mDay As Integer,
                                      Dim SC_in_GMToffset as integer,
                                      Dim ByRef StrOut as string[5],
                                      Dim ByRef ThoursOut as byte,
                                      Dim Byref TminutesOut as byte)



    Dim JD              as Float
    Dim t               as Float
    Dim RiseTimeGMT     as Float

    JD = CalcJD(mYear, mMonth, mDay)
    t = CalcTimeJulianCent(JD)

    ' Apparent SunRise GMT time
    RiseTimeGMT = CalcSunRiseUTC(JD, SC_in_Latitude, SC_in_Longitude)
    TimeToString (RiseTimeGMT, SC_in_GMToffset , StrOut, ThoursOut, TminutesOut)

End Sub


Sub Procedure GetLocalSunSetTime(Dim SC_in_Latitude as Float,
                                      Dim SC_in_Longitude as Float,
                                      Dim mYear As Integer,
                                      Dim mMonth As Integer,
                                      Dim mDay As Integer,
                                      Dim SC_in_GMToffset as integer,
                                      Dim ByRef StrOut as string[5],
                                      Dim ByRef ThoursOut as byte,
                                      Dim Byref TminutesOut as byte)




    Dim JD              as Float
    Dim t               as Float
    Dim SetTimeGMT      as Float

    JD = CalcJD(mYear, mMonth, mDay)
    t = CalcTimeJulianCent(JD)

    ' Apparent SunSet GMT time
    SetTimeGMT = CalcSunSetUTC(JD, SC_in_Latitude, SC_in_Longitude)
    TimeToString (SetTimeGMT, SC_in_GMToffset , StrOut, ThoursOut, TminutesOut)

End Sub


Sub Procedure GetLocalNoonTime(Dim SC_in_Longitude as Float,
                                      Dim mYear As Integer,
                                      Dim mMonth As Integer,
                                      Dim mDay As Integer,
                                      Dim SC_in_GMToffset as integer,
                                      Dim ByRef StrOut as string[5],
                                      Dim ByRef ThoursOut as byte,
                                      Dim Byref TminutesOut as byte)




    Dim JD              as Float
    Dim t               as Float
    Dim SolNoonGMT      as Float

    JD = CalcJD(mYear, mMonth, mDay)
    t = CalcTimeJulianCent(JD)

    ' Calculate solar noon for this date
    SolNoonGMT = CalcSolNoonUTC(t, SC_in_Longitude)
    TimeToString (SolNoonGMT, SC_in_GMToffset , StrOut, ThoursOut, TminutesOut)

End Sub

Sub Procedure GetMoreCalendarData(Dim mYear As Integer,
                                    Dim mMonth As Integer,
                                    Dim mDay As Integer,
                                    Dim Byref mIsLeapYear as byte,
                                    Dim Byref DayOfYear as integer,
                                    Dim Byref StrDayOfWeek as string[3],
                                    Dim Byref IntDayOfWeek as integer,
                                    Dim Byref SC_out_DaylightSavingTime as byte)

    Dim Jd          as float
    Dim i           as integer
    Dim LastSunday  as integer
    Dim sTemp       as string[3]
    Dim iTemp       as integer



    '+----------------------------------------------+
    '+ Leap year calculation                        +
    '+----------------------------------------------+
    mIsLeapYear = isLeapYear(mYear)

    '+----------------------------------------------+
    '+ Numerical day of year calculation            +
    '+----------------------------------------------+
    DayOfYear = calcDayOfYear(mMonth,mDay,mIsLeapYear)

    '+----------------------------------------------+
    '+ Numerical and string day of week calculation +
    '+----------------------------------------------+
    jd = CalcJD(mYear,mMonth,mDay)
    calcDayOfWeek(jd,StrDayOfWeek,IntDayOfWeek)

    '+----------------------------------------------+
    '+ Daylight Saving Time (DST) calculation       +
    '+----------------------------------------------+

    ' remember to put the right ending day
    ' for the for-next loop.
    '------------------------------------------
    for i = 1 to 31 ' march ending day
        iTemp = 0
        jd = 0
        jd = CalcJD(mYear,SC_in_dst_SMonth,i)
        calcDayOfWeek(jd,sTemp,iTemp)
        if iTemp = 7 then   ' Looking for Sunday day
            LastSunday = i
        end if
    next i
    SC_out_DST_StartDay = LastSunday
    SC_out_DST_StartMonth = SC_in_dst_SMonth
    SC_out_DST_StartYear = mYear

    ' remember to put the right ending day
    ' for the for-next loop.
    '------------------------------------------
    for i = 1 to 31 ' october ending day
        iTemp = 0
        jd = 0
        jd = CalcJD(mYear,SC_in_dst_EMonth,i)
        calcDayOfWeek(jd,sTemp,iTemp)
        if iTemp = 7 then   ' Looking for Sunday day
            LastSunday = i
        end if
    next i
    SC_out_DST_EndDay = LastSunday
    SC_out_DST_EndMonth = SC_in_dst_EMonth
    SC_out_DST_EndYear = mYear

    SC_out_DaylightSavingTime = false
    if (CalcJD(mYear,mMonth,mDay) >=
        CalcJD(SC_out_DST_StartYear,
                SC_out_DST_StartMonth,
                SC_out_DST_StartDay)) then
                    if (CalcJD(mYear,mMonth,mDay) <=
                        CalcJD(SC_out_DST_EndYear,
                                SC_out_DST_EndMonth,
                                SC_out_DST_EndDay)) then
                                    '-----------------
                                    SC_out_DaylightSavingTime = true
                    end if
    end if



End Sub


'****************************** End Module *************************************
end.

Main program

Code: Select all

program SunRiseSunSet
include "SunCalc_Library"


Symbol LED7     = PORTB.7
Symbol LED6     = PORTB.6

Sub Procedure ConfigureLocalData

    '==================================================
    ' Local latitude, longitude
    ' 45 54 19.48 , 13 18 36.26
    '==================================================
    SC_in_LatDeg = 45       ' North +; South -;
    SC_in_LatMin = 54
    SC_in_LatSec = 19
    SC_in_LatSec100 = 48

    SC_in_LonDeg = -13      ' West +; East -;
    SC_in_LonMin = 18
    SC_in_LonSec = 36
    SC_in_LonSec100 = 26

    SC_in_GMToffset = 1    ' West -; East +;

    SC_in_Latitude = GetLocalLatitude(SC_in_LatDeg,
                                        SC_in_LatMin,
                                        SC_in_LatSec,
                                        SC_in_LatSec100)

    SC_in_Longitude = GetLocalLongitude(SC_in_LonDeg,
                                        SC_in_LonMin,
                                        SC_in_LonSec,
                                        SC_in_LonSec100)

    ' Daylight Saving Time parameters
    '-----------------------------------------------------------
    SC_in_dst_SMonth    = 3     ' Start period: march for Europe
    SC_in_dst_EMonth    = 10    ' End period: october for Europe

End Sub


main:


    ConfigureLocalData

    TRISB = 0
    PORTB = 0

    ' Today date
    '----------------------
    SC_in_ThisYear = 2008
    SC_in_ThisMonth = 9
    SC_in_ThisDay = 29

    while true

        ' Get more useful information from calendar
        '--------------------------------------------------
        GetMoreCalendarData(SC_in_ThisYear,
                            SC_in_ThisMonth,
                            SC_in_ThisDay,
                            SC_out_IsLeapYear,
                            SC_out_DayOfYear,
                            SC_out_StrDayOfWeek,
                            SC_out_IntDayOfWeek,
                            SC_out_DaylightSavingTime)

        if SC_out_DaylightSavingTime then
            LED7 = true
        ELSE
            LED7 = false
        end if


        GetLocalSunRiseTime (SC_in_Latitude,
                            SC_in_Longitude,
                            SC_in_ThisYear,
                            SC_in_ThisMonth,
                            SC_in_ThisDay,
                            SC_in_GMToffset,
                            SC_out_StrBuffer,
                            SC_out_RiseTime_Hours,
                            SC_out_RiseTime_Minutes)

        GetLocalNoonTime (SC_in_Longitude,
                            SC_in_ThisYear,
                            SC_in_ThisMonth,
                            SC_in_ThisDay,
                            SC_in_GMToffset,
                            SC_out_StrBuffer,
                            SC_out_NoonTime_Hours,
                            SC_out_NoonTime_Minutes)

        GetLocalSunSetTime (SC_in_Latitude,
                            SC_in_Longitude,
                            SC_in_ThisYear,
                            SC_in_ThisMonth,
                            SC_in_ThisDay,
                            SC_in_GMToffset,
                            SC_out_StrBuffer,
                            SC_out_SetTime_Hours,
                            SC_out_SetTime_Minutes)

        ' Free running cycle led
        '-----------------------
        if LED6 = false then
            LED6 = true
        else
            LED6 = false
        end if


    wend

end.


Best regards,
Max

http://www.b-vu.com

Jack Flanders
Posts: 337
Joined: 17 Apr 2008 02:53
Location: Fantasy Land

#2 Post by Jack Flanders » 30 Sep 2008 03:07

Great job, Bytex!!! :D

I especially want to thank you for the exceptional good job of formatting your code. I find it *very* readable. Good use of both punctuation and white space along with indenting.

Outstanding! :D

LGR
Posts: 3204
Joined: 23 Sep 2004 20:07

#3 Post by LGR » 30 Sep 2008 14:16

Seconded. This is how project code should be done.
If you know what you're doing, you're not learning anything.

Bytex
Posts: 459
Joined: 23 Jun 2008 00:58
Location: Palmanova (UD), Italy
Contact:

#4 Post by Bytex » 30 Sep 2008 22:11

Hello guys, good criticisms are always appreciated. Thank you :wink:

Max

Best regards,
Max

http://www.b-vu.com

aaqilkhan
Posts: 57
Joined: 22 Jan 2007 04:45
Location: Toronto, Canada

#5 Post by aaqilkhan » 18 Dec 2008 04:21

Excellent job Bytex. I wrote my own code to calculate solar position. Today i found out ur post and wanted to mention that you did an outstanding job. Very well formatted and excellent coding.

Thanks for sharing.

Bytex
Posts: 459
Joined: 23 Jun 2008 00:58
Location: Palmanova (UD), Italy
Contact:

#6 Post by Bytex » 19 Dec 2008 00:00

Thank you again :D
Max

Best regards,
Max

http://www.b-vu.com

speedy08fr
Posts: 21
Joined: 17 Nov 2010 15:02
Location: france (ardenne)

Re: SunRise-SunSet & Noon time calculation - Library

#7 Post by speedy08fr » 24 Dec 2019 15:13

HELLO
SUPER PROGRAM WELL ABOVE MY CAPACITIES
I WANTED TO KNOW IF WE CAN RECOVER AZIMUT FROM SUN TO THREE HOURS GIVES
RISING. MIDDAY. SLEEP
IS OR IN THE PROGRAME THANKS
ANGLE DEGRÉ

Post Reply

Return to “mikroBasic General”