PICAXE
This a a project with PICAXE I did in my Introduction to Engineering class in May 2015. PICAXE is a PIC micro-controller similar to Arduino, except that the CPU has less capability, is less expensive, and its programming language is BASIC rather than C++. You can read more about PICAXE here. The project we choose was to make an alarm clock. This alarm clock was unconventional because the PICAXE (Model: 08M2) we were working with didn't have enough inputs/outputs to control a display, a keypad, and a speaker. Since the main requirement was to be able to set the time, we opted to forgo a speaker and instead have the display show the text "WAKE UP!!!" when the alarm went off. An alarm clock that makes no noise, defeats the purpose of having an alarm clock. Therefore, a functional alarm clock would require PICAXE chip with more capability. Another issue was a limit on the number of variables we could use (maximum of 28) which meant we weren't able to have an option to make the alarm active or not. Meaning that the alarm would always go off when the time reached the time the alarm was set at. Having access to a higher end PICAXE chip would have alleviated the problem of not enough outputs and variables and allowed the alarm clock to be more functional. What I enjoyed most about this project was that it was an opportunity to integrate software and hardware and it was fun in spite of the limitations.
There are four different displays possible on this application: a display showing the current time, alarm setting, and temperature in degrees Fahrenheit; a display for setting the time; a display for setting the alarm time; and a display for when the alarm goes off. The keypad controls the alarm clock
Caution: Dear students, please consult your instructor before attempting to reuse any of the code on this site. Don't risk failing your course or worse!
Main display: Shows time (1:03:08 AM), alarm setting ( 0:0:0 AM), and temperature (77 degrees Fahrenheit).
Key pad detail: The picture above shows how the keypad it set up to change the clock settings. To set the time, press the "A" key, increase or decrease the hour (keys "1" & "4"), minute (keys "2" & "5"), second (keys "3" & "6"), and then press the "#" key to save and exit. To exit without saving, press the "*" key. Setting the alarm works in a similar fashion by pressing the "B" key. To shut off the alarm after it has gone off, press the "D" key.
"Set Time" splash screen
Time set screen
"Set Alarm" splash screen
Alarm set screen
Back to the main screen with the time at: 1:07:33 AM and the alarm set to go off at 1:08:00 AM (i.e. in 27 seconds)
The alarm "goes off". Unfortunately, due to the limitations of this PICAXE model, we didn't have enough outputs to also have it make a noise with the attached speaker because all the available inputs/outputs were taken up with the keypad and display. Working with a higher end PICAXE model would have alleviated that problem. Pressing the "D" key will shut off the alarm and go back to the main display.
PICAXE code:
'*********** Team Three project prototype
'*********** Alarm Clock
'Students: Please consult your instructor before attempting to reuse this code
'Members:
'Athena Roberts: Programmer
'Liviu Stepan: Hardware
'Samantha Lanoue
'Nadine Callaway
'Cody Snidecor
'
' Symbols for program storage
symbol seconds = b0
symbol mins = b1
symbol hour = b2
symbol day = b3
symbol date = b4
symbol month = b5
symbol year = b6
symbol control = b7
symbol temp = b8
symbol trash = b9
symbol hour_digit_1 = b10
symbol hour_digit_2 = b11
symbol min_digit_1 = b12
symbol min_digit_2 = b13
symbol sec_digit_1 = b14
symbol sec_digit_2 = b15
symbol a_hour_digit_1 = b16
symbol a_hour_digit_2 = b17
symbol a_min_digit_1 = b18
symbol a_min_digit_2 = b19
symbol a_sec_digit_1 = b20
symbol a_sec_digit_2 = b21
symbol temp_digit_1 = b22
symbol temp_digit_2 = b23
symbol key_pressed = b24
symbol a_hour = b25
symbol a_mins = b26
symbol a_seconds = b27
' Symbols for inputs or outputs
symbol tsensor = C.4
' Symbols for using LCD/keypad matrix and TinyRTC device
symbol small_pause = 20
symbol big_pause = 1000
symbol Backlight = 0x03 'follow with one byte for level 0-250
symbol Contrast = 0x04 'follow with one byte for level 0-100
symbol Set_pos = 0x0C 'follow with two bytes for row, col
symbol Home_cursor = 0x0D
symbol Clear_screen = 0x14
symbol Print_string = 0x15
symbol Keypad_mode = 0x31 'follow with 0 for 4X4 matrix, 1 for 8 separate switches to ground
symbol Keypad_read = 0x32 'returns 1 byte, number from 1-16 else 0 if no key pressed
symbol LCD_address = 0x98
symbol Command_pre = 0xFE
symbol DS1307 = 0xD0
' Symbol used for BCD to binary conversion
Symbol MINUS_6 = $FFFA ' -6 = 0 - 6 & $FFFF
' set DS1307 slave address, as described in the chip's technical documentation PDF
' note that binary values (digits 0 and 1 only) have percent sign prefixes in PICAXE Basic
' initialise the clock - "Mon 2015-04-14 22:00:00" all as BCD (binary coded decimal)
' note that hexidecimal values (base 16, digits 0-9 plus letters A-F) have dollar sign prefix
day = $03 '$00 = Monday, $01 = Tuesday through $06 = Sunday
year = $15 '$00 = 2000, $11 = 2011, etc.
month = $04 '$01 = January, $02 = February through $12 = December
date = $30 '$01 = first day of the month through $30 or $31 (as applicable per month)
hour = $01 '$00 = midnight through $23 = 11 pm
mins = $01 '$00 through $59 = minutes of the current hour
seconds = $00 '$00 through $59 = seconds of the current minute
control = %00010000 'the 1 enables a pulse output at 1Hz (heartbeat LED) - see PDF docs
' set I2C to talk to TinyRTC
i2cslave DS1307, i2cslow, i2cbyte
' set clock (do this the first time you run the program only)
writei2c 0,(seconds,mins,hour,day,date,month,year,control)
' set default alarm time
a_hour = $00
a_mins = $00
a_seconds = $00
' following lines clear the LCD screen, set backlight, and set contrast
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Backlight,200)
pause small_pause
hi2cout (Command_pre,Contrast,10)
pause small_pause
'
main:
' debug
' Test if time is equal to alarm time
if a_hour = hour AND a_mins = mins AND a_seconds = seconds then
gosub AlarmSound ' goto alarming sound routine
endif
'read keypad
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Keypad_read)
pause small_pause
hi2cin (key_pressed)
pause small_pause
' read the clock and then the temp sensor
i2cslave DS1307, i2cslow, i2cbyte
readi2c 0,(seconds,mins,hour,day,date,month,year)
readtemp tsensor, temp
temp = temp * 9/5 + 32 'convert temp from Celsius to Fahrenheit
' convert BCD values read from real time clock to decimal values that can be displayed
gosub convert
' dump date, time, and temperature to serial port
' serout 0,n4800,("Date: ",#month,"/",#date,"/",#year," Time: ",#hour,":",#mins,":",#seconds," - temp F: ",#temp,13,10)
' get ready to write to the LCD
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Home_cursor)
pause small_pause
' bintoascii statements needed because data is stored in PICAXE memory as binary (after BCD conversion) and LCD display requires ASCII
bintoascii hour,trash,hour_digit_1,hour_digit_2
bintoascii mins,trash,min_digit_1,min_digit_2
bintoascii seconds,trash,sec_digit_1,sec_digit_2
bintoascii a_hour,trash,a_hour_digit_1,a_hour_digit_2
bintoascii a_mins,trash,a_min_digit_1,a_min_digit_2
bintoascii a_seconds,trash,a_sec_digit_1,a_sec_digit_2
bintoascii temp,trash,temp_digit_1,temp_digit_2
'decide what to do based on key pressed
select case key_pressed
case 0 'if no key pressed, display time and alarm time
hi2cout (Command_pre,Print_string," T:",hour_digit_1,hour_digit_2,":",min_digit_1,min_digit_2,":",sec_digit_1,sec_digit_2," ")
pause small_pause
hi2cout (Command_pre,Set_pos,00,05)
pause small_pause
hi2cout (Command_pre,Print_string," A:",a_hour_digit_1,a_hour_digit_2,":",a_min_digit_1,a_min_digit_2,":",a_sec_digit_1,a_sec_digit_2," ",temp_digit_1,temp_digit_2,"F")
pause small_pause
case 4 'Goto SetTime subroutine
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Set Time ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
'read the clock
i2cslave DS1307, i2cslow, i2cbyte
readi2c 0,(seconds,mins,hour,day,date,month,year)
gosub convert
gosub SetTime
case 8 'Goto SetAlarm subroutine
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Set Alarm ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
bintoascii a_hour,trash,a_hour_digit_1,a_hour_digit_2
bintoascii a_mins,trash,a_min_digit_1,a_min_digit_2
bintoascii a_seconds,trash,a_sec_digit_1,a_sec_digit_2
gosub SetAlarm
else 'Suggest pressing a different key
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Try pressing ")
pause small_pause
hi2cout (Command_pre,Set_pos,00,05)
pause small_pause
hi2cout (Command_pre,Print_string," another key :-) ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
endselect
goto main 'there is no end - loop till powered off
'
convert: 'this is a subroutine that handles changing the BCD stored values into decimal so they are human readable
seconds = seconds / 16 * MINUS_6 + seconds
mins = mins / 16 * MINUS_6 + mins
hour = hour / 16 * MINUS_6 + hour
date = date / 16 * MINUS_6 + date
month = month / 16 * MINUS_6 + month
year = year / 16 * MINUS_6 + year
return
unconvert: 'convert binary back to BCD
seconds = seconds / 10 * 6 + seconds
mins = mins / 10 * 6 + mins
hour = hour / 10 * 6 + hour
date = date / 10 * 6 + date
month = month / 10 * 6 + month
year = year / 10 * 6 + year
return
SetTime: 'Set time on alarm clock
' debug
'read keypad
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Keypad_read)
pause small_pause
hi2cin (key_pressed)
pause small_pause
hi2cout (Command_pre,Home_cursor)
pause small_pause
select case key_pressed
case 0 ' Display current setting if no key pressed
hi2cout (Command_pre,Print_string," T:",hour_digit_1,hour_digit_2,":",min_digit_1,min_digit_2,":",sec_digit_1,sec_digit_2," ")
pause small_pause
hi2cout (Command_pre,Set_pos,00,05)
pause small_pause
hi2cout (Command_pre,Print_string," *:Exit #:Save")
pause small_pause
case 1 ' increase hour by one
hour = hour + 1
if hour > 23 then '23
hour = 24 - hour '24
endif
bintoascii hour,trash,hour_digit_1,hour_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 2 ' increase minute by one
mins = mins + 1
if mins > 59 then
mins = 60 - mins
endif
bintoascii mins,trash,min_digit_1,min_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 3 ' increase seconds by one
seconds = seconds + 1
if seconds > 59 then
seconds = 60 - seconds
endif
bintoascii seconds,trash,sec_digit_1,sec_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 5 ' decrease hour by one
if hour = 0 then
hour = 23
else
hour = hour - 1
endif
bintoascii hour,trash,hour_digit_1,hour_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 6 ' decrease minutes by one
if mins = 0 then
mins = 59
else
mins = mins - 1
endif
bintoascii mins,trash,min_digit_1,min_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 7 ' decrease seconds by one
if seconds = 0 then
seconds = 59
else
seconds = seconds - 1
endif
bintoascii seconds,trash,sec_digit_1,sec_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 13 ' exit SetTime subroutine
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Exiting... ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
return
case 15 ' save time to clock
gosub unconvert
i2cslave DS1307, i2cslow, i2cbyte
writei2c 0,(seconds,mins,hour,day,date,month,year,control)
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Time saved ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
return
' else 'Suggest pressing a different key
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
' hi2cout (Command_pre,Print_string," Try pressing ")
' pause small_pause
' hi2cout (Command_pre,Set_pos,00,05)
' pause small_pause
' hi2cout (Command_pre,Print_string," another key :-) ")
' pause big_pause
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
end select
goto SetTime
SetAlarm:'Set alarm time. Would also be nice to be able to activate and unactivate alarm. That requires more variables. Use "w" variables?
'read keypad
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Keypad_read)
pause small_pause
hi2cin (key_pressed)
pause small_pause
hi2cout (Command_pre,Home_cursor)
pause small_pause
select case key_pressed
case 0 ' Display current setting if no key pressed
hi2cout (Command_pre,Print_string," A:",a_hour_digit_1,a_hour_digit_2,":",a_min_digit_1,a_min_digit_2,":",a_sec_digit_1,a_sec_digit_2," ")
pause small_pause
hi2cout (Command_pre,Set_pos,00,05)
pause small_pause
hi2cout (Command_pre,Print_string," *:Exit #:Save")
pause small_pause
case 1 ' increase hour by one
a_hour = a_hour + 1
if a_hour > 23 then '23
a_hour = 24 - a_hour '24
endif
bintoascii a_hour,trash,a_hour_digit_1,a_hour_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 2 ' increase minute by one
a_mins = a_mins + 1
if a_mins > 59 then
a_mins = 60 - a_mins
endif
bintoascii a_mins,trash,a_min_digit_1,a_min_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 3 ' increase seconds by one
a_seconds = a_seconds + 1
if a_seconds > 59 then
a_seconds = 60 - a_seconds
endif
bintoascii a_seconds,trash,a_sec_digit_1,a_sec_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 5 ' decrease hour by one
if a_hour = 0 then
a_hour = 23
else
a_hour = a_hour - 1
endif
bintoascii a_hour,trash,a_hour_digit_1,a_hour_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 6 ' decrease minutes by one
if a_mins = 0 then
a_mins = 59
else
a_mins = a_mins - 1
endif
bintoascii a_mins,trash,a_min_digit_1,a_min_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
case 7 ' decrease seconds by one
if a_seconds = 0 then
a_seconds = 59
else
a_seconds = a_seconds - 1
endif
bintoascii a_seconds,trash,a_sec_digit_1,a_sec_digit_2
' hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
' case 13 ' unactivate alarm
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
' hi2cout (Command_pre,Print_string," Alarm Unactive ")
' pause big_pause
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
' return
case 15 ' activate alarm
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Clear_screen)
pause small_pause
hi2cout (Command_pre,Print_string," Alarm Active ")
pause big_pause
hi2cout (Command_pre,Clear_screen)
pause small_pause
return
' else 'Suggest pressing a different key
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
' hi2cout (Command_pre,Print_string," Try pressing ")
' pause small_pause
' hi2cout (Command_pre,Set_pos,00,05)
' pause small_pause
' hi2cout (Command_pre,Print_string," another key :-) ")
' pause big_pause
' hi2cout (Command_pre,Clear_screen)
' pause small_pause
end select
goto SetAlarm
AlarmSound: 'sound the alarm
hi2csetup i2cmaster, LCD_address, i2cslow, i2cbyte
hi2cout (Command_pre,Keypad_read)
pause small_pause
hi2cin (key_pressed)
pause small_pause
hi2cout (Command_pre,Home_cursor)
pause small_pause
select case key_pressed
case 16
hi2cout (Command_pre,Print_string," Alarm shutoff ")
pause big_pause
' hi2cout (Command_pre,Set_pos,00,05)
' pause small_pause
' hi2cout (Command_pre,Print_string," *:Exit #:Save")
' pause small_pause
return
else
hi2cout (Command_pre,Clear_screen)
pause big_pause
hi2cout (Command_pre,Print_string," WAKE UP!!!!! ")
pause big_pause
' hi2cout (Command_pre,Set_pos,00,05)
' pause small_pause
' hi2cout (Command_pre,Print_string," WAKE UP!!!!! ")
' pause small_pause
end select
goto AlarmSound
'SetDate: 'If we have time and enough memory
'
'
'
'goto SetDate
Caution: Dear students, please consult your instructor before attempting to reuse any of the code on this site. Don't risk failing your course or worse!
Copyright 2015 Athena Roberts