Code:
'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'* Universal thermostat -25/+75 C. by R.T.G. van Steenis *
'* Compiler : PicBasic Pro 2.45 *
'* 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 PIC16F877A Code size = 1966 Words *
'* *
'* Oscillator XT (4 MHz.) - Power up timer enabled - MCR enable *
'* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
'*****************************************************************************
'* LCD Defines for EasyPic5 & 16F877A *
'*****************************************************************************
'@ ERRORLEVEL -306
'@ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_ON & _LVP_OFF & _CP_OFF
'
' DEFINE LCD_DREG PORTB ' I/O port where LCD is connected
' DEFINE LCD_DBIT 0
' DEFINE LCD_RSREG PORTB
' DEFINE LCD_RSBIT 4 ' Register select pin
' DEFINE LCD_EREG PORTB
' DEFINE LCD_EBIT 5 ' Enable pin
' DEFINE LCD_BITS 4 ' 4-bit data bus
' DEFINE LCD_LINES 2 ' LCD has 2 character lines
'
' DEFINE OSC 8
' DEFINE BUTTON_PAUSE 100
'
''*****************************************************************************
''Pinout for EasyPic5
''
''
' Heat Var PORTC.0
' Cool Var PORTC.2
' Waitbit Var PortC.4
' DQ Var PORTE.2 ' One-wire data pin
'
' Mode_B Var PORTA.0 'Pullups ...
' UP_B Var PORTA.1
' DOWN_B Var PORTA.2
''
''*****************************************************************************
''Configs EasyPic5
''*****************************************************************************
''
'ADCON1 = 7 ' Set PORTD and PORTE to digital
'CMCON = 7 ' Comparators OFF
'
'PORTA = %00000111
'PORTB = 0
'PORTC = 0
'PORTD = 0
'PORTE = 0
'
'TRISA = %00000111
'TRISB = 0
'TRISC = 0
'TRISD = 0
'TRISE = %00000100
'*****************************************************************************
'
'
'*****************************************************************************
'*****************************************************************************
' Elektor LCD Defines
@ __CONFIG _XT_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_ON & _BODEN_OFF & _LVP_OFF & _CP_OFF
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
'*****************************************************************************
'Pinout for Elektor
Heat Var PORTA.2
Cool Var PORTA.3
DQ Var PORTA.4 ' One-wire data pin
Mode_B Var PORTB.0
UP_B Var PORTB.1
DOWN_B Var PORTB.2
'*****************************************************************************
' I/o Settings
PORTA = 0
PORTB = 0
TRISA= %11110000 ' RA0..3=Outputs RA4=Input
TRISB= %00000111 ' RB0..RB2=Inputs, RB3..RB7=Outputs
CMCON=7 ' Disable comparators
'*****************************************************************************
'*****************************************************************************
' Variables
'*****************************************************************************
Temperature Var Word ' Temperature storage
TempC Var Word
Float Var Word
TargetTemp Var Word ' Desired Temperature
Hyst Var Word ' Hystereris
V Var Word ' Var. for display
Cadence Var Word
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
DS18B20_Bit Var Byte
FAM Var Byte
CRC Var Byte
ID Var Byte[7]
Twist Var Bit
Busy Var Bit
Disable_out Var Bit
'*****************************************************************************
' Resolution
'*****************************************************************************
'DS18B20_9bit CON %00011111 ' 93.75ms, 0.5°C
'DS18B20_10bit CON %00111111 ' 187.5ms, 0.25°C <-- My favorite
'DS18B20_11bit CON %01011111 ' 375ms, 0.125°C
'DS18B20_12bit CON %01111111 ' 750ms, 0.0625°C (default)
Resolution CON 12
Offset CON 300
'*****************************************************************************
'Initialization
'*****************************************************************************
SELECT CASE Resolution
Case 9
DS18B20_bit = %00011111 ' 93.75ms, 0.5°C
Cadence = 900
Case 10
DS18B20_bit = %00111111 ' 187.5ms, 0.25°C <-- My favourite
Cadence = 810
Case 11
DS18B20_bit = %01011111 ' 375ms, 0.125°C
Cadence = 625
Case 12
DS18B20_bit = %01111111 ' 750ms, 0.0625°C (default)
Cadence = 250
END SELECT
DATA 46, 224, 20 ' Temp MSB, TEMP LSB, Hysteresis DIV 10
Heat=0 ' Warm Output Low
Cool=0 ' Cold Output Low
Disable_out = 1
Mode=0 ' Temperature display mode
Twist = 0
'*****************************************************************************
' Program start
'*****************************************************************************
PAUSE 500
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.)
LCDOUT $FE, 1, $FE, $0C ' Clear display, cursor off
PAUSE 250
'*****************************************************************************
SensID:' Sensor Identification
'*****************************************************************************
OWOUT DQ, 1, [ $33 ] 'READ Chip Family code
OWIN DQ, 2, [ FAM,ID[6],ID[5],ID[4],ID[3],ID[2],ID[1],CRC]
IF FAM = $05 THEN
LCDOUT $FE,$80, "DS 2405 "
PAUSE 1000
LCDOUT $FE,$80, " CRC: ",HEX2 CRC," FAM: ", HEX2 FAM
ENDIF
'*****************************************************************************
' DS 1820 / DS 18S20
'*****************************************************************************
IF FAM = $10 THEN
LCDOUT $FE,$80, "DS 18S20/1820"
PAUSE 2000
LCDOUT $FE,$80, " CRC: ",HEX2 CRC," FAM: ", HEX2 FAM
ENDIF
'*****************************************************************************
' DS 18B20 Config
'*****************************************************************************
IF FAM = $28 THEN
LCDOUT $FE,$80, "DS 18B20 "
OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_bit] 'Skip ROM search and write N_bits
' resolution to scratch pad
'*****************************************************************************
'DS 18B20 PAR Test
'*****************************************************************************
HIGH DQ
PAUSE 10 'Keep DQ High for 10 ms
INPUT DQ
'*****************************************************************************
PAUSE 2000
'*****************************************************************************
' Show CRC and FAM
'*****************************************************************************
LCDOUT $FE,$80, " CRC: ",HEX2 CRC," FAM: ", HEX2 FAM
ENDIF
'*****************************************************************************
' Show ID
'*****************************************************************************
LCDOUT $FE,$C0," ID:",HEX2 ID[1],HEX2 ID[2],HEX2 ID[3],HEX2 ID[4],HEX2 ID[5],HEX2 ID[6]
PAUSE 2000
'*****************************************************************************
' Clear Screen
'*****************************************************************************
LCDOUT $FE,1
'*****************************************************************************
'*****************************************************************************
MainLoop:
'*****************************************************************************
' Select and Save Function
'*****************************************************************************
If Mode_B=0 then ' Mode switch pressed
Pause 50 ' Debounce
LcdOut $FE, $8F, "*" ' Show that command is accepted
If Mode_B=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
'*****************************************************************************
' set Temperature
'*****************************************************************************
If Mode =1 then ' Set Target Temperature
LcdOut $FE, $80, "SET TEMPERATURE " ' Show function
V=TargetTemp ' TargetTemp in V
Gosub SelectSign ' Select +/blank/-
Gosub DisplayTemp ' Display Target Temperature
If (UP_B=0) Or (DOWN_B=0) then ' Up or Down button pushed
'****************************************************************************
' Decrease set Temp
'****************************************************************************
If DOWN_B=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
'*****************************************************************************
' Increase set Temp
'*****************************************************************************
If UP_B=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
'*****************************************************************************
' Display set Temp
'*****************************************************************************
GoSub SetTargetTemp ' Display TargetTemp and delay 0.25 Sec.
EndIf
EndIf
'*****************************************************************************
' Set Hysteresis
'*****************************************************************************
If Mode=2 then ' Set Hysteresis
LcdOut $FE, $80, "HYSTERESIS " ' Show function
Sign=" " ' No sign
V= 10000+Hyst ' Set value for V
Gosub DisplayTemp ' Display Hysteresis
If (UP_B=0) Or (DOWN_B=0) then ' Up or down button pushed
Sign=" " ' No sign for Hysteresis
'*****************************************************************************
' Decrease Hysteresis
'*****************************************************************************
If DOWN_B=0 then ' Down button
If Hyst > 10 then Hyst=Hyst-10 ' Not less than 0.1 C.
EndIf
'*****************************************************************************
' Increase Hysteresis
'*****************************************************************************
If UP_B=0 then ' Up button
If Hyst < 1000 then Hyst=Hyst+10 ' Not more than 10.0 C.
EndIf
'*****************************************************************************
' Scale and show Hysteresis
'*****************************************************************************
V= 10000+Hyst ' Set value for V
Gosub DisplayTemp ' Display Hysteresis
Pause 250 ' Delay 0.25 Sec.
EndIf
EndIf
'*****************************************************************************
' Wait for End setting
'*****************************************************************************
If Mode > 0 then Mainloop ' Setting TargetTemperature or Hysteresis
LcdOut $FE, $80, " TEMPERATURE " ' Show function
'*****************************************************************************
' Sensor Presence Test
'*****************************************************************************
LOW DQ ' OneWire line Low
PauseUs 480 ' Keep down for 480 µS
Input DQ ' Make Pin Input
PauseUs 70 ' Wait 70 µS
If DQ then ' No presence pulse from DS1820
LcdOut $FE, $1, "** No sensor! **" ' Show message
Disable_out = 1
Pause 500 ' Wait 0.5 Sec.
Goto MainLoop ' Check again
Endif
Pauseus 400 ' Wait 400µs more and see
IF DQ = 0 THEN
LcdOut $FE, $1, " sensor shorted!" ' Show message
Disable_out = 1
Pause 500 ' Wait 0.5 Sec.
Goto MainLoop ' Check again
Endif
Disable_out = 0 ' Sensor Ok : Output allowed
'*****************************************************************************
' Temp reading
'*****************************************************************************
OWOut DQ, 1, [$CC, $44 ] ' Start temperature conversion
WaitBit = 1 ' Show conversion ON
' REPEAT
'
' OWIn DQ, 4, [Busy] ' Check for still busy converting
'
' UNTIL BUSY
'*****************************************************************************
' DS18B20 PAR Test
'*****************************************************************************
HIGH DQ
PAUSE ( 1000 - Cadence )
INPUT DQ
WaitBit = 0
'*****************************************************************************
' Conversion completed
'*****************************************************************************
OWOUT DQ, 1, [$CC, $BE ] ' Skip ROM search & read scratchpad memory
OWIN DQ, 2, [Temperature.Lowbyte, Temperature.Highbyte]'READ two bytes / end comms
PAUSE Cadence ' 1 Measure/s !!!
'*****************************************************************************
' Temperature Calculation
'*****************************************************************************
Convert_Temp:
IF FAM = $10 THEN Temperature = Temperature * 8
IF Temperature.15 THEN
Temperature = ~Temperature + 1
Twist = 1
ENDIF
TempC = ( Temperature & $7FF ) >> 4 ' Partie Entière '4
Float = ((Temperature.Lowbyte & $0F ) * 25 )>> 2 ' Partie décimale 100èmes
Temperature = TempC*100 + Float 'Préparation 1/100 degrés
IF Twist THEN
V= 10000 - Temperature ' 25 C=12500 0 C=10000 -10 C=9000
Twist = 0
else
V= 10000 + Temperature
EndIf
'*****************************************************************************
' Offset Correction for DS 1820
'*****************************************************************************
IF FAM = $10 THEN V = V + Offset
'*****************************************************************************
' Show status
'*****************************************************************************
IF NOT Disable_out THEN
If V < TargetTemp - Hyst then ' Below Target temperature - Hysteresis
Heat=1 ' Activate Warm Output
Cool=0 ' Deactivate Cold Output
EndIf
If V > TargetTemp + Hyst then ' Above Target temperature + Hysteresis
Heat=0 ' Deactivate Warm output
Cool=1 ' Activate Cold Output
EndIf
GoSub SelectSign ' +/blank/- Sign
GoSub DisplayTemp ' Temperature to LCD
Else
Heat = 0 : Cool = 0
Endif
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
Return
'*****************************************************************************
'*****************************************************************************
DisplayTemp:
If V >= 10000 then ' Above 0 C.
Temperature = V-10000
Else
Temperature = 10000-V ' Below 0 C.
EndIf
LcdOut $FE, $C0," ", Sign, DEC (Temperature / 100), ".", DEC2 Temperature,178,"C "
Return
'*****************************************************************************
'*****************************************************************************
SetTargetTemp:
V=TargetTemp
Gosub SelectSign
Gosub DisplayTemp
Pause 250
Return
'*****************************************************************************
'*****************************************************************************
END
I ran it aboard an EasyPic 5 Board ... but connections are described in the beginning of the listing ...
Bookmarks