PID thermostat Issue


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Oct 2009
    Posts
    583

    Default PID thermostat Issue

    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

    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
    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.

    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

    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
    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 ??

    Constructive comments welcome.
    Last edited by Scampy; - 23rd February 2015 at 21:25.

  2. #2
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: PID thermostat Issue

    Is your code for the second part working?
    I'm not quite sure what you are asking.
    Regards,
    TABSoft

  3. #3
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: PID thermostat Issue

    Yes, both programs work independently. The second section of code just proves the DHT sensor works, the code above it is the main program that uses a DS18B20 sensor. I would like to use the DHT sensor in place of the 18B20 so that it's temperature data can be used to work with the PID routine. The problem is that the two sensors use different one wire protocol as far as I can tell, and that's what I am asking for help with.

  4. #4
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: PID thermostat Issue

    Okay.
    It looks like the routines you want to use the data in are in the Include files..

    Do you want to provide the whole thing so we can see if we can help?
    Regards,
    TABSoft

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,516


    Did you find this post helpful? Yes | No

    Default Re: PID thermostat Issue

    Hi,
    I've never used the DS18B20 or the DHT11.
    Looking at the datasheet for the DS18B20 it seems like it returns the temperature in units of 0.1 degrees. Ie, if the returned value is 325 the actual temperature is 32.5C.
    The DHT11 claims a resoultion of 8 bits and 1 degree but it still seems to send 16 bits of temperature data where the low byte is the decimal part (which I guess will always be 0).

    Anyway, if you want to use the DHT11 instead of the DS18B20 what you want to do is make sure to scale the raw value so that they both give you the same value at a certain temperature. They might already DO that but you need to verify it. In the DS18B20 code your raw value seems to be the TempC variable while in the DHT11 code it's the temp variable.

    At a known temperature (roughly) run the 18B20 code and output the TempC variable on the LCD. What does it say? Something like 225 for 22.5 degrees?
    At the same temperarure (roughly) run the DHT11 code and output the Temp variable on the LCD. What does it say? Something like 220 for 22.5 degrees? Or something else?

    If they are the same (roughly) then you're good to go as is. Otherwise you need to scale the DHT11 value so it gives the same result as the DS18B20 code for any given temperature (or you need to retune the PID filter).

    With that said that DHT11 code looks REALLY convoluted, especially the highlighted part.

    I wrote the following, not saying it'll work, have no sensor here to verify with.
    Code:
    PulsWidth VAR BYTE
    BitValue VAR BIT
    
    Humidity VAR WORD
    Temperature VAR WORD
    Checksum VAR BYTE
    
    
    Main:
      GOSUB ReadDHT11
      LCDOUT $FE, 1, "RH: ", DEC Humidity, "%"
      LCDOUT $FE, $C0, "Temp: ", DEC Temperature, "c"
      PAUSE 1000
    Goto Main
    
    
    ReadDHT11:
      ' DHT11 reference: http://www.micropik.com/PDF/dht11.pdf
      ' Datasheet says resolution is 8 bits yet it sends 16 bits
      ' of data. This might be legacy from the higher resolution
      ' DHT22 sensor and the lower byte (the decimal part) is
      ' probably 0 all the time. No sensor here to verify with
      ' and datasheet is typical Chinese cut'n'paste stuff....
    
      ' Add the starbit stuff here !
    
      ' Read 16 bits of humidity data
      FOR x = 15 to 0 step - 1
        GOSUB GetBit
        Humidity.0[x] = BitValue
      NEXT x
    
      ' Read 16 bits of temperature data
      FOR x = 15 to 0 step - 1
        GOSUB GetBit
        Temperature.0[x] = BitValue
      NEXT x
    
      ' Read 8 bits of checksum data
      FOR x = 7 to 0 step - 1
        GOSUB GetBit
        Checksum.0[x] = BitValue
      NEXT x
    
      ' Checksum is the 8 bit sum of the 4 databytes
      ' this could be calculated and verified against
      ' the recieved checksum here.
    RETURN
    
    GetBit:
      PulsIn PORTA.5, 1, PulsWidth
      IF PulsWidth >=  9 AND PulsWidth <= 21 THEN BitValue = 0   ' if pulsewidth between 20 and 40uS then read as '0'
      IF PulsWidth >= 29 AND PulsWidth <= 21 THEN BitValue = 1   ' if pulsewidth between 60 and 80uS then read as '1'
    RETURN
    /Henrik.

  6. #6
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: PID thermostat Issue

    Quote Originally Posted by HenrikOlsson View Post

    Anyway, if you want to use the DHT11 instead of the DS18B20 what you want to do is make sure to scale the raw value so that they both give you the same value at a certain temperature. They might already DO that but you need to verify it. In the DS18B20 code your raw value seems to be the TempC variable while in the DHT11 code it's the temp variable.

    At a known temperature (roughly) run the 18B20 code and output the TempC variable on the LCD. What does it say? Something like 225 for 22.5 degrees?
    At the same temperature (roughly) run the DHT11 code and output the Temp variable on the LCD. What does it say? Something like 220 for 22.5 degrees? Or something else?

    /Henrik.
    Hi Henrik,

    I've merged the two sections of code for some crude testing (I'll try you refined version for the DTH sensor later). Yes you are correct in that the DS18B20 results are stored in the variable TempC and the result is a three digit value as you summarized - ie 234 would be 23.4 degreed C. The DHT does the same, but the value for the result is in double figures - I've changed the variable for the result of reading the DHT to TempB.

    Reading the values from the LCD using
    Code:
    lcdout  $FE,$C0,#tempb,"  ",#tempc
    I'm getting 19 for tempb (DTH sensor) and 205 (18B20 sensor) for tempc. I'm guessing that the DS18B20 is more accurate given the two sensors are side by side. I'm guessing if I multiply tempb by ten this should then in theory work - which it did.

    I'll play about with the code, but at least I've now got something to work with

Similar Threads

  1. DS18B20 thermostat
    By snuff28 in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 19th April 2013, 15:19
  2. 4 Channel Thermostat using PID loops
    By malc-c in forum Code Examples
    Replies: 36
    Last Post: - 18th March 2013, 11:17
  3. Thermostat for refrigerator
    By fratello in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 8th August 2012, 23:58
  4. Thermostat
    By koossa in forum Off Topic
    Replies: 15
    Last Post: - 16th November 2010, 11:06
  5. Pulse proportional thermostat
    By malc-c in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 12th December 2009, 03:00

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts