// Thermometer with an LM335
// Hardware: experimental board for the PIC16F8877
// Web: http://www.eeng.biz/
//
// uC: PIC16F887 (fosc=4 MHz, Vdd=5 V nom.)
// Compiler: mikroC v8.2.0.0 or later
// Date: 07/25/2008
// Revised: 08/24/2008


// Configuration bits (Project -> Edit Project...):
// CONFIG1: _INTOSC_IO & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF &
// _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF & _DEBUG_OFF
// CONFIG2: _BOR40V & _WRT_OFF


// The LM335 generates an output voltage that is proportional to the absolute
// temperature (Kelvin degrees). Negative tempertures can be measured without a
// negative voltage reference.
// The output of the LM335 is read by the ADC of the PIC16F887. The mean of
// 10 readings is calculated and converted to C degrees.
// The value is displayed on the LCD.

// Notes:
// 1) the accuracy of the LM335 depends on the precision of the supply voltage, Vdd.



unsigned int val, t_int, t_dec;
double sum;
unsigned char j;
unsigned char txt[7];

void main()
{
    while(HTS==0);            // wait until the internal oscillator is stable

    ANSELH = 0;  		          // configure analog and digital inputs
    ANSEL  = 0b00001101;

    PORTA = 0;
    PORTC = 0;
    PORTB = 0;

    TRISA = 0b00011101;			  // I/O directions
    TRISB = 0b11001111;
    TRISC = 0b11110000;

    // inotialize the LCD
    Lcd_Custom_Config(&PORTC,3,2,1,0,&PORTA,7,1,6);  // initialize the LCD
    Lcd_Custom_Cmd(Lcd_CURSOR_OFF);                  // cursor OFF
    Lcd_Custom_Cmd(Lcd_CLEAR);                       // clear screen

    // write a message
    Lcd_Custom_Out(1, 1, "Reading LM335...");
    Lcd_Custom_Out(2, 1, "T = ");
    Lcd_Custom_Chr(2, 9, 223);            // °
    Lcd_Custom_Chr(2, 10, 'C');


    // ADC settings
    ADCON1 = 0b10000000;
    ADCON0 = 0b01000001;



    while(1==1)
    {
         sum = 0;
         for (j=0;j<10;j++)
         {
             Delay_ms(50);
             ADCON0.f1 = 1;            		  // start an A/D conversion
             while(ADCON0.f1 == 1);
             val = ADRESH;
             val <<= 8;
             val += ADRESL;
             sum += val;
         }
         // 'sum' is the sum of 10 readings


         sum = sum * 5 / 1023;
         sum = sum * 100 - 2731.5;    	   	// multiply by 100 and subtract a constant
                                         		// (Kelvin to Celsius conversion)

         t_int = ((unsigned int)sum) / 10;  // integer part and
         t_dec = ((unsigned int)sum) % 10;	// one fractional digit

         IntToStr(t_int, txt);			          // make the output string
         Lcd_Custom_Out(2, 1, txt);
         Lcd_Custom_Chr_Cp(',');
         Lcd_Custom_Chr_Cp(48+t_dec);     	// write to the LCD
         Lcd_Custom_Out(2, 1, "T = ");
         Delay_ms(1000);                  	// 1 second delay

    }

}



