Problem with temperature values in DS18B20 on PIC16F877

Status
Not open for further replies.

pasicr

Advanced Member level 1
Joined
Aug 13, 2005
Messages
440
Helped
39
Reputation
80
Reaction score
29
Trophy points
1,308
Location
Macedonia
Activity points
4,213
Hi for all,
I use dig. term. DS18B20 from Dallas with pic16f877 and 2x16 LCD,
I have this problem, on start everithing is OK, on LCD I see temp.,
but after abouth 60 seconds, thermometer still work but the value is incorect,
show temp arround 2,0 to 3,0 degree C, (the real temp in my room is around 24 C)
after one or two min, everithing is OK, the value is real,
if somebody have strange experience like this, share with me,
regards
 

DS18B20 on pic877

helo....pasicr...
hi, i m a beginner in pic.
currently, i have a final project which is temperature sensor ds18b20 wit 2x16 lcd using pic16f877. i have sum problem in write the mplab program....can u send me ur program??
 

DS18B20 on pic877

Hi there,

Did you ever manage to resolve your issue, only i'm on a similar path and wish to discuss the DS18B20 with someone who has some experiance of using one...

Don't worry I have 90% of the code written and schematic drawn up... I just have some possible timming issues and a printf problem...

But it's actual use I need to chat about...
 

DS18B20 on pic877

Hi hawk,
I can try to help, but the DS18S20 code I have is made using mikroBASIC, where there are inbuilt 1-wire functions for reading from and writing to the 1-wire device.
You might use mikroC, where you need not worry about timing and such as that is done by the compiler.

For anyone who needs it:
Code:
program Temp_DS1820

'Microcontroller: ATmega88 (Atmel AVR)
'Programming Language: BASIC
'Compiler: mikroBASIC PRO for AVR v2.10
'Sensor: DS18S20
'Programmer: Tahmid

dim LCD_RS as sbit at PORTB2_bit
dim LCD_EN as sbit at PORTB3_bit
dim LCD_D4 as sbit at PORTB4_bit
dim LCD_D5 as sbit at PORTB5_bit
dim LCD_D6 as sbit at PORTB6_bit
dim LCD_D7 as sbit at PORTB7_bit

dim LCD_RS_Direction as sbit at DDB2_bit
dim LCD_EN_Direction as sbit at DDB3_bit
dim LCD_D4_Direction as sbit at DDB4_bit
dim LCD_D5_Direction as sbit at DDB5_bit
dim LCD_D6_Direction as sbit at DDB6_bit
dim LCD_D7_Direction as sbit at DDB7_bit


sub procedure ConversionDelay()
    delay_ms(800)
end sub

sub procedure StabilizeDelay()
    delay_ms(200)
end sub

dim Temperature as word
dim TempH as byte
dim TempL as byte
dim TLow as byte
dim vDisp as string[9]
dim DecimalPoint as byte

main:
     DDRC = $FE 'RC0 input for One-Wire
     LCD_Init()
     LCD_Cmd(_LCD_CURSOR_OFF) 'LCD Cursor off
     LCD_Cmd(_LCD_CLEAR) 'Clear LCD
     StabilizeDelay() 'Wait for sensor and LCD to stabilize
     vDisp = "+124.5 'C"
     LCD_Out(1, 1, "Temp:")
     while true
         OW_Reset(PORTC, 0) 'Reset command to initialize One-Wire
         OW_Write(PORTC, 0, $CC) 'Skip ROM Command
         OW_Write(PORTC, 0, $44) 'Convert_T command
         ConversionDelay() 'Provide delay for conversion
         OW_Reset(PORTC, 0) 'Reset command to initialize One-Wire
         OW_Write(PORTC, 0, $CC) 'Skip ROM Command
         OW_Write(PORTC, 0, $BE) 'Read Scratchpad Command
         Temperature = OW_Read(PORTC, 0) 'Read Temperature low byte
         Temperature = Temperature + ((OW_Read(PORTC, 0)) << 8) 'Read Temperature high byte and convert low and high bytes to one 16-bit word
         TempH = Hi(Temperature) 'High 8 bits of Temperature
         TempL = Lo(Temperature) 'Low 8 bits of Temperature
         DecimalPoint = Temperature.B0 'Check if Temperature is integer or fractional
         if (Temperature and $8000) then 'If reading is negative
            vDisp[0] = "-"
            TempL = byte((not TempL + 1) >> 1)
         else 'If reading is positive
            vDisp[0] = "+"
            TempL = TempL >> 1 'Shift one position right (divide by 2) to get integer reading and get rid of decimal point
         end if
         vDisp[1] = TempL div 100 + 48 'Get hundreds and convert to ASCII
         vDisp[2] = (TempL div 10) mod 10 + 48 'Get tens and convert to ASCII
         vDisp[3] = TempL mod 10 + 48 'Get units and convert to ASCII
         if (DecimalPoint) then 'If reading is fractional, ie has 0.5 at end
            vDisp[5] = "5"
         else 'If reading is a whole number
            vDisp[5] = "0"
         end if
         LCD_Out(1, 8, vDisp) 'Show temperature
     wend
end.

Hope this helps.
Tahmid.
 

Hi, I tried this code and got a complier error on the line DDRC = $FE, commenting out this doesn't work (clearly) and I cannot find any information on what this is doing in the help. I am using a 16F877A PIC. Any ideas
 

Anyone knows how program PIC16F877A with DS1820 using MikroC
If yes please tell me some explainations in comments in the .c file
 

Hi, I tried this code and got a complier error on the line DDRC = $FE, commenting out this doesn't work (clearly) and I cannot find any information on what this is doing in the help. I am using a 16F877A PIC. Any ideas

The code is for the ATMEL AVR series of microcontrollers. Here the ATMEGA88 was the target microcontroller. So, quite a lot of changes are required to make it work for PIC16F877A.

Anyone knows how program PIC16F877A with DS1820 using MikroC
If yes please tell me some explainations in comments in the .c file

Here's a piece of code you should take a look at:

Code:
// 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

//  Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:
//  18S20: 9  (default setting; can be 9,10,11,or 12)
//  18B20: 12
const unsigned short TEMP_RESOLUTION = 12;

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) {
     LCD_Chr(2,4,'-');
     temp2write = ~temp2write + 1;
     }
  else{
     LCD_Chr(2,4,' ');
  }

  // 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

  // Print temperature on LCD
  Lcd_Out(2, 5, text);
}

void main() {
 ADCON1=0x06;

  Lcd_Init();                                    // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                           // Clear LCD
  Lcd_Cmd(_LCD_CURSOR_OFF);                      // Turn 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);
}

While not all lines are commented, you should be able to understand. Go through the datasheet of the DS1820 and also the mikroC one-wire library function ( https://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/onewire_library.htm ). If you still don't understand, feel free to ask questions.

Hope this helps.
Tahmid.
 
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…