'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'* Universal thermostat -25/+75 C.  by R.T.G. van Steenis                  *
'* Digital thermostat (080090-11) from Elektor july_august 2008            *
'* Compiler : PicBasic Pro 2.44                                            *
'* B0 = Mode switch in (In)            A0 = LCD Enable    (Out)            *
'* B1 = + switch in    (In)            A1 = LCD RS        (Out)            *
'* B2 = - switch in    (In)            A2 = "Warm" Output (Out)            *
'* B3 = Not connected  (Out)           A3 = "Cold" Output (Out)            *
'* B4 = LCD Bit 4      (Out)           A4 = DQ DS1820     (In)             *
'* B5 = LCD Bit 5      (Out)                                               *
'* B6 = LCD Bit 6      (Out)                                               *
'* B7 = LCD Bit 7      (Out                                                *
'*                                                                         *
'*                 modify by Niculescu Dan                                 * 
'*                                                                         *
'*         DUAL THERMO 2xDS18B20 ; PIC 16F628A  ; LCD 2x16                 *
'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

TRISA= %11110000                        ' RA0..3=Outputs RA4=Input
TRISB= %00000111 			          ' RB0..RB2=Inputs, RB3..RB7=Outputs
CMCON=7                                 ' Disable comparators

DEFINE LCD_DREG PORTB                   ' LCD on port B
DEFINE LCD_DBIT 4                       ' Data bits B4..B7
DEFINE LCD_RSREG PORTA                  ' RS on PORTA
DEFINE LCD_RSBIT 1                      ' RS on A1 
DEFINE LCD_EREG PORTA                   ' E on PORTA
DEFINE LCD_EBIT 0                       ' E on A0
DEFINE LCD_BITS 4                       ' LCD 4 bit mode
DEFINE LCD_LINES 2                      ' 2 line LCD display

Temperature1     Var	Word		' Temperature storage Sensor1
Temperature2     Var	Word		' Temperature storage Sensor2
TempC            Var    Word
Float            Var    Word
TargetTemp	     Var	Word		' Desired Temperature
Hyst		     Var	Word		' Hystereris
V		     Var	Word		' Var. for display
V2		     Var	Word		' Var. for display
B1               Var    Byte        ' Byte for TargetTemp calculation 
B2               Var    Byte        ' Byte for TargetTemp calculation
Sign		     Var	Byte		' +/- sign
Mode 		     Var	Byte		' 0=Temp. display, 1=Set Temp, 2=Set Hysteresis
DQ		     Var	PORTA.4	' One-wire data pin
Twist            Var    Bit
Twist2           Var    Bit
Dummy            Var    Byte

DS18B20_9bit 	CON %00011111 ; 93.75ms, 0.5°C
DS18B20_10bit 	CON %00111111 ; 187.5ms, 0.25°C 
DS18B20_11bit 	CON %01011111 ; 375ms,   0.125°C
DS18B20_12bit 	CON %01111111 ; 750ms,   0.0625°C  (default)
DS18B20_1_12bit 	CON %01111111 ; 750ms,   0.0625°C  
DS18B20_2_12bit 	CON %01111111 ; 750ms,   0.0625°C  

DATA 46, 224, 20                        ' Temp MSB, TEMP LSB, Hysteresis DIV 10

PORTA.2=0                               ' Warm Output Low
PORTA.3=0                               ' Cold Output Low
Mode=0                                  ' Temperature display mode  
Twist = 0
Twist2 = 0

Pause 500
LCDOUT $FE, 1, $FE, $0C                 ' Clear display, cursor off
Pause 250

Read 0, B1                              ' Read TargetTemp MSB
Read 1, B2                              ' Read TargetTemp LSB
TargetTemp=B1*256+B2                    ' Calculate TargetTemp value (Default=20.0 C.)
Read 2, B1                              ' Read Hysteresis 
Hyst=10*B1                              ' Calculate Hysteresis value (Default= 2.0 C.)  

 OWOut DQ, 1, [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $4E, $FF, $FF, $7F] ' Init Sensor 1
 OWOut DQ, 1, [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $48] 
 OWOut DQ, 1, [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $B8] 
 OWOut DQ, 1, [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $BE] 
Pause 1000
 OWIn DQ, 0, [Temperature1.Byte0, Temperature2.Byte1]
