Home‎ > ‎Education‎ > ‎Physics & Engineering‎ > ‎

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 a 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

 

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

'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





Comments