Shop OBEX P1 Docs P2 Docs Learn Events
Basic Stamp 2 (BS2) RTC DS1302 & Temp DS1620 on an LCD, Buttons and Alarm — Parallax Forums

Basic Stamp 2 (BS2) RTC DS1302 & Temp DS1620 on an LCD, Buttons and Alarm

T&E EngineerT&E Engineer Posts: 1,396
edited 2008-09-05 22:54 in Robotics
To my surprise there was no Basic Stamp 2 method to display both date/time and temperature on an LCD and control it with buttons. With DEBUG, yes but buttons no. I built something similar sometime back using a BS2 and an SX Video Module (Hitt Consulting - Bean) using only a DS1302 RTC and buttons.

http://forums.parallax.com/showthread.php?p=553426

I also did something similar using an SX-28 and an LCD with a DS1302 RTC and buttons.

http://forums.parallax.com/showthread.php?p=643780

However, there was nothing I could find for the BS2 that used an LCD, buttons, DS1302 RTC and a DS1620 Temperature IC as well as having an alarm mode. So I saw the need in the forums and decided to meet the need on some level.

The code is pretty much self explainatory with comments. I am not a programmer by trade just hobby so there are probably better ways to do this - but I used what I could find and modified it to get it to work.

It does use 8 buttons (I used the professional development board by Parallax).

The temp is displayed in Celsius or Fahrenheit but I suggest commenting out either of the tempC or tempF WORD to free up a word. If you use both, there is only a "bit" of variable space left. So it is good to comment one out.

The code you have seen before as it is a compilation of other DS1302, DS1620 and other programs combined to get it to work together.

There is also only 1 available BS2 pin left as well as having 1 bit to 1 word left.

The LCD displays (but you can change it to what you want):

Su 06:00:00A xxC· (xx is the temperature)
12:00PM 12/31/08

One last question that I am not sure about is I thought I remember reading that you must set the Date (eg. Sunday, Monday, etc..) because it affects the year 2 digit code. The DS1302 has an algorythm that uses this Date to figure out if the year is actually 2008, or 1908, 1808 (based on if the year 2 digits are 08). I think this is correct so I have a button for setting the Date. The top line is very tight on data displayed so the Date is only 2 characters (e.g. Su, Mo, Tu, etc..)

Another thing is that the Alarm time (2nd line) is·set by holding down Button6 and Button0 (for minutes forward) or Button1 (for Hours forward). I did not utilize the Backward button (Button7) as this would be too many buttons to·press or hold.

Comments?

PS: I found a small bug in the alarm setting and fixed it (6/29/08)

[size=2][code]
' ==============================================================================
'
'   File...... DS1302_DS1620_LCD_8BTN.BS2
'   Purpose... RTC Control
'   Author.... Tim Gilmore
'   E-mail.... [url=mailto:gilmoret@us.saic.com]gilmoret@us.saic.com[/url]
'   Started... 27 June 2008
'   Updated... 29 June 2008
'
'   {$STAMP BS2}
'   {$PBASIC 2.5}
'
'
' ==============================================================================

' ------------------------------------------------------------------------------
' Program Description
' ------------------------------------------------------------------------------
' This program demonstrates the control and use of an external real-time clock
' chip, the DS1302 and a real-time temperature chip, the DS1620 both from Dallas Semiconductor.
'
' It has 8 buttons tied high with 10K resistors. The other side of the button goes to ground.
' Also recommend a 220 ohm resistor between each BUTTON BIN AND each BUTTON.
'
'                                     5 vdc
'                                       ^
'                                       |
'                                       |
'                                   (10K ohm)
'                                       |
'                                       |   --|--
'   BS2 Pin (x) <--(220 ohm resistor)-------o   o--|
'                                                  |
'                                                -----
'   (Repeat for all 8 switch assemblies)          ---
'      (x is a BS2 Pin from 8 to 15)               -
'

