Temperature couldn't be read

Discussion in 'Embedded Systems and Microcontrollers' started by zheyilew, Nov 4, 2013.

  1. zheyilew

    Thread Starter New Member

    Nov 4, 2013
    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

    Code ( (Unknown Language)):
    2. void main(void)
    3. {
    4.     init();
    5.     while(1)
    6.     {
    7.         LCDWrite("Room Temp: ",11,0,0);
    8.         sprintf(buffer,"%d",(int)temperatureA);
    9.         LCDWrite(buffer,2,0,12 );
    10.         LCDWrite("'C",2,0,15);
    11.     }  
    12. }
    14. void interrupt ISR()
    15. {
    16.     if((TMR0IE==1)&&(TMR0IF==1))
    17.     {
    18.         counter++;      
    19.         if(counter==31)//2 hz osccilatinge
    20.         {
    21.             //temperature sensor 1
    22.             ADCON0=0B00000001;         //AN0, ADC on
    23.             GO=1;       //Start conversion
    24.             while(ADCON0bits.GODONE==1);   //polling of GO/DONE' bit
    25.             result=ADRESL;
    26.             resulthi=ADRESH;
    27.             resulthi=resulthi<<8;
    28.             result|=resulthi;
    29.             temperatureA=(char)result*500/1023;//temperature formula for LM35
    30.             counter=0;//reset the 1Hz counter
    31.         }
    32.     }
    33. }
  2. JohnInTX


    Jun 26, 2012
    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.

    resulthi = resulthi<<8 clears a char.

    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.

    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: Nov 5, 2013
  3. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    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. :)
  4. zheyilew

    Thread Starter New Member

    Nov 4, 2013
    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.