Hi All,

My latest project is a temperature controlled switch using PIC16F684 and an LM35DZ.
The LM35DZ output is 10mV per degree celcius. The routine is designed such that a relay is energised when the ambient temperature exceeds a pre-set temperature. The relay is de-energised once the ambient temperature drops below the pre-set temperature (less 1 degree hysteresis to stop relay chatter). All works well with my code for a short period of time (5-10 minutes) but then something strange happens with the display temperature - the temperature displays a random value (eg 4.7) instead of the correct value (eg 25.0) even though the voltage at the ADC input pin is correct (eg 250mV).

To help stabilise the result from the LM35DZ output I averaged 1000 samples in a While...Wend loop. I suspect the problem I am experiencing has something to do with this averaging routine, and I have been over it a dozen times, but I can't work out what goes wrong. As stated above, the routine works for a period of time but then falls over. I am investigating an alternate averaging routine but for my own sanity I need to find out why this routine fails after a short time. My code is as follows:


Code:
'****************************************************************
'*  Name    : TempCont.pbp                                      *
'*  Author  : Barry Phillips                                    *
'*  Notice  : Copyright (c) 2012 Baztronics                     *
'*          : All Rights Reserved                               *
'*  Date    : 16/12/2012                                        *
'*  Version : 1.0                                               *
'*  Notes   : Temperature Controlled Switch                     *
'*          :                                                   *
'****************************************************************
' PicBasic Pro program to display temperature from LM35DZ with
' 10-bit A/D conversion on LCD using PIC16F684 and switch relay on
' if ambient temperature is greater than temperature setting.
'
' LM35DZ output is 10mV per degree celcius
'
' 10-bit ADC equates to 4.88mV per step. For this application total accuracy
' has been forgone for simplicity and it is assumed that 1 step equates to 
' 5mV or 0.5 degree celcius. The displayed temperature is calculated by 
' ADCIN value multiplied by 5 (Adval*5).       
'
' Connect LM35DZ to RA0 (Pin 13)
' Connect switch "Up" to RA3 (Pin 4) 10k Pull-Up to +5V
' Connect switch "Down" to RA4 (Pin 3) 10k Pull-Up to +5V
' Connect switch "Bypass" to RA5 (Pin 2) 10k Pull-Up to +5V
' Connect LED to RC5 (Pin 5) via 470R to +5V
' Connect Relay drive to RC4 (Pin 6)
' Connect LCD D4 to RC0 (Pin 10)
' Connect LCD D5 to RC1 (Pin 9)
' Connect LCD D6 to RC2 (Pin 8) 
' Connect LCD D7 to RC3 (Pin 7)
' Connect LCD R/S to RA1 (Pin 12)
' Connect LCD E to RA2 (Pin 11)

' Define LCD registers and bits
Define	LCD_DREG	PORTC
Define	LCD_DBIT	0
Define	LCD_RSREG	PORTA
Define	LCD_RSBIT	1
Define	LCD_EREG	PORTA
Define	LCD_EBIT	2
Define	LCD_BITS	4
Define	LCD_LINES	2

CMCON0 = %00000111		' Disable comparators
ANSEL = %00000001		' Set AN0 as analogue input
TRISA = %00111001	    ' Set PORTA.0, PORTA.3 - .5 to input, all others output
TRISC = 0			    ' Set PORTC as output
high PORTC.5            ' Ensure LED turned off
low PORTC.4             ' Ensure Relay is turned off
ADCON1 = %01010000	    ' Set A/D clock Fosc/16
ADCON0 = %10000001	    ' Right justify result
						' Set Vref = Vdd
						' Select channel AN0
						' Turn on A/D converter
						
OSCCON = %01110001      ' Set clock frequency to 8MHz
define OSC  8
                        
' Define ADCIN parameters
Define	ADC_BITS	10	' Set number of bits in result
Define	ADC_CLOCK	3	' Set clock source (3=rc)
Define	ADC_SAMPLEUS 50	' Set sampling time in uS

Pause   100             ' Wait 0.1 second

