' =========================================================================
'
'   File...... EnvironmentalControllerBETA02.BS2
'   Purpose... First Beta version of controller code
'   Author.... Brann Fenix
'   E-mail.... BrannFenix@gmail.com
'   Started... 08-26-2006
'   Updated...
'
'   Notes:
'   Parts of code used in this file are from the following files and authors:
'   =========================================================================
'   DS1302_Template.BS2                                 By Chris Savage -- Parallax, INC
'   SHT1x.BS2                                           By Jon Williams -- Parallax, INC
'   Various Examples from the Applied Sensors Book      By Tracy Allen  -- www.emesystems.com
'
'
'
'   {$STAMP BS2}
'   {$PBASIC 2.5}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------
'
' This code when finished will read and log the output of the following sensors:
' I.   Sensirion Temperature/Humidity Sensor SHT1x for Air Temp/Humidity
' II.  AD592 Temperature Probe for Water Temps.
' III. ????
'
' The code will also make use of a DS1302 for time keeping and as the
' base of a full service scheduler that will be able to control relays connected
' to 120v house hold items such as heats, chillers, pumps, ect.
'
' The code will also allow the user to define settings for environmental items
' such as water temp.  The device will then use data from sensors and relays
' connected to heaters and chillers to raise and lower the water temp in order
' to keep it in the defined setting.  Depending on the sensors and what the relays
' are controlling this code will be able to keep almost anything at a pre-defined
' range for as long as need.
'
'TO DO:
' a. [] Figure out a better way to have the scheduler work without hard coding the event triggers and reactions.
' b. [] ADD TODO HERE!
' c. [] ADD TODO HERE!
' d. [] ADD TODO HERE!
'
'
'
' More info on this project can be found in this thread on the Parallax forum:
' http://forums.parallax.com/forums/default.aspx?f=5&p=1&m=140311
'
'
'
'
' -----[ Revision History ]------------------------------------------------



' -----[ I/O Definitions ]-------------------------------------------------

DataIO          PIN     0               ' Send/Receive Data @ DS1302.6/SHT1x.1
Clock           PIN     1               ' Serial Clock      @ DS1302.7/SHT1x.3
DS1302RST       PIN     2               ' RESET Pin         @ DS1302.5
AD592           PIN     3
' -----[ Constants ]-------------------------------------------------------


RdBurst         CON     $BF             ' Read Burst Of Data from DS1302
Hr24            CON     0               ' 24 Hour Mode for DS1302
Hr12            CON     1               ' 12 Hour Mode for DS1302

ShtTemp         CON     %00011          ' Read Temperature for SHT1x
ShtHumi         CON     %00101          ' Read Humidity for SHT1x
ShtStatW        CON     %00110          ' Status Register Write for SHT1x
ShtStatR        CON     %00111          ' Status Register Read for SHT1x
ShtReset        CON     %11110          ' Soft Reset (Wait 11 ms After) for SHT1x
Ack             CON     0               ' For SHT1x ??
NoAck           CON     1               ' For SHT1x ??
No              CON     0               ' For SHT1x ??
Yes             CON     1               ' For SHT1x ??
MoveTo          CON     2               ' For DEBUG Control ??
ClrRt           CON     11              ' Clear DEBUG Line to Right ??
DegSym          CON     186             ' degrees symbol for DEBUG  ??

AD592Kal        CON     15000           ' Calibration Value for AD592.

' -----[ Variables ]-------------------------------------------------------


ioByte          VAR     Byte            ' Data From/To SHT1x and DS1302
work            VAR     Byte            ' Work Data for DS1302
reg             VAR     Byte            ' Read/Write Address for DS1302
secs            VAR     Byte            ' Seconds for DS1302
mins            VAR     Byte            ' Minutes for DS1302
hrs             VAR     Byte            ' Hours for DS1302
date            VAR     Byte            ' Dage for DS1302
month           VAR     Byte            ' Month for DS1302
day             VAR     Nib             ' Day for DS1302
year            VAR     Byte            ' Year for DS1302

ampm            VAR     hrs.BIT5        ' AM/PM Flag Bit for DS1302
clockMode       VAR     hrs.BIT7        ' 12/24 Hour Mode Bit for DS1302
ampmFlag        VAR     Bit             ' 0 = AM, 1 = PM for DS1302
modeFlag        VAR     Bit             ' 0 = 24, 1 = 12 (Hours) for DS1302


