Temperature Sensor (DS18S20 + PIC16F877A)
Here's a temperature sensor (thermometer) circuit that you can easily build. It uses the popular PIC 16F877A microcontroller. The temperature sensor is DS18S20. The DS18S20 communicates through the one-wire protocol. The PIC16F877A communicates with the DS18S20 with the one-wire protocol and gets the information for the temperature and displays it on the LCD.
The temperature range of this circuit is -55'C to +125'C.
The methods of communicating with the DS18S20 and sending/receiving commands, and reading the temperature value, are all explained in the DS18S20 datasheet (datasheets.maximintegrated.com/en/ds/DS18S20.pdf).
Here is the code for the PIC16F877A:
(You can download the source file from: https://rapidshare.com/files/1817975964/DS18S20PIC16F877A.c)
--------------------------------------------------------------------------------------------------------------
//Programmer: Syed Tahmid Mahbub
//Compiler: mikroC PRO for PIC v4.60
//Target PIC: PIC16F877A
--------------------------------------------------------------------------------------------------------------
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;
unsigned char TempH;
unsigned char TempL;
unsigned char TLow;
unsigned char vDisp[9];
unsigned char DP;
void main() {
PORTB = 0;
TRISB = 0;
LCD_Init();
LCD_CMD(_LCD_CURSOR_OFF);
LCD_CMD(_LCD_CLEAR);
PORTD = 0;
TRISD = 0x01;
delay_ms(200); //Wait for sensor and LCD to stabilize
//vDisp = "+124.5 'C"
vDisp[4] = '.';
vDisp[7] = 39; // '
vDisp[8] = 'C';
LCD_Out(1,1, "Temp:");
while (1){
OW_Reset(&PORTD, 0); // 'Reset command to initialize One-Wire
OW_Write(&PORTD, 0, 0xCC); // 'Skip ROM Command
OW_Write(&PORTD, 0, 0x44); // 'Convert_T command
delay_ms(800); // 'Provide delay for conversion
RD7_bit = ~RD7_bit;
OW_Reset(&PORTD, 0); // 'Reset command to initialize One-Wire
OW_Write(&PORTD, 0, 0xCC); // 'Skip ROM Command
OW_Write(&PORTD, 0, 0xBE); // 'Read Scratchpad Command
TempL = OW_Read(&PORTD,0); //Read Temperature low byte
TempH = OW_Read(&PORTD,0); //Read Temperature high byte
DP = TempL & 0x01; // 'Check if Temperature is integer or fractional
if (TempH){ //If reading is negative
vDisp[0] = '-';
TempL = ((~TempL) + 1) >> 1;
}
else{
vDisp[0] = '+';
TempL = TempL >> 1; // 'Shift one position right (divide by 2) to get integer reading and get rid of decimal point
}
vDisp[1] = (TempL / 100) + 48; // 'Get hundreds and convert to ASCII
vDisp[2] = ((TempL / 10) % 10) + 48; // 'Get tens and convert to ASCII
vDisp[3] = (TempL % 10) + 48; // 'Get units and convert to ASCII
if (DP){ // 'If reading is fractional, ie has 0.5 at end
vDisp[5] = '5';
}
else{ // 'If reading is a whole number
vDisp[5] = '0';
}
Lcd_Chr(1,8, vDisp[0]);
Lcd_Chr(1,9, vDisp[1]);
Lcd_Chr(1,10, vDisp[2]);
Lcd_Chr(1,11, vDisp[3]);
Lcd_Chr(1,12, vDisp[4]);
Lcd_Chr(1,13, vDisp[5]);
Lcd_Chr(1,14, vDisp[6]);
Lcd_Chr(1,15, vDisp[7]);
Lcd_Chr(1,16, vDisp[8]);
}
}
--------------------------------------------------------------------------------------------------------------
Reference documents:
DS18S20 datasheet:datasheets.maximintegrated.com/en/ds/DS18S20.pdf
PIC16F877A datasheet: ww1.microchip.com/downloads/en/devicedoc/39582b.pdf
mikroC LCD library: http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/lcd_library.htm
mikroC One-Wire library: http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/onewire_library.htm
The temperature range of this circuit is -55'C to +125'C.
The methods of communicating with the DS18S20 and sending/receiving commands, and reading the temperature value, are all explained in the DS18S20 datasheet (datasheets.maximintegrated.com/en/ds/DS18S20.pdf).
Here is the code for the PIC16F877A:
(You can download the source file from: https://rapidshare.com/files/1817975964/DS18S20PIC16F877A.c)
--------------------------------------------------------------------------------------------------------------
//Programmer: Syed Tahmid Mahbub
//Compiler: mikroC PRO for PIC v4.60
//Target PIC: PIC16F877A
--------------------------------------------------------------------------------------------------------------
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;
unsigned char TempH;
unsigned char TempL;
unsigned char TLow;
unsigned char vDisp[9];
unsigned char DP;
void main() {
PORTB = 0;
TRISB = 0;
LCD_Init();
LCD_CMD(_LCD_CURSOR_OFF);
LCD_CMD(_LCD_CLEAR);
PORTD = 0;
TRISD = 0x01;
delay_ms(200); //Wait for sensor and LCD to stabilize
//vDisp = "+124.5 'C"
vDisp[4] = '.';
vDisp[7] = 39; // '
vDisp[8] = 'C';
LCD_Out(1,1, "Temp:");
while (1){
OW_Reset(&PORTD, 0); // 'Reset command to initialize One-Wire
OW_Write(&PORTD, 0, 0xCC); // 'Skip ROM Command
OW_Write(&PORTD, 0, 0x44); // 'Convert_T command
delay_ms(800); // 'Provide delay for conversion
RD7_bit = ~RD7_bit;
OW_Reset(&PORTD, 0); // 'Reset command to initialize One-Wire
OW_Write(&PORTD, 0, 0xCC); // 'Skip ROM Command
OW_Write(&PORTD, 0, 0xBE); // 'Read Scratchpad Command
TempL = OW_Read(&PORTD,0); //Read Temperature low byte
TempH = OW_Read(&PORTD,0); //Read Temperature high byte
DP = TempL & 0x01; // 'Check if Temperature is integer or fractional
if (TempH){ //If reading is negative
vDisp[0] = '-';
TempL = ((~TempL) + 1) >> 1;
}
else{
vDisp[0] = '+';
TempL = TempL >> 1; // 'Shift one position right (divide by 2) to get integer reading and get rid of decimal point
}
vDisp[1] = (TempL / 100) + 48; // 'Get hundreds and convert to ASCII
vDisp[2] = ((TempL / 10) % 10) + 48; // 'Get tens and convert to ASCII
vDisp[3] = (TempL % 10) + 48; // 'Get units and convert to ASCII
if (DP){ // 'If reading is fractional, ie has 0.5 at end
vDisp[5] = '5';
}
else{ // 'If reading is a whole number
vDisp[5] = '0';
}
Lcd_Chr(1,8, vDisp[0]);
Lcd_Chr(1,9, vDisp[1]);
Lcd_Chr(1,10, vDisp[2]);
Lcd_Chr(1,11, vDisp[3]);
Lcd_Chr(1,12, vDisp[4]);
Lcd_Chr(1,13, vDisp[5]);
Lcd_Chr(1,14, vDisp[6]);
Lcd_Chr(1,15, vDisp[7]);
Lcd_Chr(1,16, vDisp[8]);
}
}
--------------------------------------------------------------------------------------------------------------
Reference documents:
DS18S20 datasheet:
PIC16F877A datasheet: ww1.microchip.com/downloads/en/devicedoc/39582b.pdf
mikroC LCD library: http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/lcd_library.htm
mikroC One-Wire library: http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/onewire_library.htm
Comments
Post a Comment