' Set up variables
adval   var word        'ADCIN variable
Temp    var word        'Temperature variable
Tempset var word        'Temperature setting variable
avecount var word       'Temperature average counter
tempsum var word        'Temperature averaging variable
B4  var byte            'Bypass flag
Tempup var PORTA.4      'Define Tempup switch port
Tempdown var PORTA.3    'Define Tempdown switch port
Bypass var PORTA.5      'Define Bypass switch port
LED1 var    PORTC.5     'Define LED port output
Relay var   PORTC.4     'Define Relay port output
DATA    @1, 50          'Store 50 in EEPROM location 1
READ    1, Tempset      'Read EEPROM location 1 and save to Tempset
B4 = 0                  'Reset bypass flag
high LED1               'Ensure LED is off
low Relay               'Ensure Relay is off

Lcdout $fe, 1		     'Clear LCD
LCDOUT $FE, $80, "   BAZTRONICS"
LCDOUT $FE, $C0, "TEMP. CONTROLLER"
pause 3000              'Pause 3 seconds
LCDOUT $FE, 1           'Clear LCD

Again:
    avecount = 1                            'Reset averaging counter
    tempsum = 0                             'Reset averaging variable
    while avecount<1001                     'Loop 1000 times
        ADCIN 0, adval		                'Read channel 0 to adval
        tempsum = tempsum + adval           'sum temp average reading
        avecount = avecount + 1             'Increment counter
        if Bypass = 0 then manual           'Poll Bypass switch
        If B4 = 0 then                      'If Bypass not activated
            if Tempup = 0 then Upstep       'Poll "Up" switch
            if Tempdown = 0 then Downstep   'Poll "Down" switch
        endif
    wend
    Temp = tempsum/200
	Lcdout $FE, $80
    LCDOUT "  Temp: ", DEC Temp/10, ".", DEC1 Temp,$DF, "C  "'Display Temp
    If B4 = 1 then                          'Test Bypass flag status
        goto Again
    Else
        LCDOUT $FE, $C0+1     'Move cursor to beginning of second line
        lcdout "  Set: ", dec tempset/2, ".", dec1 tempset*5,$DF, "C  "'Display Tempset
    endif
    If temp>tempset*5 then  'Test ambient temperature vs temperature setting
        low LED1            'Turn on LED
        high Relay          'Turn on relay
        LCDOUT $FE, $C0, $DB
    endif
    if Temp < (tempset-2)*5 then'Test ambient temperature vs temperature setting    
        high LED1           'Turn off LED
        low Relay           'Turn off relay
        LCDOUT $FE, $C0, " "
    endif       
Goto Again		            'Do it forever

Upstep:
    If Tempset<99 then
        Tempset = Tempset + 1   'Increment temperature setting
    else
        Tempset = Tempset       'Set Tempset upper limit
    endif
    LCDOUT $FE, $C0+1           'Move cursor to beginning of second line
    lcdout "  Set: ", dec tempset/2, ".", dec1 tempset*5,$DF,"C  "'Display Tempset
    WRITE 1, Tempset            'Store new Tempset to EEPROM location 1
    Pause 250                   'Pause 250ms for switch debounce
    goto Again
    
Downstep:
    if Tempset>2 then
        Tempset = Tempset - 1   'Decrement temperature setting
    else
        Tempset = Tempset       'Set Tempset lower limit
    endif
    LCDOUT $FE, $C0+1           'Move cursor to beginning of second line
    lcdout "  Set: ", dec tempset/2, ".", dec1 tempset*5,$DF, "C  "'Display Tempset
    WRITE 1, Tempset            'Store new Tempset to EEPROM location 1
    pause 250                   'Pause 250ms for switch debounce
    goto again
    
Manual:
    If B4 = 0 then
        B4 = 1                      'Set Bypass flag
        low LED1                    'Turn on LED
        high Relay                  'Turn on Relay
        LCDOUT $FE, $C0+1           ' Move cursor to beginning of second line
        lcdout "  BYPASS MODE  "    'Display Bypass Mode message
    else
        B4 = 0                      'Reset Bypass flag
        high LED1                   'Turn off LED
        low Relay                   'Turn off Relay
        LCDOUT $FE, $C0+1           'Move cursor to beginning of second line
        lcdout "  Set: ", dec tempset/2, ".", dec1 tempset*5,$DF, "C  "'Display Tempset
    endif
    Pause 250                       'Pause 250ms for switch debounce
    do while Bypass = 0             'Loop until Bypass switch is released
    Loop
    goto again
       
End
Any assistance would be greatly appreciated.

Cheers
Barry
VK2XBP