ackBit          VAR     Bit             ' Ack/Nak from/to SHT1x
toDelay         VAR     Byte            ' timeout delay timer For SHT1x
timeOut         VAR     Bit             ' timeout status For SHT1x
soT             VAR     Word            ' temp counts from SHT1x
tempC           VAR     Word            ' temp - celcius For SHT1x
tempF           VAR     Word            ' temp - fahrenheit For SHT1x
soRH            VAR     Word            ' humidity counts from SHT1x
rhLin           VAR     Word            ' humidity; linearized for SHT1x
'rhTrue         VAR     Word            ' humidity; temp compensated for SHT1x
status          VAR     Byte            ' status byte for SHT1x

ad592Rct        VAR     Word            ' RCTIME Value for Calculating Temps withAD592
ad592tK         VAR     Word            ' Kelvin Temperature from AD592


' -----[ EEPROM Data ]-----------------------------------------------------

Sun             DATA    "SUN", 0        ' Day Abbreviations for Use with DS1302
Mon             DATA    "MON", 0
Tue             DATA    "TUE", 0        ' These data statements could
Wed             DATA    "WED", 0        ' contain the full day name and
Thu             DATA    "THU", 0        ' the code would still work
Fri             DATA    "FRI", 0        ' without change.
Sat             DATA    "SAT", 0



' -----[ Initialization ]--------------------------------------------------

Init:
GOSUB SHT_Connection_Reset              ' Reset SHT1x Connection
PAUSE 250                               ' Let DEBUG Window Open

' -----[ Program Code ]----------------------------------------------------

Main:
DO                                    ' Place your main routines here
  GOSUB Scheduler                     ' Get The Current Date/Time from DS1302
  GOSUB Show_Time                     ' Display Current Date/Time Read from DS1302
  GOSUB SHT_DisplayData:              ' Main code for Displaying SHT1x Data
  GOSUB Show_LiquidTemp01             ' Get and Display Temp from AD592
LOOP


' -----[ Subroutines ]-----------------------------------------------------


' ######[Feature AD592 Subroutines Go Below This Line]#####

Show_LiquidTemp01:

