All,
Would appreciate your constructive criticism on the schematic for my clock project:
And also the code. (Not quite complete yet: still to replace SOUND commands with solenoid/chime sequencing subroutine)
Thanks!
Paul
Would appreciate your constructive criticism on the schematic for my clock project:
And also the code. (Not quite complete yet: still to replace SOUND commands with solenoid/chime sequencing subroutine)
Code:
; Clock
; P. Beard 2/5/2012
#picaxe 20m2
#terminal 4800
; Picaxe Pin symbols
symbol SPKR = C.7
symbol LDR = B.6
symbol IR = C.5
symbol DOORBELL = PINC.6
symbol CHIME0 = C.0
symbol CHIME1 = C.1
symbol CHIME2 = C.2
symbol CHIME3 = C.3
symbol CHIME4 = C.4
symbol PENDpins = pinsB
symbol PENDdirs = dirsB
; Display symbols (SAA1064 Display Driver)
symbol DISPLAY = $70 ; I2C slave address
symbol DISPLAYSETTINGS = %00000111 ; Dynamic; all digits enabled; test mode off
symbol BRIGHTSETTINGS = %01110000 ; bits controlling display brightness
; RTC symbols (Jungletronics DS1338 based module)
symbol RTC = $D0 ; I2C slave address
; Data to translate numbers 0..9 into decimal digits on 7 seg display
symbol SEGDATA = 0
data SEGDATA, (%01011111, %00000101, %10011011, %10001111, %11000101, %11001110, %11011110, %00000111, %11011111, %11001111)
; Data for Charlieplexing the Pendulum display
symbol PENDDATAdirs = 10
data PENDDATAdirs, (%11000, %10100, %10010, %10001, %11000, %01100, %01010, %01001, %10100, %01100, %00110, %00101, %10010, %01010, %00110, %00011, %10001, %01001, %00101, %00011)
symbol PENDDATApins = 30
data PENDDATApins, (%10000, %10000, %10000, %10000, %01000, %01000, %01000, %01000, %00100, %00100, %00100, %00100, %00010, %00010, %00010, %00010, %00001, %00001, %00001, %00001)
; irin command symbols
symbol SETTIME = 10 ; ">10" button on remote
symbol TICKONOFF = 17 ; Vol - button on remote
symbol NOCOMMAND = 255
; Program variables
symbol RTCsecs = b6
symbol RTCmins = b5
symbol RTChours = b4
symbol DISPHoursTens = b8
symbol DISPHoursUnits = b9
symbol DISPMinsTens = b10
symbol DISPMinsUnits = b11
symbol TickOn = bit16
symbol ColonOn = bit17
symbol InputValue = b20
symbol MaxInputValue = b21
symbol InputValuePosition = b22
symbol CHIMEPULSE = 2000
symbol PENDpos = b12
symbol PENDdir = bit18
main:
setfreq m4
; Set time on RTC
'HI2CSETUP I2CMASTER, RTC, i2cslow, i2cbyte
;HI2COUT 0, (<secs>, <mins>, <hours>, <dow>, <day>, <month>, <year>, <control bits>)
'HI2COUT 0, ($00, $50, $12, $07, $09, $06, $12, $14)
TickOn = 1
do
gosub GetTime
gosub UpdateDisplay
gosub Chime
gosub Tick
for PENDpos = 1 to 19
gosub Pendulum
next
gosub Tick
for PENDpos = 18 to 0 step -1
gosub Pendulum
next
loop
GetTime:
; Read current time from RTC
HI2CSETUP I2CMASTER, RTC, i2cslow, i2cbyte
HI2CIN 0, (RTCsecs, RTCmins, RTChours)
return
UpdateDisplay:
; Write time to display, converting from BCD to decimal digits
DISPHoursTens = RTChours / $10 + SEGDATA
read DISPHoursTens, DISPHoursTens
DISPHoursUnits = RTChours & $0F + SEGDATA
read DISPHoursUnits, DISPHoursUnits
; Flash colon (actually just decimal point on this display)
ColonOn = not ColonOn
DISPHoursUnits = 32 * ColonOn | DISPHoursUnits
DISPMinsTens = RTCmins / $10 + SEGDATA
read DISPMinsTens, DISPMinsTens
DISPMinsUnits = RTCmins & $0F + SEGDATA
read DISPMinsUnits, DISPMinsUnits
; Dim display depending on light level
readadc LDR, b0
b0 = b0 / 2 + 16 & BRIGHTSETTINGS | DISPLAYSETTINGS
HI2CSETUP I2CMASTER, DISPLAY, i2cslow, i2cbyte
HI2COUT 0, (b0, DISPMinsUnits, DISPMinsTens, DISPHoursUnits, DISPHoursTens)
return
Tick:
; Make "tick" sound, if enabled, between 7am and 11pm
if TickOn = 1 and RTChours >= $07 and RTChours <= $22 then : pulsout SPKR, 10 : end if
return
Chime:
; Chime only between 7am and 11pm
if RTChours >= $07 and RTChours <= $22 then
if RTCsecs = $00 and RTCmins = $00 then
; Worst version ever of "Westminster Chimes"
sound SPKR, (120, 100, 115, 100, 110, 100)
; "Bong" the hours (convert hours from BCD into 12 hour time: we don't want 22 bongs at 10pm!
b0 = RTChours & 15
b0 = RTChours / 16 * 10 + b0
if b0 > 12 then : b0 = b0 - 12 endif
For b1 = 1 to b0
sound SPKR, (0, 100, 80, 100)
Next
else if RTCsecs = $00 and RTCmins = $15 then
; Chime at quarter past
sound SPKR, (110, 100, 115, 100, 120, 100)
else if RTCsecs = $00 and RTCmins = $30 then
; Chime at half past
sound SPKR, (120, 100, 110, 100, 115, 100)
else if RTCsecs = $00 and RTCmins = $45 then
; Chime at quarter to
sound SPKR, (100, 100, 120, 100, 115, 100)
endif
endif
return
Pendulum:
; Charlieplex the pendulum LEDs
b0 = PENDpos + PENDDATAdirs
read b0, b0
b1 = PENDpos + PENDDATApins
read b1, b1
PENDpins = 0
PENDdirs = b0
PENDpins = b1
; Check for IR commands & doorbell push
b0 = NOCOMMAND
irin [20], IR, b0
if b0 <> NOCOMMAND then gosub ProcessIRCommand
if DOORBELL = 0 then gosub RingDoorbell
return
RingDoorbell:
pulsout CHIME0, CHIMEPULSE
pause 200
pulsout CHIME1, CHIMEPULSE
pause 200
pulsout CHIME2, CHIMEPULSE
pause 200
pulsout CHIME3, CHIMEPULSE
pause 200
pulsout CHIME4, CHIMEPULSE
'sound SPKR, (90, 100, 120, 50, 110, 50, 100, 50)
return
ProcessIRCommand:
sound SPKR, (125, 2)
pause 250
if b0 = TICKONOFF then
TickOn = not TickOn
else if b0 = SETTIME then
; Allow user to enter time
HI2COUT 1, (8, 8, 8, 8) ; clear display
; read tens of hours
MaxInputValue = 2
InputValuePosition = 4
gosub GetInputValue
RTChours = InputValue * $10
; read units of hours
if InputValue = 2 then : MaxInputValue = 3 : else : MaxInputValue = 9 : endif
gosub GetInputValue
RTChours = RTChours | InputValue
; read tens of mins
MaxInputValue = 5
gosub GetInputValue
RTCmins = InputValue * $10
; read units of mins
MaxInputValue = 9
gosub GetInputValue
RTCmins = RTCmins | InputValue
; Set time on RTC and zero the seconds
HI2CSETUP I2CMASTER, RTC, i2cslow, i2cbyte
HI2COUT 0, (0, RTCMins, RTCHours)
sound SPKR, (110, 2, 0, 2, 120, 2)
endif
return
GetInputValue:
do
; read a value from IR remote
irin IR, InputValue
if InputValue >= 0 and InputValue <= 9 then
InputValue = InputValue + 1 % 10
if InputValue <= MaxInputValue then
; digit OK
sound SPKR, (125, 2)
exit
else
; digit not allowed
sound SPKR, (75, 2)
end if
else
; not a digit
sound SPKR, (75, 2)
end if
loop
; Update display with input value
b0 = InputValue + SEGDATA
read b0, b0
HI2COUT InputValuePosition, (b0)
dec InputValuePosition
pause 250
return
end
Paul