Welcome Guest, you are in: Login

Fruit Of The Shed

Navigation (MMBasic)






Search the wiki

»


Page History: Quick and Dirty Daylight Indicator

Compare Page Revisions



« Older Revision - Back to Page History - Newer Revision »


Page Revision: 2017/10/20 10:31


The following is a function to provide a Boolean indicator of whether the given time occurs during "Civil Daylight" on the given date. This is the light period of the day considered between the twilights of sunrise and sunset. To do this with precision requires horrible, complex (= slow) maths and it's a huge overkill for a simple Go/NoGo test.

This function was written to provide some intelligence to exterior lighting so that it is only activated/enabled during the night, thus precision is not required - within 5 or 10 minutes either way is fine.

On the downside: It is very rough and ready: The sunrise/set times change considerably between the start and finish of say, March. This function uses the start of the current month and the start of the next to create a linear progression based around 30 divisions (days). If you graphed it, it wouldn't be a smooth sine wave over the year but rather an analogue made up of a series of straight lines (with some jaggies around month change because for simplicity it assumes there are 30 days in every month). The use of Civil Daylight means there is a tendency to over-compensate for darkness anyway so it shouldn't be a problem.

On the upside: Because it is very maths light, it is really quick, <4ms @ 48MHz so it doesn't cost much if you want to call it from the main loop.

The numbers in the Case statements are the STart and FiNish of daylight as minutes from midnight for the first day of the relevant month with no daylight saving time. I did try this with the times on the 22nd of each month so the function would be exactly right on the longest and shortest days of the year but it resulted in a much higher fluctuation over the remainder of the month due to the 22 day offset early on in each month and only 8 days after.

A day contains 1440 minutes and so daylight may start at the 405th minute and continue until the 1060th minute (i.e. 06:45 until 17:40). This sunrise/set online tool was used to obtain the daylight times with a few tweaks. Converting to the numbers here is simply the first day of each month, and I based them on civil twilight start and stop times; HH*60+MM. There are 13 groups; having an additional month for January after December removes the need for a modulo and so is a tiny speed increase at the expense of a bit of program space. The times shown are for London, UK rounded up or down to 5 minutes - you can change these for your own location but do not include daylight saving times.

This is the second version of this function which eliminates some variables and decision making; generally improving performance and avoiding the flat spots around the solstice months.

Accepts the standard DATE$ and TIME$ strings as argument, any seconds on the time string are ignored e.g both hh:mm:ss and hh:mm are fine.

Syntax:
x=Daylight(strDateDDMMYYYY,strTime24H) Do not use Daylight saving

Example Uses:
DaylightAug5am=Daylight("17/08/2017","05:00:00")
or
DaylightAug5am=Daylight("17/08/2017","05:00")

If Daylight(Date$,Time$) Then LightsOff Else LightsOn


Code
  Function DayLight(dt$,tm$) As Integer ' DT must be dd/mm/yyyy as per DATE$, tm$ is hh:mm[:ss] so TIME$ will work
    Local Integer mn,st,fn,st0,fn0,dd,mm,h,m

    dd=Val(Left$(dt$,2)):mm=Val(Mid$(dt$,4,2)):h=Val(Left$(tm$,2)):m=Val(Mid$(tm$,4,2))

    Do
      Select Case mm
        Case 1:st=490:fn=960 'i.e. 0810-1600 start/end of full daylight GMT, London UK - probably OK for all of UK
        Case 2:st=460:fn=1010
        Case 3:st=405:fn=1060
        Case 4:st=335:fn=1115
        Case 5:st=275:fn=1165
        Case 6:st=230:fn=1210
        Case 7:st=230:fn=1220
        Case 8:st=265:fn=1190
        Case 9:st=315:fn=1115
        Case 10:st=360:fn=1060
        Case 11:st=415:fn=990
        Case 12:st=470:fn=955
        Case 13:st=490:fn=960' december +1 = january
      End Select

      If fn0<>0 Then Exit Do

      fn0=fn:st0=st
      mm=mm+1
    Loop

    st=st0-(((st0-st)/30)*dd):fn=fn0-(((fn0-fn)/30)*dd)
    mn=(h*60)+m ' mins of day
    DayLight= (mn>=st) And (mn<fn)

  End Function