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.





Bookmarks