Several years ago, Darrel (god rest his soul) and Henrik helped me no end in developing a 4 channel controller for my reptiles. I've used this code as a basis to develop simplified version, and to see if I can use a DTH11 sensor to incorporate humidity readout. Here is what I've got
The only issue I have with this code is that unlike the 4 channel version (which has been keeping my vivariums at a stable temperature for the past 4 years) is that it jumps out to the sensor error routine to often for my liking. Other than that it behaves just like the 4ch version and maintains a stable temperature around the set point. Any suggestions as to reduce the frequency that it detects a miss-read would be welcome.Code:'*******************************************************************************
' Set Config - 18F2520
'*******************************************************************************
ASM
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
'*******************************************************************************
' LCD (20 x 4) set up
'*******************************************************************************
DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us
'*******************************************************************************
' Defines Statements
'*******************************************************************************
DEFINE OSC 20 ' 18F4520 / 18F2520, 20mhz crystal
clear
'*******************************************************************************
'Analog and Comparator settings
'*******************************************************************************
ADCON0 = %00000000 'AD converter module disabled
ADCON1 = %00001111 'All Digital
ADCON2 = %00000000
CMCON = 7 'Disable Comparators
'*******************************************************************************
'Pins & Ports
'*******************************************************************************
TempSensor1 VAR PORTA.5 ' Pin assigned to Sensor (EasyPIC5)
HeaterOut1 VAR PORTA.4 ' Output
'*******************************************************************************
'Interrupts
'*******************************************************************************
DEFINE WRITE_INT 1
INCLUDE "DT_INTS-18.bas" ; DT's Base Interrupt System
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, HeaterDrive, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
T1CON = %00000001 ; free-running, 1:4 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
'*******************************************************************************
'DS18B20 Defines
'*******************************************************************************
DEFINE DS1820_DECIMALS 1 ' 1
DEFINE DS1820_VERIFYCRC YES ' NO
DEFINE DS18B20_ONLY YES ' NO
INCLUDE "DT18x20.pbp" ' Include DT18x20 module
'*******************************************************************************
'Inc PID routine
'*******************************************************************************
INCLUDE "incPID.pbp" ' Include the PID routine.
'*******************************************************************************
'Varibles
'*******************************************************************************
TempWD VAR WORD ' temporary WORD variable
FlashStar VAR BIT
GIE VAR INTCON.7
spMode1 VAR BYTE
SetPoint1 VAR WORD[1]
Temperatures VAR WORD
HeatCycle VAR BYTE BANK0 SYSTEM
HeaterDrives VAR BYTE[4] BANK0 SYSTEM
HeatDrive1 VAR HeaterDrives[0]
SensorActive VAR BIT
ChannelPWR VAR BIT
'*******************************************************************************
'EEPROM data
'*******************************************************************************
EE_spMode1 DATA 0 ' 0=Manual mode, temp is set by Pot.
EE_SetPoint1 DATA WORD 250 ' 25.0 deg. after programming if not in manual mode
EE_pid_Kp1 DATA WORD $0700 ' PID constants $0700, $0080, $0200
EE_pid_Ki1 DATA WORD $0080
EE_pid_Kd1 DATA WORD $0200
EE_pid_Ti1 DATA 8 ' Update I-term every 8th call to PID
EE_pid_I_Clamp1 DATA 250 ' Clamp I-term to max ±100
EE_pid_Out_Clamp1 DATA WORD 255 ' Clamp the final output to 255
EE_CH1PWR DATA 1
READ EE_spMode1, spMode1
READ EE_SetPoint1, WORD SetPoint1
READ EE_pid_Kp1, WORD pid_Kp
READ EE_pid_Ki1, WORD pid_Ki
READ EE_pid_Kd1, WORD pid_Kd
READ EE_pid_Ti1, pid_Ti
READ EE_pid_I_Clamp1, pid_I_Clamp
READ EE_pid_Out_Clamp1, WORD pid_Out_Clamp
read EE_CH1PWR, ChannelPWR
'*******************************************************************************
'Initialization
'*******************************************************************************
LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
@ DS1820_Select _TempSensor1 ; Select the DS18x20 pin
@ DS1820_Resolution 12 ; Set # of bits in resolution
LOW HeaterOut1 ; set heater pin to Output
'*******************************************************************************
'Main Program
'*******************************************************************************
Main:
@ DS1820_Convert ; start a temperature conversion
@ DS1820_Stat ; check the sensors status
; enable interrupts after 1-wire
PAUSEUS 20
GIE = 1 ; disable interrupts before 1-wire
@ DS1820_Read ; get the temperature result
@ DS1820_Stat
GIE = 1
IF DS1820_Error = 0 THEN ; if there were no errors
LCDOUT $FE,$80 ; line 1, col 0
TempWD = TempC : GOSUB TempToLCD ; display TempC
'TempWd = TempC
pid_Error = SetPoint1 - TempC
TempWD = pid_Error ; Display the error value
Gosub PID
IF pid_Out.15 THEN pid_Out = 0 ; only keep positive values
HeatDrive1 = pid_Out
ELSE ;--- Error reading Sensor --------
gosub senserror
ENDIF
GOTO Main
'*******************************************************************************
'Interrupt
'*******************************************************************************
ASM
HeaterDrive
incf HeatCycle,F ; HeatCycle
movf _HeatDrive1,W ; HeatDrive1
subwf HeatCycle,w
btfsc STATUS,C
bcf _HeaterOut1
btfss STATUS,C
bsf _HeaterOut1
INT_RETURN
ENDASM
'*******************************************************************************
'Display Temp
'*******************************************************************************
TempToLCD:
IF TempWD.15 THEN LCDOUT "-" ; if negative, display minus sign
TempWD = ABS(TempWD) ; get the positive value
LCDOUT DEC TempWD/DS1820_DIG ; Display the Integer portion
@ if (DS1820_DECIMALS > 0) ; if using decimals
LCDOUT "." ; display decimal point
TempWD = TempWD//DS1820_DIG ; get decimal portion
@ if (DS1820_DECIMALS > 1) ; with DECIMALS=2, next DIG is 1
LCDOUT DEC1 TempWD DIG 1
@ endif
@ if (DS1820_DECIMALS >= 1) ; with DECIMALS=1, next DIG is 0
LCDOUT DEC1 TempWD DIG 0
@ endif
@ endif
RETURN
'*******************************************************************************
'Sensor Error
'*******************************************************************************
senserror:
LCDOUT $FE,1,"Sensor Error"
HeatDrive1 = 0
pause 1000
LCDOUT $FE,1," "
return
OK now on to the second part.
I've used this code below to read the DTH11 sensor and display the results on an LCD
The part I'm stumped with is how to use the data from the DTH11 to replace that of the 18B20. If I read the data sheet for the DHT11 once triggered to send data, it sends a 40 bit serial data which includes 8 bit temperature and 8 bit humidity (presumably bits 8-15 for temp and bits 24 to 31 for humidity by the code high-lighted). The data sheet for the 18B20 states that you can set the resolution for temp to digital conversion between 9 and 12 bits, but I'm sure it sends the actual temperature value as 2 x 8 bit bytes ??Code:ASM
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM
'*******************************************************************************
' LCD (20 x 4) set up
'*******************************************************************************
DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us
'*******************************************************************************
' Defines Statements
'*******************************************************************************
DEFINE OSC 20 ' 18F4520 / 18F2520, 20mhz crystal
ADCON1 = $0F
clear
'*******************************************************************************
'Analog and Comparator settings
'*******************************************************************************
ADCON0 = %00000000 'AD converter module disabled
ADCON1 = %00001111 'All Digital
ADCON2 = %00000000
CMCON = 7 'Disable Comparators
'*******************************************************************************
'Port and Register settings (interrupts)
'*******************************************************************************
TRISA = %00010111
TRISB = %00000011
T0CON = %11000111
T1CON = %00000001 ; free-running, 1:1 prescaler
TMR1H = %11111111
TMR1L = %11111011
'*******************************************************************************
LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
'*******************************************************************************
dht var byte[32]
humidite var byte
haut var byte
bas var byte
temp var byte
x var byte
dht11 var portA.5
'*******************************************************************************
start:
TRISA.5 = 0 '
high dht11
pause 2000 ' wait 2 sec
low dht11 : pause 18' send 20ms low
high dht11 : pauseus 30 ' send 40us hi
TRISA.5 = 0
PulsIn PORTA.5, 1, haut
if haut < 15 then goto start
for x = 31 to 0 step-1
PulsIn PORTA.5, 1, dht[x] ' 1
next x
For x = 31 to 0 step-1
if dht(x)>=9 and dht(x)<=21 then dht(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if dht(x)>=29 and dht(x)<=41 then dht(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
humidite=dht[31]*128+dht[30]*64+dht[29]*32+dht[28]*16+dht[27]*8+dht[26]*4+dht[25]*2+dht[24]*1
temp=dht[15]*128+ dht[14]*64+dht[13]*32+dht[12]*16+dht[11]*8+dht[10]*4+dht[9]*2+dht[8]*1
lcdout $FE,1
lcdout $FE,$C0,"Humidite = ",#humidite,"% "
lcdout $FE,$80,"Temperature = ",#temp,$DF,"C"
goto start
Constructive comments welcome.