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