الجمعة، 7 سبتمبر، 2012

Temperature measurement using DS1820 sensor

The source of this project is LINK
Temperature measurement is one of the most common tasks performed by the microcontroller. A DS1820 sensor is used for measurement here. It is capable of measuring temperature in the range of -55 °C to 125 °C with 0.5 °C accuracy. For the purpose of transferring data to the microcontroller, a special type of serial communication called 1-wire is used.
Due to a simple and wide use of these sensors, commands used to run and control them are in the form of functions stored in the One_Wire library. There are three functions in total:
  • Ow_Reset is used for reseting sensor;
  • Ow_Read is used for receiving data from sensor; and
  • Ow_Write is used for sending commands to sensor.
This example implies the advantage in using libraries with ready-to-use functions. Concretely, you don’t have to study documentation provided by the manufacturer in order to use this sensor. It is sufficient to copy some of these functions in the program. If you want to know how any of them is declared, just right click on it and select the Help option.
/*Header******************************************************/

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

const unsigned short TEMP_RESOLUTION = 9;
char *text = "000.0000";
unsigned temp;

void Display_Temperature(unsigned int temp2write) {
    const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
    char temp_whole;
    unsigned int temp_fraction;
    
    // check if temperature is negative
    if (temp2write & 0x8000) {
        text[0] = '-';
        temp2write = ~temp2write + 1;
    }
    // extract temp_whole
    temp_whole = temp2write >> RES_SHIFT ;
    
    // convert temp_whole to characters
    if (temp_whole/100)
        text[0] = temp_whole/100 + 48;
    else
        text[0] = '0';
    
    text[1] = (temp_whole/10)%10 + 48; // Extract tens digit
    text[2] = temp_whole%10 + 48;      // Extract ones digit
    
    // extract temp_fraction and convert it to unsigned int
    temp_fraction = temp2write << (4-RES_SHIFT);
    temp_fraction &= 0x000F;
    temp_fraction *= 625;
    
    // convert temp_fraction to characters
    text[4] = temp_fraction/1000 + 48;     // Extract thousands digit
    text[5] = (temp_fraction/100)%10 + 48; // Extract hundreds digit
    text[6] = (temp_fraction/10)%10 + 48;  // Extract tens digit
    text[7] = temp_fraction%10 + 48;       // Extract ones digit
    
    // Display temperature on LCD
    Lcd_Out(2, 5, text);
}

void main() {
    ANSEL = 0;    // Configure AN pins as digital I/O
    ANSELH = 0;
    C1ON_bit = 0; // Disable comparators
    C2ON_bit = 0;
    
    Lcd_Init();   // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR);      // Clear LCD
    Lcd_Cmd(_LCD_CURSOR_OFF); // Turn the cursor off
    Lcd_Out(1, 1, " Temperature: ");    
    
    // Print degree character, 'C' for Centigrades
    Lcd_Chr(2,13,223);        // different LCD displays have different char code for degree
    // if you see greek alpha letter try typing 178 instead of 223
    
    Lcd_Chr(2,14,'C');
    
    //--- main loop
    do {
        //--- perform temperature reading
        Ow_Reset(&PORTE, 2);       // Onewire reset signal
        Ow_Write(&PORTE, 2, 0xCC); // Issue command SKIP_ROM
        Ow_Write(&PORTE, 2, 0x44); // Issue command CONVERT_T
        Delay_us(120);
        Ow_Reset(&PORTE, 2);
        Ow_Write(&PORTE, 2, 0xCC); // Issue command SKIP_ROM
        Ow_Write(&PORTE, 2, 0xBE); // Issue command READ_SCRATCHPAD
        temp = Ow_Read(&PORTE, 2);
        temp = (Ow_Read(&PORTE, 2) << 8) + temp;
        
        //--- Format and display result on Lcd
        Display_Temperature(temp);
        Delay_ms(500);
    } while (1);
}