' Pin Assignments
' 0   DS1302 DataIO
' 1   DS1302 Clock
' 2   DS1302 Chip Select
' 3   Parallax Serial LCD RX Line
'
' 4   DS1620 DQ (use a 1K resistor between DQ {DS1620) and pin 4 (BS2))
' 5   DS1620 Clock2
' 6   DS1620 Reset
' 7   ???
' 8   Button 0
' 9   Button 1
' 10  Button 2
' 11  Button 3
' 12  Button 4
' 13  Button 5
' 14  Button 6
' 15  Button 7
'
'  BE SURE TO "RESET" THE BASIC STAMP 2 CIRCUIT AFTER POWER UP.
' ------------------------------------------------------------------------------
' I/O Definitions
' ------------------------------------------------------------------------------
DataIO          CON     0                       ' DS1302.6
Clock           CON     1                       ' DS1302.7
CS1302          CON     2                       ' DS1302.5
LCD             CON     3                       ' Parallax Serial LCD Display  (Rx line)
DQ              CON     4                       ' DS1620.1 (data I/O)
Clock2          CON     5                       ' DS1620.2
Reset           CON     6                       ' DS1620.3
BtnsIn          VAR     INH                     ' button input (pins 8 - 15)

' ------------------------------------------------------------------------------
' Constants
' ------------------------------------------------------------------------------
WrSecs          CON     $80                     ' write seconds
RdSecs          CON     $81                     ' read seconds
WrMins          CON     $82                     ' write minutes
RdMins          CON     $83                     ' read minutes
WrHrs           CON     $84                     ' write hours
RdHrs           CON     $85                     ' read hours
CWPr            CON     $8E                     ' write protect register
WPr1            CON     $80                     ' set write protect
WPr0            CON     $00                     ' clear write protect
WrBurst         CON     $BE                     ' write burst of data
RdBurst         CON     $BF                     ' read burst of data
WrRam           CON     $C0                     ' RAM address control
RdRam           CON     $C1
Yes             CON     1
No              CON     0
Hr24            CON     0
Hr12            CON     1
ClockMode       CON     Hr12            ' use AM/PM mode

Baud            CON     32              ' 19K2 bps
LcdBkSpc        CON     $08             ' move cursor left
LcdRt           CON     $09             ' move cursor right
LcdLF           CON     $0A             ' move cursor down 1 line
LcdCls          CON     $0C             ' clear LCD (use PAUSE 5 after)
LcdCR           CON     $0D             ' move pos 0 of next line
LcdBLon         CON     $11             ' backlight on
LcdBLoff        CON     $12             ' backlight off
LcdOff          CON     $15             ' LCD off
LcdOn1          CON     $16             ' LCD on; cursor off, blink off
LcdOn2          CON     $17             ' LCD on; cursor off, blink on
LcdOn3          CON     $18             ' LCD on; cursor on, blink off
LcdOn4          CON     $19             ' LCD on; cursor on, blink on
LcdLine1        CON     $80             ' move to line 1, column 0
LcdLine2        CON     $94             ' move to line 2, column 0
LcdCC0          CON     $F8             ' define custom char 0
LcdCC1          CON     $F9             ' define custom char 1
LcdCC2          CON     $FA             ' define custom char 2
LcdCC3          CON     $FB             ' define custom char 3
LcdCC4          CON     $FC             ' define custom char 4
LcdCC5          CON     $FD             ' define custom char 5
LcdCC6          CON     $FE             ' define custom char 6
LcdCC7          CON     $FF             ' define custom char 7

RdTmp           CON     $AA                     ' read temperature
WrHi            CON     $01                     ' write TH (high temp)
WrLo            CON     $02                     ' write TL (low temp)
RdHi            CON     $A1                     ' read TH
RdLo            CON     $A2                     ' read TL
StartC          CON     $EE                     ' start conversion
StopC           CON     $22                     ' stop conversion
WrCfg           CON     $0C                     ' write config register
RdCfg           CON     $AC                     ' read config register

