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.