LcdOut $FE, $80,  "Senzor1 INIT OK" 
Pause 500


 OWOut DQ, 1, [$55, $28,  $EB, $EA, $48, $1, $0, $0, $FF, $4E, $FF, $FF, $7F] ' Init Sensor 2
 OWOut DQ, 1, [$55, $28,  $EB, $EA, $48, $1, $0, $0, $FF, $48] 
 OWOut DQ, 1, [$55, $28,  $EB, $EA, $48, $1, $0, $0, $FF, $B8] 
 OWOut DQ, 1, [$55, $28,  $EB, $EA, $48, $1, $0, $0, $FF, $BE] 
Pause 1000
 OWIn DQ, 0, [Temperature2.Byte0, Temperature2.Byte1] 
LcdOut $FE, $C0,  "Senzor2 INIT OK" 
Pause 1000


MainLoop: 
 If PORTB.0=0 then                      ' Mode switch pressed
  Pause 50                              ' Debounce 
LcdOut $FE, 1
 LcdOut $FE, $8F, "*"                   ' Show that command is accepted 
  If PORTB.0=0 then MainLoop            ' Wait until button is released  
  Mode=Mode+1                           ' Increment mode
  If Mode=2 then                        ' Save Target Temperature (Mode1 -> Mode2)
   Write 0, TargetTemp / 256		    ' TargetTemp MSB
   Write 1, TargetTemp MOD 256          ' TargetTemp LSB
  EndIf
  If Mode > 2 Then                      ' Save Hysteresis (Mode 2 -> Mode 0) 
   Mode=0               		    ' Only 0, 1, 2 are valid
   Write 2, Hyst / 10                   ' Divide Hyst value to fit in Byte
  EndIf
 EndIf

 If Mode =1 then
  LcdOut $FE, $80, "SET TEMPERATURE "   ' Show function
  V=TargetTemp                          ' TargetTemp in V  
  Gosub SelectSign                      ' Select +/blank/- 
  Gosub DTemp                           ' Display Target Temperature
  If (PORTB.1=0) Or (PORTB.2=0) then    ' Up or Down button pushed
   If PORTB.2=0 then                    ' Down button 
    If TargetTemp > 7500 then           ' Not lower than -25 C. (10000-MinTemp * 100)
     TargetTemp=TargetTemp-25           ' Decrease temperuture with 0.25 C.
    EndIf
   EndIf
   If PORTB.1=0 then                    ' Up button
    If TargetTemp < 17500 then          ' Not higher than 75 C. (10000+MaxTemp * 100)
     TargetTemp=TargetTemp+25           ' Increase temperature with 0.25 C.
    EndIf
   EndIf
   GoSub SetTargetTemp                  ' Display TargetTemp and delay 0.25 Sec.
  EndIf
 EndIf 

 If Mode=2 then                         ' Set Hysteresis  
  LcdOut $FE, $80, "SET HYSTERESIS "    ' Show function
  Sign=" "                              ' No sign  
  V= 10000+Hyst                         ' Set value for V  
  Gosub DTemp                           ' Display Hysteresis
  If (PORTB.1=0) Or (PORTB.2=0) then    ' Up or down button pushed  
   Sign=" "                             ' No sign for Hysteresis
   If PORTB.2=0 then                    ' Down button
    If Hyst > 10 then Hyst=Hyst-10      ' Not less than 0.1 C.
   EndIf
   If PORTB.1=0 then                    ' Up button
    If Hyst < 1000 then Hyst=Hyst+10    ' Not more than 10.0 C.
   EndIf 
   V= 10000+Hyst                        ' Set value for V
   Gosub DTemp                          ' Display Hysteresis 
   Pause 250                            ' Delay 0.25 Sec.
  EndIf
 EndIf 

 If Mode > 0 then Mainloop              ' Setting TargetTemperature or Hysteresis


Output DQ             			    ' Make Pin Output
 DQ=0					          ' OneWire line Low
 PauseUs 480                            ' Keep down for 480 µS  
 Input DQ                               ' Make Pin Input
 PauseUs 70                             ' Wait 70 µS
 If DQ=1 then                           ' No presence pulse from DS1820   
  LcdOut $FE, $1, "** No sensor! **"    ' Show message
  Pause 500                             ' Wait 0.5 Sec. 
  Goto MainLoop                         ' Check again
 EndIf

'===================================================================================================

Main :
Part1:	
 OWOut DQ, 1, [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $44] ' Start temp. conversion Sensor1

WaitLoop: 
While not DQ
Wend

