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/18 07:18


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 any precision requires horrible, complex (read 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 during the hours of darkness, thus precision is not required, within a few 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 a close 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. The other compromise is that the daylight start/stop times of the solstice months and their +1 are the same to make the advance/retard logic work at the change of the year - the sunrise/sunset times change slowly around here as we are at the peak or trough of the sine wave so again it doesn't make a significantly meaningful difference for dusk-to-dawn lighting.

On the upside: Because it is very maths light, it is really quick, <4ms @ 48MHz so it doesn't "cost" much when called in 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. 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. Obviously, there are 12 groups - the ones in the below example are for London, UK - you will need to change these for your own location and time format if necessary, but for anywhere in the UK south of a line from The Wash to The Wirral, these are probably OK as we aren't after astronomical precision.

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
		Local Float q0,q1

		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 	'08h10-16h00 start/end of full daylight GMT, London UK
				Case 2:st=465:fn=1010	'07h45-16h50
				Case 3:st=410:fn=1060	'06h50-17h40
				Case 4:st=340:fn=1115	'05h40-18h35
				Case 5:st=275:fn=1165	'04h35-19h25
				Case 6:st=230:fn=1210	'03h50-20h10
				Case 7:st=230:fn=1210	'03h50-20h10
				Case 8:st=265:fn=1190	'04h25-19h50
				Case 9:st=315:fn=1125	'05h15-18h45
				Case 10:st=365:fn=1060	'06h05-17h40
				Case 11:st=420:fn=990	'07h00-16h30
				Case 12:st=490:fn=960 	'08h10-16h00
			End Select

			If fn0<>0 Then Exit Do

			fn0=fn:st0=st
			mm=mm+1:If mm>12 Then mm=1
		Loop

		q0=Abs(st0-st)/30:q1=Abs(fn0-fn)/30 ' assume all months are 30 days (told you it was dirty)

		If mm<7 Then
			st=st0-Fix(q0*dd):fn=fn0+Fix(q1*dd) ' advance daylight
		Else
			st=st0+Fix(q0*dd):fn=fn0-Fix(q1*dd) ' retard daylight
		EndIf

		mn=(h*60)+m ' mins of day
		DayLight=(mn>=st) And (mn<fn)

	End Function