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
Plug and Play
On EasyPIC board, put MCP9700A in DS1820 socket. Connect JP14 to RE2.
Circuit Schematic
MCP9700A circuit
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 ; } } }