' ------------------------------------------------------------------------------
' Variables
' ------------------------------------------------------------------------------
index           VAR     Byte                    ' loop counter
reg             VAR     Byte                    ' DS1302 address to read/write
ioByte          VAR     Byte                    ' data to/from DS1302
secs            VAR     Byte                    ' seconds
secs01          VAR     secs.LOWNIB
secs10          VAR     secs.HIGHNIB
mins            VAR     Byte                    ' minutes
mins01          VAR     mins.LOWNIB
mins10          VAR     mins.HIGHNIB
hrs             VAR     Byte                    ' hours
hrs01           VAR     hrs.LOWNIB
hrs10           VAR     hrs.HIGHNIB
 
day             VAR     Byte            '1 - 7 for Sunday through Saturday (Used for determining if the year is 2008 or 1908).
month           VAR     Byte
month01         VAR     month.LOWNIB
month10         VAR     month.HIGHNIB
date            VAR     Byte            ' Date (0 - 31)
date01          VAR     date.LOWNIB
date10          VAR     date.HIGHNIB
year            VAR     Byte            ' Year (00 - 99) - up to the year 2100 (or really 2099).
year01          VAR     year.LOWNIB
year10          VAR     year.HIGHNIB
ampm            VAR     hrs.BIT5                ' 0 = AM, 1 = PM
tMode           VAR     hrs.BIT7                ' 0 = 24, 1 = 12
rawTime         VAR     Word                    ' raw storage of time values
work            VAR     Byte                    ' work variable for display output
oldSecs         VAR     Byte                    ' previous seconds value
apChar          VAR     Byte                    ' "A" or "P"
ampmFlag        VAR     Bit                     ' 0 = AM, 1 = PM
btns            VAR     Byte
btnMin          VAR     btns.BIT0               ' update minutes
btnHrs          VAR     btns.BIT1               ' update hours
btnDay          VAR     btns.BIT2               ' update day
btnMonth        VAR     btns.BIT3               ' update month
btnDate         VAR     btns.BIT4               ' update date
btnYear         VAR     btns.BIT5               ' update year
btnAlarm        VAR     btns.BIT6               ' Set alarm
btnBack         VAR     btns.BIT7               ' go backward for everything except alarm.

mins_alarm      VAR     Byte
hrs_alarm       VAR     Byte
ampmflag_alarm  VAR     Bit
alarmbit_alarm  VAR     Bit

tempIn          VAR     Word                    ' raw temperature
sign            VAR     tempIn.BIT8             ' 1 = negative temperature
tSign           VAR     Bit
tempC           VAR     Word                    ' Celsius
'tempF           VAR     Word                    ' Fahrenheit
'
'Comment out tempF to free up a Word of variable space (if not using Fahrenheit)

idx             VAR     Byte
' ------------------------------------------------------------------------------
' EEPROM Data
' ------------------------------------------------------------------------------
Su              DATA    "Su ", 0
Mo              DATA    "Mo ", 0
Tu              DATA    "Tu ", 0
We              DATA    "We ", 0
Th              DATA    "Th ", 0
Fr              DATA    "Fr ", 0
Sa              DATA    "Sa ", 0

' ------------------------------------------------------------------------------
' Initialization
' ------------------------------------------------------------------------------
Initialize:
  DIRL = %00111111                              ' switches are ins, others outs
  DIRH = %00000000
  reg = CWPr                                    ' clear write protect register
  ioByte = WPr0
  GOSUB RTC_Out
  HIGH LCD                                      ' Setup Serial Output Pin
  SEROUT LCD, Baud, [noparse][[/noparse]LcdOn1, LcdBLon]           ' Turn LCD Display & Backlight On
  HIGH Reset                                    ' alert the DS1620
  SHIFTOUT DQ, Clock2, LSBFIRST, [noparse][[/noparse]WrCfg, %10]    ' use with CPU; free-run
  LOW Reset
  PAUSE 10
  HIGH Reset
  SHIFTOUT DQ, Clock2, LSBFIRST, [noparse][[/noparse]StartC]        ' start conversions
  LOW Reset
  alarmbit_alarm = 1

  oldSecs = $99                                 ' set the display flag
  hrs = $06                                     ' preset time to 6:00 AM
  month = $12
  date = $31
  year = $08
  mins_Alarm = 0
  hrs_Alarm = $12
  GOSUB Set_Time