OWOut DQ, 1,  [$55, $28,  $DD, $06, $49, $1, $0, $0, $D4, $BE]
Pause 500
OWIn DQ, 0, [Temperature1.Byte0, Temperature1.Byte1]
If Temperature1.15 then       
  Temperature1= ~Temperature1 +1
  Twist = 1
Endif
 
Dummy = 625 * Temperature1
TempC = DIV32 10 
TempC = (Temperature1 & $7FF) >> 4
Float = ((Temperature1.Lowbyte & $0F ) * 25 )>>2
Temperature1 = TempC*100 + Float
If Twist then
  V= 10000 - Temperature1               ' 25 C=12500  0 C=10000  -10 C=9000 
  Twist = 0
 else
  V= 10000 + Temperature1
 EndIf
 If V >= 10000 then                     ' Above 0 C.      
  Temperature1=V-10000                   
 Else                                   
  Temperature1=10000-V                  ' Below 0 C. 
 EndIf
 GoSub SelectSign                       ' +/blank/- Sign 
 GoSub DisplayTemp                      ' Temperature to LCD

'===================================================================================================
Part2 :	
 OWOut DQ, 1, [$55, $28, $EB, $EA, $48, $1, $0, $0, $FF, $44]  ' Start temp. conversion Sensor2

WaitLoop2: 
While not DQ
Wend

OWOut DQ, 1,  [$55, $28, $EB, $EA, $48, $1, $0, $0, $FF, $BE]
Pause 500
OWIn DQ, 0, [Temperature2.Byte0, Temperature2.Byte1]
If Temperature2.15 then       
  Temperature2= ~Temperature2 +1
  Twist2 = 1
Endif
 
Dummy = 625 * Temperature2
TempC = DIV32 10 
TempC = (Temperature2 & $7FF) >> 4
Float = ((Temperature2.Lowbyte & $0F ) * 25 )>>2
Temperature2 = TempC*100 + Float
If Twist2 then
  V2= 10000 - Temperature2              ' 25 C=12500  0 C=10000  -10 C=9000 
  Twist2 = 0
 else
  V2= 10000 + Temperature2
 EndIf
 If V2 >= 10000 then                    ' Above 0 C.      
  Temperature2=V2-10000                   
 Else                                   
  Temperature2=10000-V2                 ' Below 0 C. 
 EndIf

 GoSub SelectSign                       ' +/blank/- Sign 
 GoSub DisplayTemp                      ' Temperature to LCD


Goto MainLoop				    ' Do it forever

' SUBROUTINES:
'===================================================================================================
SelectSign:
 If v = 10000 then                      ' Temperature = 0 C.
  Sign=" " 				          ' No sign
 Else 
  If v < 10000 then              	    ' <> 0
   Sign="-"				          ' Temperature below 0 C. 	
  Else
   Sign="+"				          ' Temperature above 0 C.
  EndIf
 EndIf

 If v2 = 10000 then                     ' Temperature = 0 C.
  Sign=" " 				          ' No sign
 Else 
  If v2 < 10000 then              	    ' <> 0
   Sign="-"				          ' Temperature below 0 C. 	
  Else
   Sign="+"				          ' Temperature above 0 C.
  EndIf
 EndIf

Return


'===================================================================================================
DisplayTemp:
 If V >= 10000 then                     ' Above 0 C.      
  Temperature1=V-10000                   
 Else                                   
  Temperature1=10000-V                  ' Below 0 C. 
 EndIf


 If V2 >= 10000 then                    ' Above 0 C.      
  Temperature2=V2-10000                   
 Else                                   
  Temperature2=10000-V2                 ' Below 0 C. 
 EndIf


LcdOut $FE, $80,  "INT : ", Sign," ", DEC (Temperature1 / 100), ".", DEC2 Temperature1, " ",223,"C " 
LcdOut $FE, $C0,  "EXT : ", Sign," ", DEC (Temperature2 / 100), ".", DEC2 Temperature2, " ",223,"C " 
Return

'===================================================================================================
SetTargetTemp:
 V=TargetTemp
 Gosub SelectSign
 Gosub DTemp 
 Pause 250
Return
'===================================================================================================
DTemp :
 If V >= 10000 then                     ' Above 0 C.      
  Temperature1=V-10000                   
 Else                                   
  Temperature1=10000-V                  ' Below 0 C. 
 EndIf
LcdOut $FE, $C0, Sign," ", DEC (Temperature1 / 100), ".", DEC2 Temperature1, " ",223,"C " 
Return

'============================================= END OF PROGRAM ======================================
