Back to www.micro-examples.com

Pic Thermometer source code

Here is the MikroC source code :

Back to project page


/*
 *******************************************************************************
 * PIC DIGITAL THERMOMETER USING A SILICON JUNCTION SENSOR
 *******************************************************************************
 *
 * how to read temperature with no expensive digital sensor, nor NTC resistor
 *
 * source code example for mikroC users
 * feel free to use this code at your own risks
 *
 * target : PIC16F877A
 * crystal frequency does not matter: any from 4 to 20 Mhz will match, 8 Mhz is good.
 * HS clock, all flags to mC default values
 *
 * EP2/EP3 settings :
 * JP14 on RE2
 * SW2 switches 5 to 8 ON, all others off
 * pull-down on PORTD
 * pull-up on keyboard
 *
 * this programm has been tested with these kinds of silicon sensors on DS1820 socket :
 *
 * SILICON DIODE :
 *      cathode to ground (upper hole),
 *      anode to Vcc thru on-board 4k7 resistor (center hole)
 *      lower hole Vcc is unused
 *
 * NPN TRANSISTOR :
 *      emitter to ground (upper hole)
 *      base and collector tied together to Vcc thru on-board 4k7 resistor (center hole)
 *      lower hole Vcc is unused
 *
 * MTS102, MTS103, MTS105 sensor :
 *      mount it as a NPN transistor
 *
 * instructions for use :
 *      - mount your silicon sensor as described above
 *      - turn on the board
 *      - press RD7 to toggle FAHRENHEIT/CELCIUS display
 *      - take a thermometer and press RD0 or RD1 to adjust the reading on LED display
 *      - cold or heat the sensor to observe the result on LED display
 *
 * you will get a 2°C accuracy in the range of ambiant temperatures,
 * enough for fan control, low cost temperature display,
 * funny experiments with low-cost devices...
 *
 * Author : Bruno Gavand, April 2006
 * see more details on www.micro-examples.com
 *
 *******************************************************************************
 */
 
/*
 * keys definition
 */
#define INCREF          PORTD.F0
#define DECREF          PORTD.F1
#define UNIT            PORTD.F7

/*
 * segments definition
 */
#define SA      1
#define SB      2
#define SC      4
#define SD      8
#define SE      16
#define SF      32
#define SG      64
#define DP      128

/*
 * 7 segments table
 */
const   unsigned char segment[10] =
        {
        SA+SB+SC+SD+SE+SF,      // 0
        SB+SC,                  // 1
        SA+SB+SG+SE+SD,         // 2
        SA+SB+SG+SC+SD,         // 3
        SF+SG+SB+SC,            // 4
        SA+SF+SG+SC+SD,         // 5
        SA+SF+SG+SE+SC+SD,      // 6
        SA+SB+SC,               // 7
        SA+SB+SC+SD+SE+SF+SG,   // 8
        SA+SB+SC+SD+SF+SG       // 9
        } ;

/*
 * other symbols
 */
#define segDEG  SA+SB+SF+SG
#define segMINUS        SG
#define segF    SA+SE+SF+SG
#define segC    SA+SD+SE+SF

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

/*
 * display table
 */
unsigned char data[4] ;

/*
 * current digit to display
 */
unsigned char dcurr ;

/*
 * fahrenheit degrees flag
 */
unsigned char   fahrenheit = 0 ;

/*
 * result of the measure
 */
int     temp ;

/*
 * offset of the sensor
 */
int     ref = 116 ;

/*
 * convert binary to 7 segment digit, blank on zero is allowed by m
 */
unsigned char   modulo10Seg(unsigned char v, unsigned char m)
        {
        return((m || v) ? segment[v % 10] : 0) ;
        }

/*
 * interrupt routine, called on each timer0 overflow
 * period does not matter, as long as display does not flicker
 */
void    interrupt(void)
        {
        if(INTCON.T0IF)                         // timer 0 overflow ?
                {
                cntr++ ;                        // increment counter

                dcurr++ ;                       // next digit
                PORTB = 0 ;                     // turn digit off
                if(dcurr == 4)                  // last digit ?
                        {
                        PORTA = 0b00000001 ;    // light the first digit
                        dcurr = 0 ;
                        }
                else
                        {
                        PORTA <<= 1 ;           // light the next digit
                        }

                PORTB = data[dcurr] ;           // assign 7 segments value

                INTCON.T0IF = 0 ;               // done
                }
        }

main()
        {
	TRISB = 0 ;                             // set PORTB as output : 7 segments display
	PORTB = 0 ;

	TRISD = 0xff ;                          // set PORTD as input : keyboard

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

        for(;;)                                 // forever
                {
                if(cntr >= 4000)                // if enough time since last one
                        {
                        /*
                         * read the sensor
                         */
                        ADCON1 = 0x00 ;         // set PORTA as analog input
                        TRISA = 0xff ;          // set PORTA as inputs
                        temp = ref - Adc_Read(7) ;      // read RE2 ADC
                        ADCON1 = 0x07 ;         // set PORTA as digital IO
                        TRISA = 0 ;             // set PORTA as outputs

                        /*
                         * convert to readable value
                         */
                        temp *= 221 ;           // temperature coefficient of the silicon junction
                        temp /= 102 ;
                        temp = 25 + temp ;      // get the result in celcius
                        
                        if(fahrenheit)          // fahrenheit display enabled ?
                                {
                                temp = ((90 * temp) / 50 ) + 32 ;       //  convert C degrees to F
                                }

                        if(temp < 0)            // value to be displayed is negative ?
                                {
                                data[0] = segMINUS ;                    // yes, first digit is minus
                                data[1] = modulo10seg(temp / 10, 0) ;   // tenths are blanked if zero
                                }
                        else
                                {
                                data[0] = modulo10seg(temp / 100, 0) ;  // no, display hundreds (if they are)
                                data[1] = modulo10seg(temp / 10, 1) ;   // thenths
                                }
                        data[2] = modulo10seg(temp, 1) ;                // units
                        data[3] = fahrenheit ? segF : segC ;            // unit symbol

                        cntr = 0 ;              // reset counter
                        }

                /*
                 * process keys
                 */
                if(PORTD)                       // a key is pressed ?
                        {
                        if(INCREF)
                                {
                                ref++ ;         // increment the reference
                                data[0] = modulo10seg(ref / 1000, 0) ;  // display new reference
                                data[1] = modulo10seg(ref / 100, 1) ;
                                data[2] = modulo10seg(ref / 10, 1) ;
                                data[3] = modulo10seg(ref, 1) ;
                                }
                        else if(DECREF)
                                {
                                ref-- ;         // decrement the reference
                                data[0] = modulo10seg(ref / 1000, 0) ;  // display new reference
                                data[1] = modulo10seg(ref / 100, 1) ;
                                data[2] = modulo10seg(ref / 10, 1) ;
                                data[3] = modulo10seg(ref, 1) ;
                                }
                        else if(UNIT)
                                {
                                fahrenheit = !fahrenheit ;      // toggle celcius / fahrenheit
                                
                                /*
                                 * display new unit
                                 */
                                data[0] = 0 ;
                                data[1] = segDEG ;
                                if(fahrenheit)
                                        {
                                        data[2] = segF ;
                                        }
                                else
                                        {
                                        data[2] = segC ;
                                        }
                                data[3] = 0 ;
                                }

                        while(PORTD) ;          // wait for the key to be released
                        cntr = 0 ;              // reset counter
                        }
                }
        }