Using a Microchip MCP9700A analog temperature sensor: cheap, easy to use, factory calibrated, plug and play.

Overview

Low power linear active thermistor. 3 pins (Ground, power, output), -40 to +125 C with +/- 2C accuracy, 2.3V to 5.5V supply, 6 uA operating current, +10mV/C temperature coefficient. 500mV output = 0C.

MCP9700A output voltage curve
MCP9700A output voltage curve

Plug and Play

On EasyPIC board, put MCP9700A in DS1820 socket. Connect JP14 to RE2.

Circuit Schematic

MCP9700A circuit
MCP9700A circuit
LCD thermometer display
LCD thermometer display

C Source Code

mcp9700a_thermometer.c
/*
 *******************************************************************************
 * PIC DIGITAL THERMOMETER USING A MICROCHIP MCP9700A ANALOG SENSOR
 *******************************************************************************
 *
 * source code example for mikroC users
 * feel free to use this code at your own risks
 *
 * target : PIC16F877A, 8 Mhz crystal
 * HS clock, no watchdog.
 *
 * easyPIC4 settings :
 *      MCP9700A on DS1820 socket, see web page for more details.
 *
 *******************************************************************************
 */

/*
 * LCD_printfix constants
 */
#define INT_RANGE   1000    // integer part : 3 digits
#define DEC_RANGE   10      // decimal part : 1 digit

/*
 * this counter is incremented on each TIMER0 overflow
 */
unsigned int cntr ;

long    temp ;          // Temperature in Celcius * 10
int     fahr ;          // Temperature in Fahrenheit * 10

/*
 * offset reference of the sensor : 0C is 500 mV => 102.4
 * since the sensor is factory calibrated, there is no need for adjustment
 */
int     ref = 1024 ;            // offset multiplied by 10 for tenth of degrees

/*
 * LCD character definitions (generated by mikroC LCD Custom Character tool)
 */
const char characterC[] = {8,20,8,0,3,4,4,3};   // C degree symbol
const char characterF[] = {8,20,8,0,7,4,6,4};   // F degree symbol

/*
 * print custom character on LCD
 */
void CustomChar(const char *def, unsigned char n, char pos_row, char pos_char)
        {
        char    i ;

        LCD_Cmd(64 + n * 8) ;
        for(i = 0 ; i <= 7 ; i++)
                {
                LCD_Chr_Cp(def[i]) ;
                }
        LCD_Cmd(LCD_RETURN_HOME) ;
        LCD_Chr(pos_row, pos_char, n) ;
        }

/*
 * print v with fixed-size integer and decimal parts
 */
void    LCD_printFix(unsigned int v)
        {
        unsigned int w ;
        unsigned int d ;
        unsigned char n ;
        unsigned char  blk = 1 ;           // zero blanking

        if(v >= 0)
                {
                LCD_Chr_Cp('+') ;
                }
        else
                {
                LCD_Chr_Cp('-') ;
                }

        v = abs(v) ;
        w = v / DEC_RANGE ;
        for(d = INT_RANGE / 10 ; d > 0 ; d /= 10)
                {
                n = (w / d) % 10 ;
                if(n)
                        {
                        blk = 0 ;
                        }
                if(blk)
                        {
                        LCD_Chr_Cp(' ') ;
                        }
                else
                        {
                        LCD_Chr_Cp('0' + n) ;
                        }
                }
        LCD_Chr_Cp('.') ;
        w = v % DEC_RANGE ;
        for(d = DEC_RANGE / 10 ; d > 0 ; d /= 10)
                {
                LCD_Chr_Cp('0' + (w / d) % 10) ;
                }
        }

/*
 * interrupt routine, called on each timer0 overflow
 */
void    interrupt(void)
        {
        if(INTCON.T0IF)
                {
                cntr++ ;
                INTCON.T0IF = 0 ;
                }
        }

/*
 * program entry
 */
void    main()
        {
        ADCON1 = 0x00 ;                         // PORTA as analog input
        TRISA = 0xff ;                          // PORTA as inputs
        TRISD = 0 ;                             // PORTD is output
        LCD_Init(&PORTD) ;                      // Initialize LCD on PORTD
        LCD_Cmd(Lcd_CLEAR) ;
        LCD_Cmd(Lcd_CURSOR_OFF) ;
        LCD_Out(1, 1, "MCP9700A EXAMPLE") ;

        OPTION_REG = 0x80 ;                     // start timer 0, no prescaler
        INTCON = 0xA0 ;                         // allow timer 0 overflow interrupt

        for(;;)
                {
                if(cntr >= 4000)                // enough time since last sample
                        {
                        /*
                         * read the sensor
                         */
                        temp = Adc_Read(7) * 10 - ref ;      // read RE2 ADC, adjust to 0C

                        /*
                         * get the result in celcius * 10
                         * sensor coefficient is +10mV/C
                         * ADC resolution is 5000/1024 = 4.88 mV
                         * one ADC point is 0.488C
                         */
                        temp *= 488 ;
                        temp /= 1000 ;

                        fahr = ((9 * temp) / 5 ) + 320 ;       // convert C to F * 10

                        /* print temperature in C on LCD */
                        LCD_Out(2, 1, "") ;
                        LCD_printFix(temp) ;
                        CustomChar(characterC, 0, 2, 7) ;

                        /* print temperature in F on LCD */
                        LCD_Out(2, 10, "") ;
                        LCD_printFix(fahr) ;
                        CustomChar(characterF, 1, 2, 16) ;

                        cntr = 0 ;
                        }
                }
        }