Temperature couldn't be read

Thread Starter

zheyilew

Joined Nov 4, 2013
2
I'm using PIC18F45K22 as my microcontroller and RA0 wihich is also AN0 as my analog input. Below is my code, please help me to find out the mistakes i've made. The temperature being displayed is always 0

Rich (BB code):
void main(void)
{
    init();
    while(1)
    {
        LCDWrite("Room Temp: ",11,0,0);
        sprintf(buffer,"%d",(int)temperatureA);
        LCDWrite(buffer,2,0,12 );
        LCDWrite("'C",2,0,15);
    }   
}

void interrupt ISR()
{
    if((TMR0IE==1)&&(TMR0IF==1))
    {
        counter++;       
        if(counter==31)//2 hz osccilatinge
        {
            //temperature sensor 1
            ADCON0=0B00000001;         //AN0, ADC on
            GO=1;		//Start conversion
            while(ADCON0bits.GODONE==1);   //polling of GO/DONE' bit
            result=ADRESL;
            resulthi=ADRESH;
            resulthi=resulthi<<8;
            result|=resulthi;
            temperatureA=(char)result*500/1023;//temperature formula for LM35
            counter=0;//reset the 1Hz counter
        }
    }
}
 

JohnInTX

Joined Jun 26, 2012
4,787
You don't show
1) whether the result registers are integers or chars or what..
2) the setting for ADCON2 which determines how the 10 bit ADC result is justified in a (hopefully) 16bit integer.

And
resulthi = resulthi<<8 clears a char.

BUT
With ADCON2 not initialized, the result is left-justified i.e. the 10 bit result is
dddddddd dd000000 in ADRESH/L. Your shifting is not correct.

With left justified data its as simple as:
ADCresult = ADRESH; // put high byte of ADC conversion into lower 8 bits of ADCresult
ADCresult = (ADCresult << 8) | ADRESL; // shift it up and add in the L bits
or something like that.

EDIT: I think I got it so far.

temperatureA=(char)result*500/1023;//temperature formula for LM35
not sure what's going on here. What type is tempertatureA?

Finally, don't do things like this inside an interrupt. What you have shown should never be done inside a PIC interrupt. You are polling the ADC inside an interrupt service routine. You don't have to do that. Just start the conversion and wait for the result. Read the 2 result bytes (with the proper justification) into something you can use and proceed.
 
Last edited:

THE_RB

Joined Feb 11, 2008
5,438
Result and resulthi both need to be unsigned 16bit vars, you didn't show variable declarations.

Since you are using a 5v ADC Vref and the LM35 is good for about 100'C, the max normal (non hardware fault) ADC value will be about
100'C = 1v = 205
so the final result will never be much over 100, meaning temperature A can be of size unsigned char.

Taking that further, if the ADC is right justified and normal operation of the LM35 means the ADC value is under 205, this is less than 255 so you can get rid of the variable resulthi which simplifies your code.

The correct math should be *500 /1024 (not 1023!) and if you use that math you can also simplify in size;
*500 /1024
= *125 /256

so the largest calc you need to do is this;
205 *125 /256
which now fits well inside a 16bit unsigned variable, so you save the need to have a 32bit variable AND the big messy 32bit mult/divide libraries that your compiler would link in. :)
 

Thread Starter

zheyilew

Joined Nov 4, 2013
2
Thanks guys, the problem is solved.
If wasn't using interrupt, the temperature will be keep flickering, else while using interrupt, the temperature will be updating for example like once per second.
 
Top