In this experiment, we are going to build a digital temperature meter using DS1820 connected to our PIC16F628A development board. The temperature value will be displayed on the LCD display. I have modified the sample program that comes with the compiler according to our PIC board requirements. Also I have elaborated comments in the program so that every step will be more clear to the readers.
Experimental Setup:
The experimental setup is very straight-forward. Place DS1820 device on the three-pin female header that we recently added to our board. And also connect the data pin of DS1820 to RB.0 pin of PIC16F628A using a jumper wire.
Software:
Here is the program written in microC that reads temperature values from DS1820 device using OneWire Library.
/* Project name:
One Wire Communication Test between PIC16F628A and DS1820
* Copyright:
(c) Rajendra Bhatt, 2009.
* Description:
This code demonstrates how to use One Wire Communication Protocol
between PIC16F628A and a 1-wire peripheral device. The peripheral
device used here is DS1820, digital temperature sensor.
MCU: PIC16F628A
Oscillator: XT, 4.0 MHz
*/
// LCD connections definitions
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD connections definitions
// String array to store temperature value to display
char *temp = "000.00";
// Temperature Resolution : No. of bits in temp value = 9
const unsigned short TEMP_RES = 9;
// Variable to store temperature register value
unsigned temp_value;
void Display_Temperature(unsigned int temp2write) {
const unsigned short RES_SHIFT = TEMP_RES - 8;
// Variable to store Integer value of temperature
char temp_whole;
// Variable to store Fraction value of temperature
unsigned int temp_fraction;
unsigned short isNegative = 0x00;
// check if temperature is negative
if (temp2write & 0x8000) {
temp[0] = '-';
// Negative temp values are stored in 2's complement form
temp2write = ~temp2write + 1;
isNegative = 1; // Temp is -ive
}
// Get temp_whole by dividing by 2 (DS1820 9-bit resolution with
// 0.5 Centigrade step )
temp_whole = temp2write >> RES_SHIFT ;
// convert temp_whole to characters
if (!isNegative) {
if (temp_whole/100)
// 48 is the decimal character code value for displaying 0 on LCD
temp[0] = temp_whole/100 + 48;
else
temp[0] = '0';
}
temp[1] = (temp_whole/10)%10 + 48; // Extract tens digit
temp[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
temp[4] = temp_fraction/1000 + 48; // Extract tens digit
temp[5] = (temp_fraction/100)%10 + 48; // Extract ones digit
// print temperature on LCD
Lcd_Out(2, 5, temp);
}
void main() {
CMCON |= 7; // Disable Comparators
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 3, "Temperature: ");
// Print degree character, 'C' for Centigrades
Lcd_Chr(2,11,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,12,'C');
//--- main loop
do {
//--- perform temperature reading
Ow_Reset(&PORTB, 0); // Onewire reset signal
Ow_Write(&PORTB, 0, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTB, 0, 0x44); // Issue command CONVERT_T
Delay_ms(600);
// If this delay is less than 500ms, you will see the first reading on LCD
//85C which is (if you remember from my article on DS1820)
//a power-on-reset value.
Ow_Reset(&PORTB, 0);
Ow_Write(&PORTB, 0, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTB, 0, 0xBE); // Issue command READ_SCRATCHPAD
// Read Byte 0 from Scratchpad
temp_value = Ow_Read(&PORTB, 0);
// Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
temp_value = (Ow_Read(&PORTB, 0) << 8) + temp_value;
//--- Format and display result on Lcd
Display_Temperature(temp_value);
} while (1);
}
Experimental Output:
The temperature reading will be displayed on the LCD screen and will be updated every 600ms. Look at some snapshots below showing output.
Experimental Setup:
The experimental setup is very straight-forward. Place DS1820 device on the three-pin female header that we recently added to our board. And also connect the data pin of DS1820 to RB.0 pin of PIC16F628A using a jumper wire.
Circuit Diagram
Here is the program written in microC that reads temperature values from DS1820 device using OneWire Library.
/* Project name:
One Wire Communication Test between PIC16F628A and DS1820
* Copyright:
(c) Rajendra Bhatt, 2009.
* Description:
This code demonstrates how to use One Wire Communication Protocol
between PIC16F628A and a 1-wire peripheral device. The peripheral
device used here is DS1820, digital temperature sensor.
MCU: PIC16F628A
Oscillator: XT, 4.0 MHz
*/
// LCD connections definitions
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD connections definitions
// String array to store temperature value to display
char *temp = "000.00";
// Temperature Resolution : No. of bits in temp value = 9
const unsigned short TEMP_RES = 9;
// Variable to store temperature register value
unsigned temp_value;
void Display_Temperature(unsigned int temp2write) {
const unsigned short RES_SHIFT = TEMP_RES - 8;
// Variable to store Integer value of temperature
char temp_whole;
// Variable to store Fraction value of temperature
unsigned int temp_fraction;
unsigned short isNegative = 0x00;
// check if temperature is negative
if (temp2write & 0x8000) {
temp[0] = '-';
// Negative temp values are stored in 2's complement form
temp2write = ~temp2write + 1;
isNegative = 1; // Temp is -ive
}
// Get temp_whole by dividing by 2 (DS1820 9-bit resolution with
// 0.5 Centigrade step )
temp_whole = temp2write >> RES_SHIFT ;
// convert temp_whole to characters
if (!isNegative) {
if (temp_whole/100)
// 48 is the decimal character code value for displaying 0 on LCD
temp[0] = temp_whole/100 + 48;
else
temp[0] = '0';
}
temp[1] = (temp_whole/10)%10 + 48; // Extract tens digit
temp[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
temp[4] = temp_fraction/1000 + 48; // Extract tens digit
temp[5] = (temp_fraction/100)%10 + 48; // Extract ones digit
// print temperature on LCD
Lcd_Out(2, 5, temp);
}
void main() {
CMCON |= 7; // Disable Comparators
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 3, "Temperature: ");
// Print degree character, 'C' for Centigrades
Lcd_Chr(2,11,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,12,'C');
//--- main loop
do {
//--- perform temperature reading
Ow_Reset(&PORTB, 0); // Onewire reset signal
Ow_Write(&PORTB, 0, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTB, 0, 0x44); // Issue command CONVERT_T
Delay_ms(600);
// If this delay is less than 500ms, you will see the first reading on LCD
//85C which is (if you remember from my article on DS1820)
//a power-on-reset value.
Ow_Reset(&PORTB, 0);
Ow_Write(&PORTB, 0, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTB, 0, 0xBE); // Issue command READ_SCRATCHPAD
// Read Byte 0 from Scratchpad
temp_value = Ow_Read(&PORTB, 0);
// Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
temp_value = (Ow_Read(&PORTB, 0) << 8) + temp_value;
//--- Format and display result on Lcd
Display_Temperature(temp_value);
} while (1);
}
Experimental Output:
The temperature reading will be displayed on the LCD screen and will be updated every 600ms. Look at some snapshots below showing output.
Hi mr Raj.
ReplyDeleteDo you have a single example with 7 segments displays?
Tanks.
Hello Mr. Raj i have been testes both version of temperature sensor (DS1820 and DS18B20) and i found a little bug, in both version cannot display symbol "-" when read a negative temperature.
ReplyDeleteDo you have any idea how to solve this problem?
I try to solve the problem by myself, with no results.
By the way you did a great gob with this site.
Regards,
ducu
My code should work to display negative temperature too. Negative temperature are in 2's complement form, see my code
ReplyDelete// check if temperature is negative
if (temp2write & 0x8000) {
temp[0] = '-';
// Negative temp values are stored in 2's complement form
temp2write = ~temp2write + 1;
}
Fabio,
ReplyDeleteHere is my experiment with Seven segment Displays.
http://pic16f628a.blogspot.com/2009/10/experiment-no-5-multiplexed-seven.html
Dear Sir,
ReplyDeleteI used DS18S20. it did not works it shows 'Temperature:
000.00 C
no temperature detects. I use same code. whats wrong?
Nimal
Try increasing the delay_ms(600) to delay_ms(800) and see if it works.
ReplyDeleteOw_Write(&PORTB, 0, 0x44);
Delay_ms(800);
// If this delay is less than 500ms, you will see the first reading on
Also Read this
http://www.picbasic.co.uk/forum/showthread.php?t=13388
Thanks, Now its working.
ReplyDeleteIf LCD is 10 meters away from DS18S20 what kind of cable I have to used?
ReplyDeletei want this circuit diagram anybody help me
ReplyDeleteKrishna,
ReplyDeleteI have posted the circuit diagram. Enjoy!
do you have hex for this example
ReplyDeleteKuzmin,
ReplyDeleteHere it is
http://embedded-lab.com/uploads/HexFiles/PIC16F628A/PIC16F628A_DS1820.zip
hello;
ReplyDeleteI'm working on a development board where the peak and the LCD are already connected together, I have to connect the sensor SRF02 as extention, but when I run C code on the LCD I get a funny message! and I don't know whence the error!
Here is my source code I use(MikroC):
/*Project name: SRF02 */
#include "SRF02_SIMPLE.h"
// LCD module connections
sbit LCD_RS at LATD2_bit;
sbit LCD_EN at LATD3_bit;
sbit LCD_D4 at LATD4_bit;
sbit LCD_D5 at LATD5_bit;
sbit LCD_D6 at LATD6_bit;
sbit LCD_D7 at LATD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
void delay2S(){ // 2 seconds delay function
Delay_ms(1000);
}
//char someData[] = "SRF02";
// Main
void main()
{
int i;
char tmpdata;
SRF02_SIMPLE_Init(); // performs I2C initialization
ADCON1 |= 0x0F; // Configure AN pins as digital
CMCON |= 7;
while(1)
{ // Disable comparators
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR); // clear Lcd
Lcd_Cmd(_LCD_CURSOR_OFF); // set cursor off
// Example for single-byte read
i = 1;
tmpdata = 1;
while ((tmpdata = SRF02_SIMPLE_RdSingle(i)) != 0)
{
Lcd_Out(1,1,"la distance est"); // Write string
Lcd_Out(2,1,tmpdata); // Write string
Lcd_Out(2,15,"cm");
delay2S();
tmpdata++;
Lcd_Out(1,1,"la distance est"); // Write string
Lcd_Out(2,1,tmpdata); // Write string
Lcd_Out(2,14,"cm");
delay2S();
}
i++ ;
}
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,4,"la distance est:");
SRF02_SIMPLE_RdSeq(2, tmpdata,10);
Lcd_Out(2,1,tmpdata);
}
//}
// SRF02 read library
//--------------- Performs SRF02 Init
void SRF02_SIMPLE_Init() {
I2C1_Init(100000);
}
//--------------- Reads data from SRF02 - single location (random)
unsigned short SRF02_SIMPLE_RdSingle(unsigned short rAddr)
{
unsigned short reslt;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(0x70); // send byte via I2C1 (device address + W)
I2C1_Wr(0x00);
I2C1_Wr(0x51); // command to start raging in cm
I2C1_stop(); // send stop sequence
delay_ms(70); // delay for 70ms.
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(0x70); // send byte via I2C1 (device address + W)
I2C1_Wr(rAddr); // send byte (data address)
I2C1_Repeated_Start(); // issue I2C1 signal repeated start
I2C1_Wr(0x71); // send byte (device address + R)
reslt = I2C1_Rd(0u); // Read the data (NO acknowledge)
while (!I2C1_Is_Idle())
asm nop; // Wait for the read cycle to finish
I2C1_Stop();
return reslt;
}
//--------------- Reads data from SRF02_SIMPLE - sequential read
void SRF02_SIMPLE_RdSeq(unsigned short rAddr,
unsigned char *rdData,
unsigned short rLen) {
unsigned short i;
I2C1_Start(); // issue I2C1 start signal
I2C1_Wr(0x70); // send byte via I2C1 (device address + W)
I2C1_Wr(rAddr); // send byte (address of SRF02 location)
I2C1_Repeated_Start(); // issue I2C1 signal repeated start
I2C1_Wr(0x71); // send byte (device address + R)
i = 0;
while (i < rLen) {
rdData[i] = I2C1_Rd(1u); // read data (acknowledge)
Delay_ms(20);
i++ ;
}
rdData[i] = I2C1_Rd(0u); // last data is read (no acknowledge)
I2C1_Stop();
}
I will be grateful if you can help me! Your suggestions/opinions are much much anticipated.
KL
Mr.Raj , circuit is not working,,showing 000.50'c on lcd .... ihave made the changes as u define delay 600 to 800 tb again nt working....i m using ds18s20 or ds18b20 ....tb stil same result 000.50'c .......plz help .. :(
ReplyDeletehi great project. But I have a problem... Im using ds1821c+ and the display shows 000.050 C, and I already changed 600ms to 800 and nothing happed.Any ideas?thank in advance for ypur help
ReplyDeleteCan you translate to hex file ?
ReplyDeletenice project its working
ReplyDeletehi it´s a great project,but does the pin 1 of the sensor needs to be grounded?
ReplyDeleteOr can be cutted?
thanks in advance
Nice project, but how I can read two sensors on different ports? Thanks!
ReplyDelete