Programmable Timer
The Project
My use for this timer is to turn my water heater on and off during usable times. I can be adapted to be used for just about any timing need. I designed it to have two programming schedules, weekdays and weekends. I decided this would be the best setup for a water heater given most people work or go to school on weekdays and are home on weekends giving reason to have two different heating schedules. Each schedules has two programmable on and off phases.
For instance, you can program the timer to switch the water heater on at 5am and off at 9am. This turns the timer on in time to warm up for the 6am risers to shower and get off to work or school. With them gone by nine, the heater would then shut off at 9am. The second on-off phase can then be set to turn the heater back on at 4pm to warm up in time for people home at 5pm to have hot water for cooking, showering or what not. After everyone is in bed, there is no need for hot water until morning so we program the heater to shut off at 11pm. With this schedule, our water heater runs 11 hours a day (less than half the time) saving power and money.
Since people are home all day on the weekends, the weekend schedule can be set to turn on at 5am and shutoff at 11pm. However, if two phases are needed they are available.
The timer can easily be adapted to have a different a schedule for each day of the week. My project only needed weekdays and weekends.
The Circuit
The circuit is fairly simple. It uses a Picaxe 18X uC, a DS1307RTC and a relay suitable for the load being switched. There are four buttons for programming, PGM, NXT, UP and DWN. The picaxe simply reads the current time from the RTC, goes through the decision-making process and switches the load on or off according to the programmed schedule.
I will post the schematic shortly as I am currently working on it.
The Code
The code has quite a few lines but isn't very tough to understand. Many of the segments are just repeated with different variables. I will try to finish commenting in the near-future. The .bas file can be found here.
#picaxe 18x
setfreq m8
symbol pgm=pin0
symbol nxt=pin1
symbol up=pin2
symbol dwn=pin6
symbol htr=7
eeprom 0,(5,8,16,22,5,22,5,22)
i2cslave %11010000, i2cslow, i2cbyte 'sets up i2c addressing for DS1307
main:
setint %00000001,%00000001
readi2c 1,(b0,b1,b3) 'reads hour and day from DS1307
let b2=b0 and %00001111 'converts min bcd time format to decimal
let b0=b0/16*10+b2
let b4=b1 and %00001111 'converts hour bcd code format to decimal
let b1=b1/16*10+b4
let b5=b3 and %00001111 'converts day bcd time format to decimal
let b3=b3/16*10+b5
if b0<10 and b1<10 then
serout 5,N2400_8,(254,128,"0",#b1,":0",#b0," ")
elseif b0>9 and b1>9 then
serout 5,N2400_8,(254,128,#b1,":",#b0," ")
elseif b0<10 and b1>9 then
serout 5,N2400_8,(254,128,#b1,":0",#b0," ")
elseif b0>9 and b1<10 then
serout 5,N2400_8,(254,128,"0",#b1,":",#b0," ")
endif
gosub testday
if b3<=5 then '
read 0,b0,b2,b3,b4:goto test 'tests whether it is weekday
else 'or weekend and runs
read 4,b0,b2,b3,b4:goto test 'appropriate comparisons
endif '
goto main '
test:
if b1>=b0 and b1<b2 or b1>=b3 and b1<b4 then 'tests time against heater
high htr 'schedule and toggles htr
else 'or off accordingly
low htr '
endif '
goto main
testday:
if b3=1 then
serout 5,N2400_8,(254,135," Monday ")
elseif b3=2 then
serout 5,N2400_8,(254,135," Tuesday ")
elseif b3=3 then
serout 5,N2400_8,(254,135,"Wednesday")
elseif b3=4 then
serout 5,N2400_8,(254,135,"Thursday ")
elseif b3=5 then
serout 5,N2400_8,(254,135," Friday ")
elseif b3=6 then
serout 5,N2400_8,(254,135,"Saturday ")
elseif b3=7 then
serout 5,N2400_8,(254,135," Sunday ")
endif
return
interrupt:
let b4=0
let b5=0
for b4=0 to 1
if pgm=1 then let b5=b5+1
endif
pause 2000
next b4
if b5=2 then set
return
set:
serout 5,N2400_8,(254,128,"Program SetTime")
serout 5,N2400_8,(254,192," Up Dwn ")
if up=1 then
goto program
elseif dwn=1 then
goto pgmtime
elseif nxt=1 then
serout 5,N2400_8,(254,1):goto reint
endif
goto set
reint:
setint %00000001,%00000001
return
program:
pause 3000
program1:
serout 5,N2400_8,(254,128,"Weekday Weekend")
serout 5,N2400_8,(254,192," Up Dwn ")
if up=1 then
goto wkdaypgm1
elseif dwn=1 then
goto wkendpgm1
elseif nxt=1 then
goto set
endif
goto program1
wkdaypgm1:
pause 3000
let b12=0
let b0=12
let b1=12
let b2=0
wkdaypgm15:
gosub htrpgm
goto wkdaypgm2
wkdaypgm2:
let b12=2
let b0=12
let b1=12
let b2=0
wkdaypgm25:
gosub htrpgm
goto program
wkendpgm1:
pause 3000
let b12=4
let b0=12
let b1=12
let b2=0
wkendpgm15:
gosub htrpgm
goto wkendpgm2
wkendpgm2:
let b12=6
let b0=12
let b1=12
let b2=0
wkendpgm25:
gosub htrpgm
goto program
htrpgm:
serout 5,N2400_8,(254,128,"Start hour: ",#b0," ")
serout 5,N2400_8,(254,192,"Stop hour: ",#b1," ")
if b2=0 then
serout 5,N2400_8,(254,143,60)
serout 5,N2400_8,(254,207," ")
elseif b2=1 then
serout 5,N2400_8,(254,207,60)
serout 5,N2400_8,(254,143," ")
endif
if up=1 and b2=0 then
let b0=b0+1 max 24 min 0
elseif up=1 and b2=1 then
let b1=b1+1 max 24 min 0
elseif dwn=1 and b2=0 then
let b0=b0-1 min 0 max 24
elseif dwn=1 and b2=1 then
let b1=b1-1 min 0 max 24
elseif nxt=1 then
let b2=b2-1 min 0 max 1
elseif pgm=1 then
write b12,b0,b1:return
endif
goto htrpgm
pgmtime:
pause 3000
let b2=0
let b0=12
let b1=30
serout 5,N2400_8,(254,1)
pgmtime1:
serout 5,N2400_8,(254,128,"Hour: ",#b0)
if b1<10 then
serout 5,N2400_8,(254,192,"Min : 0",#b1)
elseif b1>9 then
serout 5,N2400_8,(254,192,"Min : ",#b1)
endif
if b2=0 then
serout 5,N2400_8,(254,143,60)
serout 5,N2400_8,(254,207," ")
elseif b2=1 then
serout 5,N2400_8,(254,207,60)
serout 5,N2400_8,(254,143," ")
endif
if up=1 and b2=0 then
let b0=b0+1 max 23 min 0
elseif up=1 and b2=1 then
let b1=b1+1 max 59 min 0
elseif dwn=1 and b2=0 then
let b0=b0-1 min 0 max 23
elseif dwn=1 and b2=1 then
let b1=b1-1 max 50 min 0
elseif nxt=1 then
let b2=b2-1 min 0 max 1
elseif pgm=1 then
goto pgmday
endif
goto pgmtime1
pgmday:
pause 3000
serout 5,N2400_8,(254,1)
let b3=1
pgmday1:
serout 5,N2400_8,(254,128,"Day ")
gosub testday
if up=1 then
let b3=b3+1 max 7 min 1
elseif dwn=1 then
let b3=b3-1 max 7 min 1
elseif pgm=1 then
goto settime
endif
goto pgmday1
settime:
serout 5,N2400_8,(254,128," Setting Time... ")
let b4=b1/10*16 'Converts b4 from dec to bcd
let b4=b1//10 | b4 'to write to the DS1307
let b5=b0/10*16 'Converts b5 from dec to bcd
let b5=b0//10 | b5 'to write to the DS1307
let b6=b3/10*16 'Converts b6 from dec to bcd
let b6=b3//10 | b6 'to write to the DS1307
writei2c 0,($00,b4,b5,b6,$08,$11,$07,$10) 'writes time and day to DS1307
pause 2000
goto set
Programming
End-user programming is simple.

This is the screen seen during normal operation. It displays the current time and day. From this screen the user can enter programming mode.
To do so, simply hold the PGM button down for 2 seconds. This will take you to the programming screens.

From the programming screen, you have the option of setting the timer schedule or setting the day and time.
To set the timer schedule, depress the UP button.
To set the day and time, depress the DWN button.

The next screen offers the option to program either the weekday or weekend schedule.
To set the weekday schedule, depress the UP button.
To set the weekend schedule, depress the DWN button.

This screen lets the user set the hours to turn the appliance on and off for the 1st phase.
Press the UP or DWN buttons to change the hour.
Press the NXT button to change between start and stop hours.
Press the PGM button to set these hours and move to the next step.

This screen lets the user set the hours to turn the appliance on and off for the 2nd phase. If no 2nd phase of control is wanted, set the start and stop hours of this phase to 24.
Press the UP or DWN buttons to change the hour.
Press the NXT button to change between start and stop hours.
Press the PGM button to set these hours and move to the next step.

After both phases are set, the user is returned to the Wkday/Wkend screen. Programming the weekend phase is done the same way as the weekday phase.
Once all weekday and weekend phases are set, press the NXT button at this screen t return to normal operation.

Now we will set the time and day.
Depress the DWN button to set the time and day.

The next screen allows the user to set the time.
Press the UP or DWN buttons to change the hour.
Press the NXT button to change between hour and min.
Press the PGM button to set these hours and move to the next step.

This screen allows the user to set the day.
Press the UP or DWN buttons to change the hour.
Press the PGM button to set the day and commit the time and day to memory.

This screen assures the user the time and day were set. It should be vsible for two seconds then the programming screen should return.

The programming screen will reappear after setting the time and day.
Press the NXT button to return to normal operation.
Programming the timer is done. Its quick and straightforward.
Conclusion
The project is simple. The code is simple. With more code, it can be adapted to be able to schedule for individual days of the week or even individual days of the year. For my purposes, it will be used on an electric water heater. With my schedule it will cut my water heater operation by 13 hours/day during the week and 7 hours/day on the weekends. This alone should cut water heater energy usage, combined with a solar water heating system however should dramatically cut energy usage.