Where I live (Connel, Argyll), we have a simple but confusing system of bin collections: Recycling blue bins are collected fortnightly on Fridays and Landfill green bins are collected 3-weekly, also on Fridays. The algorithm is straightforward but remembering on Thursday (bins are emptied early in the morning) which part of the cycle applies is challenging.
I used an MSF based clock to tell the date and a simple bit of arithmetic using the Julian Date number (offset to a start date on which I know the bins state) to work out the states of the two bins. Green or Blue LEDs are lit on Thursday morning and stay lit until Friday night as appropriate. I used the Universal Solder MSF module.
I added a Red LED to warn if the MSF clock is not working. It sometimes loses the signal for a few minutes. The TIME variable is used to keep the clock moderately correct. It only needs to get the day of the week right. If the MSF clock has failed for over 24 hours, the Red LED flashes. I haven't noticed this happen in 2 years of operation. I am about 120 miles from the Anthorrn (Cumbria) MSF transmitter.
I am indebted to contributors to the forum:
Hippy's Show bits MSF decoder, http://www.picaxeforum.co.uk/showthread.php?11334-Decoding-UK-s-NPL-MSF-Time-Signal post 36
and
T.Ikeda's Julian day number (JDN) calculator https://picaxeforum.co.uk/threads/julian-date-code-for-picaxe.8674/
I used an MSF based clock to tell the date and a simple bit of arithmetic using the Julian Date number (offset to a start date on which I know the bins state) to work out the states of the two bins. Green or Blue LEDs are lit on Thursday morning and stay lit until Friday night as appropriate. I used the Universal Solder MSF module.
I added a Red LED to warn if the MSF clock is not working. It sometimes loses the signal for a few minutes. The TIME variable is used to keep the clock moderately correct. It only needs to get the day of the week right. If the MSF clock has failed for over 24 hours, the Red LED flashes. I haven't noticed this happen in 2 years of operation. I am about 120 miles from the Anthorrn (Cumbria) MSF transmitter.
I am indebted to contributors to the forum:
Hippy's Show bits MSF decoder, http://www.picaxeforum.co.uk/showthread.php?11334-Decoding-UK-s-NPL-MSF-Time-Signal post 36
and
T.Ikeda's Julian day number (JDN) calculator https://picaxeforum.co.uk/threads/julian-date-code-for-picaxe.8674/
Code:
#PICAXE 08M2
#NO_DATA
' Bins alarm MSF self start
' DW 2/24
' Show when which bins should go out. Lights up on Wednesday midnight and stays on until Friday midnight
' Take date data from MSF clock, convert to JDN starting 24/3/23=0, calculate when Green or Blue bin goes out
' Uses MSF to find what date it is
'Receive MSF data based on:
'Hippy's Show bits as received and display date/time info from
'http://www.picaxeforum.co.uk/showthread.php?11334-Decoding-UK-s-NPL-MSF-Time-Signal post 36
' Red LED on C.0 flashing if no MSF for 12 hours or more. On steady if MSF not working but <12 hr since last time fix. Off when MSF working.
' Diagnotic output for LCD/OLED on C.4.
'Julian day number (JDN) calculator
'Created: 2007-12-23 (T.Ikeda - KA1OS)
'Latest mod: 2008-01-27
'From https://picaxeforum.co.uk/threads/julian-date-code-for-picaxe.8674/
' Uses LCD/OLED to display diagnostics.
SYMBOL RedLight =C.0 ' Red LED on leg 7, along with Programming line
SYMBOL BlueLight=C.1 ' Blue LED on leg 6
SYMBOL GreenLight=C.2 ' Green LED on leg 5
Symbol SIGNAL = pinC.3' Radio signal Input Pin (leg 4)
Symbol LCDout = C.4 ' LCD diagnostics out (leg 3)
Symbol ACTIVE = 1 ' Active level ( 0 or 1 )
Symbol INACTIVE = ACTIVE ^ 1
Symbol gapchar = "-"
Symbol bitest = bit0 'Counts bits for parity tests
Symbol btyr = bit1 'Parity test 17-24
Symbol btmd = bit2 'Parity test 25-35
Symbol btdow = bit3 'Parity test 36-38
Symbol bttim = bit4 'Parity test 39-51
Symbol Paritycheck=bit5 'Overall parity result (1=good)
Symbol bitA = bit6
Symbol bitB = bit7
SYMBOL GFlag = bit8 ' High when Green bin is due
SYMBOL BFlag = bit9 ' High when Blue bin is due
SYMBOL RFlag = bit10 ' High when red light is on or flashing
SYMBOL FlFlag= bit11 ' High if MSF hasn't worked for 12 hours
Symbol bcd = b2 ' MSF workspace
Symbol bitVal = b3 ' MSF workspace
SYMBOL JDN = w2 'b4,b5 Julian date number
SYMBOL JDtest=w3 'b6,b7 JDN or JDN+1 so we score a hit on Thursday and Friday
SYMBOL test = b8 ' 0 on Thursday/Friday
SYMBOL hour = b14
SYMBOL mins = b15
SYMBOL dow = b16
SYMBOL yr = b17
SYMBOL mon = b18
SYMBOL date = b19
Symbol bits = b22
SYMBOL putPtr = b23
SYMBOL mn = w13 ; b26, b27 minutes after midnight
SYMBOL p50 = 50 'For default freq M4
Symbol p100= 100
Symbol p200=200
SYMBOL tmax=43200 ' 12hrs in seconds for TIME. For 4MHz
SYMBOL baudmode = N2400_4
LOW BlueLight ' All bin lights off to start
LOW GreenLight
HIGH RedLight ' MSF Clock not working yet
FlFlag = 0 ' Set after tmax without MSF, flashing red
TIME = 0
BFlag = 0
GFlag = 0
RFlag = 1
Do ' Wait for the MSF clock to get started
Gosub ReadBit
Loop
Paritycheck=0
WaitForMinute:
IF Paritycheck=1 THEN ' If MSF is working, use its time; reset error flags
LOW RedLight
FlFlag = 0 ' No Flashing or steady Red light
RFlag = 0
TIME = 0
hour = mn/60
mins = mn//60
Paritycheck=0
serout LCDout, baudmode, (254,128," using MSF ")
ELSEIF RFlag=0 THEN ' MSF Clock not working
RFlag = 1 ' MSF was working but now it's not
HIGH RedLight
TIME = 0
ELSEIF TIME>tmax THEN
FlFlag = 1 ' MSF hasn't worked for 12 hours so start flashing
TIME = 0
RFlag = 1
ELSEIF FlFlag=1 THEN
IF TIME>0 THEN
Toggle RedLight ' MSF not working>12hrs, keep flashing
RFlag = 1
TIME = 0
ENDIF
ENDIF
IF mins<10 THEN
serout LCDout, baudmode, (254,139,#hour,":0",#mins," ")
ELSE
serout LCDout, baudmode, (254,139,#hour,":",#mins," ")
ENDIF
serout LCDout, baudmode, (254,192,#BFLag," ",#GFlag," ",#DOW," ")
' Correct time has been established.
'Julian day number (JDN) calculator by T.Ikeda
'From https://picaxeforum.co.uk/threads/julian-date-code-for-picaxe.8674/
'Works with dates from 2000-01-01 to 2178-12-31
'
'Original program had 2000-01-01, JDN = 0 (Epoch: 2000-01-01)
' To extend usefulness, moved Epoch to 2023-03-24 has JDN=0.
JDN = 0
If mon > 2 Then
JDN = 1
End If
JDN = yr + JDN * 7 / 4
JDN = 367 * yr - JDN
JDN = mon * 3912 / 128 + date - 31 + JDN
'Add correction for 2100 not being a leap year...
If JDN > 36584 Then
JDN = JDN -1
End If
JDN = JDN - 8483 'JDN epoch moved to 2023-03-24=day0. Blue bin next week Green in 2 weeks.
JDtest = JDN + 1
test = JDtest//7
test = JDN//7 * test ' Is Zero on Thursdays & Fridays
IF test=0 THEN
BFlag = JDtest // 14 / 7 ' Every 2 weeks
GFlag = JDtest // 21 / 14 ' Every 3 weeks
ELSE
BFlag = 0
GFlag = 0
ENDIF
IF BFLag=1 THEN 'This is a Blue week
HIGH BlueLight
ELSE
LOW BlueLight
ENDIF
IF GFlag=1 THEN 'This is a Green week
HIGH GreenLight
ELSE
LOW GreenLight
ENDIF
serout LCDout, baudmode, (254,192,#JDN, " ",#BFlag, " ",#GFlag," ")
Do ' Back to MSF clock
Gosub ReadBit
Loop
END
StartMinute:
putPtr = $50
bits = 16 : Gosub ReadBcd ' $50,$51 Unused bits 16
bits = 8 : bitVal = 8 : Gosub ReadBcd : btyr = bitest ' $52,$53 Year bits 4+4
bits = 5 : bitVal = 1 : Gosub Readbcd : btmd = bitest ' $54,$55 Month bits 1+4
bits = 6 : bitVal = 2 : Gosub ReadBcd : btmd = btmd + bitest ' $56,$57 Day bits 2+4
bits = 3 : bitVal = 4 : Gosub Readbcd : btdow = bitest ' $58,$59 DOW bits 3
bits = 6 : bitVal = 2 : Gosub ReadBcd : bttim = bitest' $5A,$5B Hour bits 2+4
bits = 7 : bitVal = 4 : Gosub Readbcd : bttim = bttim + bitest ' $5C,$5D Minutes bits 3+4
bits = 2 : Gosub ReadBcd ' Unused bits 2
bits = 1 : Gosub ReadBcd : btyr = btyr + bitB ' Year parity check bit 54B
bits = 1 : Gosub ReadBcd : btmd = btmd + bitB ' Month/day parity check bit 55B
bits = 1 : Gosub ReadBcd : btdow= btdow+ bitB ' DOW parity check bit 56B
bits = 1 : Gosub ReadBcd : bttim= bttim+ bitB ' Time parity check 57B
IF btyr=1 AND btmd=1 AND btdow=1 AND bttim=1 THEN
Paritycheck = 1
putPtr = $52
DO
Peek putPtr,bcd
IF putPtr = $52 THEN
yr = bcd
ENDIF
IF putPtr = $54 THEN
mon = bcd
ENDIF
IF putPtr = $56 THEN
date = bcd
ENDIF
IF putPtr = $58 THEN
dow = bcd
ENDIF
IF putPtr = $5A THEN
mn = bcd*60
Endif
IF putPtr = $5C THEN
mn = mn + bcd
ENDIF
putPtr = putPtr+1
Peek putPtr,bcd
putPtr = putPtr+1
Loop until putPtr>$5C
ENDIF
Goto WaitForMinute
ReadBcd:
bcd = 0 'Accumulate data into bcd bit by bit
bitest = 0
Do
Gosub ReadBit
bcd = bitVal * BitA + bcd 'Add next bit
bitest = bitest + bitA
bitVal = bitVal / 2 'Define next bit's value
bits = bits - 1 'Keep count of bits
If bits = 4 Then 'If it's a 2 digit result, this is the tens
bcd = bcd * 10
bitVal = 8
End If
Loop Until bits = 0
Poke putPtr,bcd
putPtr = putPtr+1
Poke putPtr,gapChar
putPtr = putPtr+1
Return
ReadBit:
Do : Loop Until SIGNAL IS INACTIVE
Do : Loop Until SIGNAL IS ACTIVE
Pause p50
If SIGNAL IS INACTIVE Then WaitForMinute
Pause p100
bitA = SIGNAL ^ INACTIVE
Pause p100
bitB = SIGNAL ^ INACTIVE
Pause p200
If SIGNAL IS ACTIVE Then StartMinute
'sertxd( #bitA )
Return