| The Free Site | vBuddy - make friends, share photos, blogs, have fun | Cheap Web Hosting - starting at $5 |
LCD Clock for controlling pumps with off peak electricity
This circuit is used for controlling pumps with electricity that is cheaper after 10pm (9pm in daylight saving) and on weekends. It gives two outputs that are high with peak and offpeak electricity. The time and date are controlled with a DS1307 real time clock and displayed on a 2x16 line LCD module. The unit also outputs the time in a serial data format to a common bus at regular intervals.
Schematic

Code
' pin6= latch clock HC595 pin 12 - low to high transition
latches the data
' pin7 = serial data out = HC595 pin 14
' pin5= shift clock = HC595 pin 11 - low to high tranition stores the serial data out
' note **** in the picaxe programmer View menue Options/Mode screen, change the 16x gosub
to 256x gosub
' if get weird bugs watch the maximum 4 nested gosubs
start:pause 1000
'gosub setclock
gosub initialiseclock' tell i2c that clock exists
goto initnew' start display
main:' main program loop
'gosub testcount used for debugging the time set
gosub buttontest
gosub readtime
gosub senddata' send to output pin 3 blue wire
gosub firstline' put display on 1st line
peek 92,b0
gosub splitbyte' hours
b1=":"
gosub wrchar
peek 91,b0
gosub splitbyte' minutes
gosub buttontest
b1=136' move cursor
gosub wrins
peek 94,b0
gosub splitbyte' day
gosub buttontest
b1="/"
gosub wrchar
peek 95,b0
gosub splitbyte' month
gosub buttontest
b1="/"
gosub wrchar
peek 96,b0
gosub splitbyte' year
gosub buttontest
' display weekday
gosub readtime
gosub secondline
peek 93,b10' number 1 to 7, 1=sunday
select case b10
case 1
for b9=0 to 8
lookup b9,("Sunday "),b1
gosub wrchar
next
case 2
for b9=0 to 8
lookup b9,("Monday "),b1
gosub wrchar
next
case 3
for b9=0 to 8
lookup b9,("Tuesday "),b1
gosub wrchar
next
case 4
for b9=0 to 8
lookup b9,("Wednesday"),b1
gosub wrchar
next
case 5
for b9=0 to 8
lookup b9,("Thursday "),b1
gosub wrchar
next
case 6
for b9=0 to 8
lookup b9,("Friday "),b1
gosub wrchar
next
case 7
for b9=0 to 8
lookup b9,("Saturday "),b1
gosub wrchar
next
endselect
gosub buttontest
gosub offpeakpower
' spend most of time waiting for button push
w0=0
do
if pin1=1 then exit
pause 100
w0=w0+1
if w0>500 then exit
loop
gosub buttontest
goto main
' **** latch routines ***
senddatatolatch:' sends data in b0
b6=b0' so returns b0 unchanged
' note QA is MSB and QH is LSB (binary number reads down) feed in LSB first
low 5
low 6
low 7
for b1=1 to 8
b2=b0 and %00000001
if b2=0 then
low 7
else
high 7
endif
high 5
low 5
let b0=b0/2
next
high 6
low 6
b0=b6
poke 87,b0' store the latch status
return
QAhigh:peek 87,b0' pin 15
b0=b0 or %10000000
goto senddatatolatch
QAlow:peek 87,b0' pin 15
b0=b0 and %01111111
goto senddatatolatch
QBhigh:peek 87,b0' pin 1
b0=b0 or %01000000
goto senddatatolatch
QBlow:peek 87,b0' pin 1
b0=b0 and %10111111
goto senddatatolatch
QChigh:peek 87,b0' pin 2
b0=b0 or %00100000
goto senddatatolatch
QClow:peek 87,b0' pin 2
b0=b0 and %11011111
goto senddatatolatch
QDhigh:peek 87,b0' pin 3
b0=b0 or %00010000
goto senddatatolatch
QDlow:peek 87,b0' pin 3
b0=b0 and %11101111
goto senddatatolatch
QEhigh:peek 87,b0' pin 4
b0=b0 or %00001000
goto senddatatolatch
QElow:peek 87,b0' pin 4
b0=b0 and %11110111
goto senddatatolatch
QFhigh:peek 87,b0' pin 5
b0=b0 or %00000100
goto senddatatolatch
QFlow:peek 87,b0' pin 5
b0=b0 and %11111011
goto senddatatolatch
QGhigh:peek 87,b0' pin 6
b0=b0 or %00000010
goto senddatatolatch
QGlow:peek 87,b0' pin 6
b0=b0 and %11111101
goto senddatatolatch
QHhigh:peek 87,b0' pin 7
b0=b0 or %00000001
goto senddatatolatch
QHlow:peek 87,b0' pin 7
b0=b0 and %11111110
goto senddatatolatch
' *** clock routines ***
Readtime:
i2cslave %11010000, i2cslow, i2cbyte set slave details
readi2c 0, (b0, b1, b2,b3,b4,b5,b6) read sec, min, hour weekday
day month year
poke 90,b0' secs
poke 91,b1' mins
poke 92,b2' hours
poke 93,b3' weekday 1-7
poke 94,b4' day
poke 95,b5' month
poke 96,b6' year
b13=b0
gosub bcdtodecimal' seconds
b0=b13
b13=b1
gosub bcdtodecimal' mins
b1=b13
b13=b2
gosub bcdtodecimal' hours
b2=b13
b13=b4
gosub bcdtodecimal' day (no need to do weekday as <10)
b4=b13
b13=b5
gosub bcdtodecimal ' month
b5=b13
b13=b6
gosub bcdtodecimal
b6=b13
poke 80,b0' poke decimal data for exporting to other picaxes if
requested
poke 81,b1' mins
poke 82,b2' hour
poke 83,b3' day 1-7
poke 84,b4' day
poke 85,b5' month
poke 86,b6' year
return
Setclock:i2cslave %11010000, i2cslow, i2cbyte
' seconds minutes hours weekday day month year
' sunday = 1 and this was set on Wed = 4
' day of the week number is not linked - it just goes to 7 then resets
' see codes re 24/12 hour clock but essentially if send as the hex number is 24h clock
' *** warning if ever set clock use 2 bcd numbers not decimal value
writei2c 0, ($00, $32, $13, $01, $05, $08, $07, $10)
return
WriteClock:i2cslave %11010000, i2cslow, i2cbyte' pokes last reads back into clock
peek 90,b0
peek 91,b1
peek 92,b2
peek 93,b3
peek 94,b4
peek 95,b5
peek 96,b6
writei2c 0,(b0,b1,b2,b3,b4,b5,b6,$10)
return
Initialiseclock:i2cslave %11010000, i2cslow, i2cbyte
return
BCDtoDecimal:' all clock values are 2 bcd numbers. If convert to hex they display
correctly
' pass b13, returns b13
b12=b13 and %00001111
b11=b13 / 16 ' shifts right 4 places
b10=b11*10
b13=b10+b12
return
' ***** LCD routines ******
' pin7 for reved's direct comms = pin 14 on the display = QA
' pin6= display 13 = QB
' pin5 = display 12 = QC
' pin4 = display 11 = QD
' pin3 = display 6 = QE
' pin2 = display 4 = QF
' QG = led
initnew:b0=0
gosub senddatatolatch' all outputs low
pause 200
gosub QChigh' send 0011
gosub QDhigh
gosub toggleenable
pause 10
gosub toggleenable
gosub toggleenable
gosub QDlow' send 0010
gosub toggleenable
gosub toggleenable
gosub QAhigh' send 1000
gosub QClow
gosub toggleenable
b1=%00001110' 14
gosub wrins
gosub cleardisplay
gosub hidecursor
gosub firstline
goto main
cleardisplay:b1=1
gosub wrins
return
hidecursor:b1=12
gosub wrins
return
firstline:b1=128
gosub wrins
return
secondline:b1=192
gosub wrins
return
' pins 76543210 = byte so MSB makes pin 7 high which is pin 14 on display
'wrinsold:b8=b1' temp store as qflow changes
' gosub QFlow
' b1=b8
' gosub bytetodisplay
' gosub QFhigh
' return
'wrcharold: b8=b1' not used any more
' gosub QFhigh
' b1=b8
' goto bytetodisplay
'bytetodisplay:' pass b1
' b7=b1' b7 not used by subs of this subroutine
' b2=b7 and %10000000
' if b2=128 then
' gosub QAhigh
' else
' gosub QAlow
' endif
' b2=b7 and %01000000
' if b2=64 then
' gosub QBhigh
' else
' gosub QBlow
' endif
' b2=b7 and %00100000
' if b2=32 then
' gosub QChigh
' else
' gosub QClow
' endif
' b2=b7 and %00010000
' if b2=16 then
' gosub QDhigh
' else
' gosub QDlow
' endif
' gosub QEhigh' toggle enable
' gosub QElow
' b2=b7 and %00001000
' if b2=8 then
' gosub QAhigh
' else
' gosub QAlow
' endif
' b2=b7 and %00000100
' if b2=4 then
' gosub QBhigh
' else
' gosub QBlow
' endif
' b2=b7 and %00000010
' if b2=2 then
' gosub QChigh
' else
' gosub QClow
' endif
' b2=b7 and %00000001
' if b2=1 then
' gosub QDhigh
' else
' gosub QDlow
' endif
' gosub QEHigh
' gosub QElow
' return
toggleenable:gosub QEhigh
gosub QElow
return
splitbyte:' takes b0 which consists of two bcd numbers from the time chip, splits into two
ascii numbers and sends to display
poke 97,b0
b1=b0 and %11110000' msb first
b1=b1/16 ' shift to right
b1=b1+48' add so turns into numbers
gosub wrchar' write 1st number
peek 97,b0
b1=b0 and %00001111' lsb
b1=b1+48
gosub wrchar' write 2nd number
peek 97,b0' restore for next sub so doesnt change
return
wrchar:' since the lcd is the only thing using the HC595 it doesn't matter what the
previous bytes are
' to send a char, RS (QF) = high, SE (QE) toggles nibbles in
b8=b1' temp store
low 5' setup HC595
low 6
low 7
b0=b1 and %11110000' mask high nibble
b0=b0 or %00000100' make RS high
b0=b0 or %00000010' make led high
gosub fast595' set up bytes, will resend so nibble definitely high when send
b0=b0 or %00001000' toggle SE (QE)
gosub fast595
b0=b0 and %11110100' SE low, and led off also
gosub fast595
b0=b8*16' move other nibble into b0
b0=b0 and %11110000' mask high nibble but probably not necessary
b0=b0 or %00000100' make RS high
gosub fast595' set up bytes, will resend so nibble definitely high when send
b0=b0 or %00001000' toggle SE (QE)
gosub fast595
b0=b0 and %11110100' SE low, and led off also
gosub fast595
b1=b8' return this character in case need to print again
return
wrins:' since the lcd is the only thing using the HC595 it doesn't matter what the
previous bytes are
' to send a char, RS (QF) = low, SE (QE) toggles nibbles in
b8=b1' temp store
low 5' setup HC595
low 6
low 7
b0=b1 and %11110000' mask high nibble and RS set low
gosub fast595' set up bytes, will resend so nibble definitely high when send
b0=b0 or %00001000' toggle SE (QE)
gosub fast595
b0=b0 and %11110000' SE low
gosub fast595
b0=b8*16' move other nibble into b0
b0=b0 and %11110000' mask high nibble but probably not necessary
gosub fast595' set up bytes, will resend so nibble definitely high when send
b0=b0 or %00001000' toggle SE (QE)
gosub fast595
b0=b0 and %11110000' SE low
gosub fast595
b0=b0 or %00000100' RS high ready for next byte
gosub fast595
return
fast595:' send byte in b0 out to HC595 QA=MSB
b3=b0' temp store
for b1=1 to 8
b2=b0 and %00000001
if b2=0 then
low 7' send out bit
else
high 7
endif
high 5' toggle clock
low 5
let b0=b0/2' shift right
next
high 6' send out byte
low 6
b0=b3' return the byte unchanged in b0
return
dualbcdtodecimal:' takes b0=aaaabbbb = 2 bcd numbers and returns b0=actual number eg
00010001 then b1=11
b1=b0 and %11110000' mask high nibble
b2=b1/16' move to right 4 places
b3=b2*10' multiply by 10
b4=b0 and %00001111' mask low nibble
b0=b3+b4
return
decimaltodualbcd:' pass b0, does reverse of above
b1=b0/10' get high nibble tens
b2=b1*16' move to left 4 places
b3=b1*10' multiply back
b4=b0-b3 ' get ones
b0=b2 or b4' merge together
return
testcount:peek 98,b0
gosub dualbcdtodecimal
b0=b0+1
if b0>20 then
b0=0
endif
gosub decimaltodualbcd
poke 98,b0
b1=133
gosub wrins' cursor move
peek 98,b0' get back number
gosub splitbyte' display two numbers
return
OffPeakPower:' rules - 10pm to 8am= off peak EXCEPT november to march inclusive, = 9pm
' and also Sat and Sun=off peak
peek 82,b0' hour
peek 83,b1' weekday number
peek 85,b2' month
b3=0' 0=peak, 1 = off peak
select case b0' hour 24 hour clock off peak = 22 to 24 and 0 to 7
case 22 to 24
b3=1
case 0 to 7
b3=1
else
b3=0' peak
endselect
select case b1
case 1' Sunday
b3=1
case 7' Saturday
b3=1
endselect
select case b2
case 11 to 12
b3=1
case 1 to 3
b3=1
endselect
' display
select case b3
case 0
b1=204
gosub wrins
for b9=0 to 3
lookup b9,("Peak"),b1
gosub wrchar
next
high 0' set output pin 0 high
low 2
case 1
b1=201
gosub wrins
for b9=0 to 6
lookup b9,("OffPeak"),b1
gosub wrchar
next
high 2' set output pin 2 high
low 0
endselect
return
SendData:let b2=0 ' device no n **Note this subroutine will change with the new bus
format***
'let b3=15 ' 4 data bytes
peek 81,b3
peek 82,b4
peek 85,b5
peek 86,b6
let w6=b3+b4+b5+b6 ' add up checksum
serout 3,N1200,("DataI",b2,b3,b4,b5,b6,b12,b13)
return
enternewnumber:' pass poke88=cursor position, poke89=max count returns b0= new number to
store in 9x
peek 88,b1
gosub wrins' cursor to first item
b1=" "
gosub wrchar
gosub wrchar
gosub readtime
do
peek 88,b1
gosub wrins' cursor to this position
let b0=b9
gosub decimaltodualbcd
gosub splitbyte
peek 88,b1
gosub wrins' cycle number and blank so know this one is active
b1=" "
gosub wrchar
if pin1=1 then exit
if pin0=1 then
' count up
let b9=b9+1
peek 89,b0
if b9>b0 then
b9=0
endif
endif
loop
peek 88,b1
gosub wrins' display last number
b0=b9
gosub decimaltodualbcd' new value in b0
gosub splitbyte
return
buttontest:
if pin1=0 then
return' button not pushed
endif
' menu button pushed so cycle through
' set hours first
peek 82,b9' get decimal value
poke 88,128' cursor position
poke 89,24' maximum count
gosub enternewnumber
poke 92,b0
gosub writeclock' store new hours
' now change minutes
peek 81,b9
poke 88,131
poke 89,60
gosub enternewnumber
poke 91,b0
gosub writeclock
' change date day number
peek 84,b9' current value
poke 88,136' cursor
poke 89,31' max count
gosub enternewnumber
poke 94,b0' store
gosub writeclock
' change month
peek 85,b9' current value
poke 88,139' cursor
poke 89,12' max count
gosub enternewnumber
poke 95,b0' store
gosub writeclock
' change year
b9=7 ' defaults back to 2007 otherwise take forever cycling to 99
poke 88,142
poke 89,99
gosub enternewnumber
poke 96,b0' store
gosub writeclock
' change day number
peek 83,b9
poke 88,192' second line now
poke 89,7' max
gosub enternewnumber
if b0=0 then
b0=1
endif
poke 93,b0' store
gosub writeclock
' finish up
gosub cleardisplay
b1=128
gosub wrins
b1="S"
gosub wrchar
b1="e"
gosub wrchar
b1="t"
gosub wrchar
pause 4000
goto main