' ------------------------------------------------------------------------------
' Program Code
' ------------------------------------------------------------------------------
Main1:
  IF 12 - (24 - (hrs10 * 10 + hrs01) // 12) = hrs_alarm THEN
      IF mins = mins_alarm THEN
        IF ampmflag = ampmflag_alarm THEN
          IF alarmbit_alarm = 1 THEN
            GOSUB Action_alarm
          ENDIF
        ENDIF
      ENDIF
    ENDIF
  GOSUB Get_Temperature                         ' read the DS1620
  GOSUB Get_Time                                ' read the DS1302
  IF (secs = oldSecs) THEN Check_Buttons        ' time for update?
Main2:
  GOSUB Show_Time                               ' yes, show it
  oldSecs = secs                                ' mark it
  IF alarmbit_alarm = 0 THEN
     alarmbit_alarm = 1
  ENDIF
Check_Buttons:
  GOSUB Get_Buttons
  IF (btns = 0) THEN Do_Some_Task               ' let Stamp do other work
  IF (btnAlarm=Yes) AND (btnMin=Yes) THEN AlarmSet
  IF (btnAlarm=Yes) AND (btnHrs=Yes) THEN AlarmSet
  IF (btnBack = Yes) THEN Go_Back               ' back button pressed?
Go_Forward:
  rawTime = rawTime + btnMin                    ' add one minute
  rawTime = rawTime + (btnHrs * 60)             ' add one hour
  day = (day + btnDay) // 7                    ' next day
  month = month + btnMonth
  IF month = $A THEN
    month = $10
  ELSEIF month > $12 THEN
    month = 1
  ENDIF
  date = date + btnDate
  IF date = $A THEN
   date = $10
  ELSEIF date = $1A THEN
   date = $20
  ELSEIF date = $2A THEN
   date = $30
  ELSEIF date > $31 THEN
   date = 1
  ENDIF
  year = year + btnYear
  IF year = $A THEN
   year = $10
  ELSEIF year = $1A THEN
   year = $20
  ELSEIF year = $2A THEN
   year = $30
  ELSEIF year = $3A THEN
   year = $40
  ELSEIF year = $4A THEN
   year = $50
  ELSEIF year = $5A THEN
   year = $60
  ELSEIF year = $6A THEN
   year = $70
  ELSEIF year = $7A THEN
   year = $80
  ELSEIF year = $8A THEN
   year = $90
  ELSEIF year > $99 THEN
   year = 0
  ENDIF

  GOTO Update_Clock
Go_Back:
  IF (btns <= %0000000) THEN Do_Some_Task          ' no update button pressed
  rawTime = rawTime + (btnMin * 1439)           ' subtract one minute
  rawTime = rawTime + (btnHrs * 1380)           ' subtract one hour
  day = (day + (btnDay * 6)) // 7               ' previous day
  month = month - btnMonth
  IF month = 0 THEN
    month = $12
  ELSEIF month = $F THEN
    month = $9
  ENDIF
  date = date - btnDate
  IF date = $2F THEN
    date = $29
  ELSEIF date = $1F THEN
    date = $19
  ELSEIF date = $F THEN
    date = $9
  ELSEIF date = 0 THEN
    date = $31
  ENDIF
  year = year - btnYear
  IF year = $9F THEN
    year = $99
  ELSEIF year = $8F THEN
    year = $89
  ELSEIF year = $7F THEN
    year = $79
  ELSEIF year = $6F THEN
    year = $69
  ELSEIF year = $5F THEN
    year = $59
  ELSEIF year = $4F THEN
    year = $49
  ELSEIF year = $3F THEN
    year = $39
  ELSEIF year = $2F THEN
    year = $29
  ELSEIF year = $1F THEN
    year = $19
  ELSEIF year = $F THEN
    year = $9
  ELSEIF year = $FF THEN
    year = $99
  ENDIF
  GOTO Update_Clock
AlarmSet:
  mins_Alarm = mins_Alarm + btnMin
  IF mins_alarm = $A THEN
   mins_alarm = $10
  ELSEIF mins_alarm = $1A THEN
   mins_alarm = $20
  ELSEIF mins_alarm = $2A THEN
   mins_alarm = $30
  ELSEIF mins_alarm = $3A THEN
   mins_alarm = $40
  ELSEIF mins_alarm = $4A THEN
   mins_alarm = $50
  ELSEIF mins_alarm = $5A THEN
   mins_alarm = 0
  ENDIF
  hrs_Alarm = hrs_Alarm + btnHrs
  IF hrs_alarm = $A THEN
    hrs_alarm = $10
  ELSEIF (ampmFlag_alarm = 0) AND (hrs_alarm > $12) THEN
    hrs_alarm = 1
    ampmFlag_alarm = 1
  ELSEIF (ampmFlag_alarm = 1) AND (hrs_alarm > $12) THEN
    hrs_alarm = 1
    ampmFlag_alarm = 0
  ENDIF

Update_Clock:                                   ' send updated value to DS1302
  rawTime = rawTime // 1440                     ' clean-up time mods
  GOSUB Set_Raw_Time                            ' set the clock with rawTime
  GOTO Main2
Do_Some_Task:                                   ' work when not setting clock
  ' other code here
  GOTO Main1

' ------------------------------------------------------------------------------
' Subroutines
' ------------------------------------------------------------------------------
Action_alarm:
'Do any alarm actions here (for example:)
'
' DO something while the time is waiting to clear (< 1 minute)
  FOR idx = 1 TO 3
   SEROUT LCD, Baud, [noparse][[/noparse]LcdCls]            ' Clear The LCD Display
   PAUSE 1000
   SEROUT LCD, Baud, [noparse][[/noparse]"ALARM ", HEX2 hrs_alarm, ":", HEX2 mins_alarm]
   IF ampmFlag_alarm = 0 THEN
      SEROUT LCD, Baud, [noparse][[/noparse]"AM", LcdCR]
    ELSE
      SEROUT LCD, Baud, [noparse][[/noparse]"PM", LcdCR]
    ENDIF
   SEROUT LCD, Baud, [noparse][[/noparse]"Take Action"]
   PAUSE 2000
  NEXT
  alarmbit_alarm = 0
RETURN

Show_Time:
  'DEBUG HOME
  LOOKUP day,[noparse][[/noparse]Su,Mo,Tu,We,Th,Fr,Sa],work        ' get address of day string
  SEROUT LCD, Baud, [noparse][[/noparse]LcdLine1]          ' LCD Home Position
Get_Day_Char:
  READ work, ioByte                             ' grab a character
  IF (ioByte = 0) THEN Check_Clock_Mode         ' if 0, string is complete
 'DEBUG ioByte                                  ' print the character
  SEROUT LCD, Baud, [noparse][[/noparse]ioByte]
  work = work + 1                               ' point to next
  GOTO Get_Day_Char
Check_Clock_Mode:
  'DEBUG "     ", CR                             ' clear day name debris
'  SEROUT LCD, Baud, [noparse][[/noparse]" ", CR]
  IF (ClockMode = Hr24) THEN Show24
Show12:
  SEROUT LCD, Baud, [noparse][[/noparse]DEC2 12 - (24 - (hrs10 * 10 + hrs01) // 12)]
  SEROUT LCD, Baud, [noparse][[/noparse]":", HEX2 mins, ":", HEX2 secs]
  ampmFlag = 0
  apChar = "A"                                  ' assume AM
  IF (hrs < $12) THEN Show_AMPM                 ' check time
  ampmFlag = 1
  apChar = "P"                                  ' hrs was >= $12
Show_AMPM:
  'SEROUT LCD, Baud, [noparse][[/noparse]apChar, "M"]               ' Un-comment to show the "M" on the display
   SEROUT LCD, Baud, [noparse][[/noparse]apChar, " "]
  GOTO Show_Time_Done
Show24:
  SEROUT LCD, Baud, [noparse][[/noparse]HEX2 hrs, ":", HEX2 mins, ":", HEX2 secs]
Show_Time_Done:
    SEROUT LCD, Baud, [noparse][[/noparse]SDEC tempC, "C"]
  SEROUT LCD, Baud, [noparse][[/noparse]HEX2 hrs_alarm, ":", HEX2 mins_alarm]
  IF ampmFlag_alarm = 0 THEN
      SEROUT LCD, Baud, [noparse][[/noparse]"AM"]
    ELSE
      SEROUT LCD, Baud, [noparse][[/noparse]"PM"]
    ENDIF
   SEROUT LCD, Baud, [noparse][[/noparse]" ", HEX2 month, "/", HEX2 date, "/", HEX2 year]
  RETURN

Get_Buttons:
  btns = %11111111                                  ' enable all button inputs
  FOR index = 1 TO 10
    btns = btns & ~BtnsIn                       ' test inputs
    PAUSE 5                                             ' delay between tests
  NEXT
  PAUSE 200                                     ' slow held button(s)
  RETURN

RTC_Out:                                        ' send ioByte to reg in DS1302
  HIGH CS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [noparse][[/noparse]reg, ioByte]
  LOW CS1302
  RETURN

RTC_In:                                         ' read ioByte from reg in DS1302
  HIGH CS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [noparse][[/noparse]reg]
  SHIFTIN DataIO, Clock, LSBPRE, [noparse][[/noparse]ioByte]
  LOW CS1302
  RETURN

Set_Raw_Time:                                   ' convert rawTime to BCD
  hrs10 = rawTime / 600
  hrs01 = (rawTime // 600) / 60
  mins10 = (rawTime // 60) / 10
  mins01 = rawTime // 10
Set_Time:                               ' DS1302 Burst Write
  HIGH CS1302                           ' Select DS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [noparse][[/noparse]WrBurst]
  SHIFTOUT DataIO, Clock, LSBFIRST, [noparse][[/noparse]secs, mins, hrs, date, month, day, year, 0]
  LOW CS1302                            ' Deselect DS1302
  RETURN
Get_Time:                                       ' read data with burst mode
  HIGH CS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [noparse][[/noparse]RdBurst]
  SHIFTIN DataIO, Clock, LSBPRE, [noparse][[/noparse]secs, mins, hrs, date, month, day, year, idx]
  LOW CS1302
  rawTime = ((hrs10 & %11) * 600) + (hrs01 * 60)
  rawTime = rawTime + (mins10 * 10) + mins01
  RETURN

Get_Temperature:
  HIGH Reset                                    ' alert the DS1620
  SHIFTOUT DQ, Clock2, LSBFIRST, [noparse][[/noparse]RdTmp]         ' give command to read temp
  SHIFTIN DQ, Clock2, LSBPRE, [noparse][[/noparse]tempIn\9]         ' read it in
  LOW Reset                                     ' release the DS1620
  tSign = sign                                  ' save sign bit
  tempIn = tempIn / 2                           ' round to whole degrees
  IF (tSign = 0) THEN No_Neg1
  tempIn = tempIn | $FF00                       ' extend sign bits for negative
No_Neg1:
  tempC = tempIn                                ' save Celsius value
  tempIn = tempIn */ $01CC                      ' multiply by 1.8
  IF (tSign = 0) THEN No_Neg2                   ' if negative, extend sign bits
  tempIn = tempIn | $FF00
No_Neg2:
  tempIn = tempIn + 32                          ' finish C -> F conversion
  'tempF = tempIn                                ' save Fahrenheit value
  RETURN


[/code][/size]
Post Edited (T&E Engineer) : 6/29/2008 4:20:17 AM GMT

Comments

Sign In or Register to comment.