LOW AD592                                                                ' Discharge the capacitor
RCTIME AD592, 0, ad592Rct                                                ' Time for the volts to rise to 1.3 V
ad592tK = AD592Kal/ad592Rct*10 + (AD592Kal//ad592Rct*10/ad592Rct)        ' Calculate Kelvin
tempC = ad592tK - 273                                                    ' Calculate Celsius
tempF = tempC * 9 / 5 + 32                                               ' Calculate Fahrenheit

DEBUG CR, "AD592 Liquid Temp = ", DEC tempF, "F" ,HOME                   'Display Temp in Fahrenheit


PAUSE 300 ' Slows down the program.
RETURN ' Back to the beginning of the loop.








' ######[Feature DS1302 Subroutines Go Below This Line]#####

Show_Time:
' This routine uses DEBUG TO display the Date/Time information but you
' would customize the routine TO display the DATA you want ON the device
' you want.  NOT all information needs TO be displayed.

  DEBUG HOME                            ' DEBUG Home Position
  LOOKUP (day - 1), [Sun, Mon, Tue, Wed, Thu, Fri, Sat], work

  DO                                    ' Display Day Abbreviation
    READ work, ioByte                   ' Read Each Character Into ioByte
    IF (ioByte = 0) THEN EXIT           ' If 0 then done
    DEBUG ioByte                        ' Send Character To DEBUG Screen
    work = work + 1                     ' Increment Address
  LOOP                                  ' Next Character, If 0 Then Done

  modeFlag = clockMode                  ' Save 12/24 Hour Clock Mode
  clockMode = 0                         ' Clear BIT7
  ampmFlag = ampm                       ' Save AM/PM Flag

  IF modeFlag = 1 THEN ampm = 0         ' Clear BIT5 (12 Hour Mode only!)

  DEBUG " ", HEX2 month, "/", HEX2 date, "/", HEX2 year, " "

  IF (modeFlag = Hr24) THEN             ' Check For 24 Hour Display mode
    DEBUG  HEX2 hrs, ":", HEX2 mins, ":", HEX2 secs
  ELSE
  DEBUG HEX2 hrs, ":", HEX2 mins        ' Print Hours/Minutes
    IF ampmFlag = 0 THEN
      DEBUG "AM"
    ELSE
      DEBUG "PM"
    ENDIF

 DEBUG " [", HEX2 secs, "]"
  ENDIF
  DEBUG CR
  RETURN

Scheduler:                               ' Select the DS1302 and Read the Current Time Then Check for Scheduled Events
  HIGH DS1302RST                         ' Select DS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [RdBurst]
  SHIFTIN DataIO, Clock, LSBPRE, [secs, mins, hrs, date, month, day, year]
  LOW DS1302RST                          ' Deselect DS1302


' ******[Below This Line Are The Guts of the Scheduler]******
'
' ######[Event Triggers Go Below This Line]#####

 ' IF hrs = Pm5 AND mins = $59 AND airTempF = 781 THEN ScheduledEvent_01 'Example Checks Hours, Minutes, and Air Temp for Trigger
  IF hrs = $13 AND mins = $44 THEN ScheduledEvent_02              'Example Checks Hours and Minutes for Trigger
  RETURN

' ######[Events To Be Triggered Go Below This Line]#####
  ScheduledEvent_01:
  DEBUG CR, "Alarm_01", CR
  DEBUG ? tempF
  RETURN

  ScheduledEvent_02:
  DEBUG CR, "Alarm_02", CR
  RETURN

' ######[Low Level DS1302 Subroutines Go Below This Line]#####

Display_HrsCode:                            'Use this Function to Show Hour Code for Testing Delete When Finished!
  DEBUG ? hrs, CR
  DEBUG HEX hrs, CR
  DEBUG HEX2 hrs,CR
  DEBUG DEC hrs, CR
  RETURN

R_In:
  HIGH DS1302RST                           ' Select DS1302
  SHIFTOUT DataIO, Clock, LSBFIRST, [reg]
  SHIFTIN DataIO, Clock, LSBPRE, [ioByte]
  LOW DS1302RST                            ' Deselect DS1302
  RETURN

' ######[Feature SHT1x Subroutines Go Below This Line]#####

SHT_DisplayData:
DEBUG CR
DEBUG "SHT1x Sensor", CR
DEBUG "----------", CR
GOSUB SHT_Measure_Temp
DEBUG MoveTo, 0, 4
DEBUG "soT...... "
DEBUG DEC soT, ClrRt, CR
DEBUG "tempC....... "
DEBUG DEC (tempC / 10), ".", DEC1 tempC, DegSym, ClrRt, CR
DEBUG "tempF....... "
DEBUG DEC (tempF / 10), ".", DEC1 tempF, DegSym, ClrRt
GOSUB SHT_Measure_Humidity
DEBUG MoveTo, 0, 8
DEBUG "soRH..... "
DEBUG DEC soRH, ClrRt, CR
DEBUG "rhLin.... "
DEBUG DEC (rhLin / 10), ".", DEC1 rhLin, "%", ClrRt, CR
DEBUG "rhTrue... "
'DEBUG DEC (rhTrue / 10), ".", DEC1 rhTrue, "%", ClrRt
PAUSE 200 ' minimum delay between readings
RETURN

Heater_On:                                        ' Turn on Internal for 2 Seconds to Test Sensor or if Humidity is too High
DEBUG "SHT1x heater on", CR
status = %00000100                                ' heater bit = On
GOSUB SHT_Write_Status
DEBUG "Waiting 2 seconds", CR
PAUSE 2000

Heater_Off:                                       ' Turn Heater Auto Off After 2 Seconds to Prevent Forgotting it On
DEBUG "SHT1x heater off", CR, CR
status = %00000000                                ' heater bit = Off
GOSUB SHT_Write_Status
GOSUB SHT_Measure_Temp
DEBUG "tempF...... "
DEBUG DEC (tempF / 10), ".", DEC1 tempF, DegSym, ClrRt, CR
GOSUB SHT_Measure_Humidity
DEBUG "rhLin... "
DEBUG DEC (rhLin / 10), ".", DEC1 rhLin, "%", ClrRt, CR, CR
PAUSE 5000
RETURN


' ######[Low Level SHT1x Subroutines Go Below This Line]#####

SHT_Connection_Reset:                              'connection reset: 9 clock cyles with DataIO HIGH, THEN start sequence
SHIFTOUT DataIO, clock, LSBFIRST, [$FFF\9]
SHT_Start:
INPUT DataIO                                       ' let pull-up take line high and then ready the SHT for Data
LOW clock
HIGH clock
LOW DataIO
LOW clock
HIGH clock
INPUT DataIO
LOW clock
RETURN


SHT_Measure_Temp:                                  ' Measure Temperature in !celcius = soT * 0.01 - 40! or !fahrenheit = soT * 0.018 - 40!
GOSUB SHT_Start                                    ' Alert Device
ioByte = ShtTemp                                   ' Temperature Command
GOSUB SHT_Write_Byte                               ' Send Command
GOSUB SHT_Wait                                     ' Wait Until Measurement Done
ackBit = Ack                                       ' Another Read Follows
GOSUB SHT_Read_Byte                                ' Get MSB
soT.HIGHBYTE = ioByte
ackBit = NoAck                                     ' Last Read
GOSUB SHT_Read_Byte                                ' Get LSB
soT.LOWBYTE = ioByte
' Note: Conversion factors are multiplied by 10 to return the
' temperature values in tenths of degrees
tempC = soT / 10 - 400                                ' Convert to Tenths C
tempF = soT ** 11796 - 400                            ' Convert to Tenths F
RETURN


SHT_Measure_Humidity:                              ' Measure Humidity
GOSUB SHT_Start                                    ' Alert Device
ioByte = ShtHumi                                   ' Humidity Command
GOSUB SHT_Write_Byte                               ' Send Command
GOSUB SHT_Wait                                     ' Wait Until Measurement is Done
ackBit = Ack                                       ' Another Read Follows
GOSUB SHT_Read_Byte                                ' Get MSB
soRH.HIGHBYTE = ioByte
ackBit = NoAck                                     ' Last Read
GOSUB SHT_Read_Byte                                ' Get LSB
soRH.LOWBYTE = ioByte
' ###USED###
' linearize humidity
' rhLin = (soRH * 0.0405) - (soRH^2 * 0.0000028) - 4
'
' for the BASIC Stamp:
' rhLin = (soRH * 0.0405) - (soRH * 0.004 * soRH * 0.0007) - 4
'
' Conversion factors are multiplied by 10 and then rounded to
' return tenths
'

rhLin = (soRH ** 26542)
rhLin = rhLin - ((soRH ** 3468) * (soRH ** 3468) + 50 / 100)
rhLin = rhLin - 40

' temperature compensated humidity
' rhTrue = (airTempC - 25) * (soRH * 0.00008 + 0.01) + rhLin
'
' Conversion factors are multiplied by 100 to improve accuracy and then
' rounded off.
' ###USED###

'rhTrue = ((airTempC / 10 - 25) * (soRH ** 524 + 1) + (rhLin * 10)) + 5 / 10

RETURN

SHT_Write_Status:                                  ' Sends "status"
GOSUB SHT_Start                                    ' Alert Device
ioByte = ShtStatW                                  ' Write to Status reg Command
GOSUB SHT_Write_Byte                               ' Send Command
ioByte = status
GOSUB SHT_Write_Byte
RETURN

SHT_Read_Status:                                    ' Returns "status"
GOSUB SHT_Start                                     ' Alert Device
ioByte = ShtStatW                                   ' Write to Status reg Command
GOSUB SHT_Read_Byte                                 ' Send Command
ackBit = NoAck                                      ' Only One Byte to Read
GOSUB SHT_Read_Byte
RETURN

SHT_Write_Byte:                                     ' sends "ioByte" and returns "ackBit"
SHIFTOUT DataIO, clock, MSBFIRST, [ioByte]          ' Send Byte
SHIFTIN DataIO, clock, LSBPRE, [ackBit\1]           ' Get Ack Bit
RETURN

SHT_Read_Byte:                                       ' returns "ioByte" and  sends "ackBit"
SHIFTIN DataIO, clock, MSBPRE, [ioByte]             ' Get Byte
SHIFTOUT DataIO, clock, LSBFIRST, [ackBit\1]        ' Send Ack Bit
INPUT DataIO                                        ' Release Data Line
RETURN

SHT_Wait:                                           ' Wait For Device to Finish Measurement (pulls data line low) Timeout After ~1/4 Second
INPUT DataIO                                        ' Data Line is Input
FOR toDelay = 1 TO 250                              ' Give ~1/4 Second to Finish
timeOut = INS.LOWBIT(DataIO)                        ' Scan Data Line
IF (timeOut = No) THEN SHT_Wait_Done                ' If Low, We're Done
PAUSE 1
NEXT
SHT_Wait_Done:
RETURN

SHT_Soft_Reset:                                     ' Reset SHT1x with Soft Reset
GOSUB SHT_Connection_Reset                          ' Reset The Connection
ioByte = ShtReset                                   ' Reset Command
ackBit = NoAck                                      ' Only One Byte to Send
GOSUB SHT_Write_Byte                                ' Send It
PAUSE 11                                            ' Wait at Least 11 ms
RETURN
 