Connect with us

OneWire - DS18B20 - PIC18F4550 code query

Discussion in 'Microcontrollers, Programming and IoT' started by GiedriusStasiulis, Jun 15, 2016.

Scroll to continue with content
  1. GiedriusStasiulis

    GiedriusStasiulis

    5
    0
    Jun 1, 2016
    Hello all,

    I am trying to read temperature from DS18B20 sensor using the OneWire protocol (non parasitic) and a PIC18F4550 (Aptinex development board with a built-in DS18B20). I've read both OneWire and DS18B20 datasheets, then I tried to look up some example codes just to understand how it all works, but the more I tried to understand the main function part, the more confused I got. I think I understand how reset, write and read functions work (clear explanations in the datasheet), but the part that confuses me the most is how to actually read data from the sensor. Below is a code that I found somewhere on the net, and after I build it, the result is in the pic. Also, after 3 seconds, the screen goes blank. The LCD module is 100% working. I really do not understand what is going on this part:

    tempL = read();
    tempH = read();

    tempL >>= 4;
    tempH <<= 4;
    tempH += tempL;
    tempL = DEC2BCD(tempH);

    Could someone please give any insights what is going on in that part and why the outcome is like that. Any help will be greatly appreciated!

    Code:
    #define _XTAL_FREQ 8000000
    
    #include <xc.h>
    #include <stdio.h>
    #include "delay.h"
    #include "LCD_4bit_config.h"
    
    #define _XTAL_FREQ 8000000
    
    #define DEC2BCD(dec) (((dec / 10) << 4) + (dec % 10))
    
    #define Skip_ROM 0xCC                // 0b11001100
    #define Convert_temperature 0x44    // 0b01000100
    #define Read_scratchpad 0xBE            // 0b10111110
    #define Write_scratchpad 0x4E
    
    #define Data_pin LATB0
    
    unsigned short tempL, tempH;
    
    char reset()
    {
    TRISB0 = 0;             // Drive bus low
    __delay_us(480);        // Delay 480us
    TRISB0 = 1;                // Release bus
    __delay_us(70);            // Delay 70us
    
    if (Data_pin == 0)        // Sample bus
        {
            __delay_us(410);
            return 0;        // Device present
        }
        else
        {
            __delay_us(410);
            return 1;        // No device present
        }
    }
    
    write(char a)
    {
        char i;
        Data_pin = 1;
       
            for (i=0;i<8;i++)
            {
                if ((a & (1<<i)) != 0 )
                {
                    TRISB0 = 0;            // Write 1 bit
                    Data_pin = 0;
                    __delay_us(6);
                    TRISB0 = 1;
                    __delay_us(64);   
                }   
               
                else
                {
                    TRISB0 = 0;            // Write 0 bit
                    Data_pin = 0;
                    __delay_us(60);
                    TRISB0 = 1;   
                    __delay_us(10);
                }
            }       
    }
    
    char read()
    {
        char i, result = 0;
        TRISB0 = 1;                //RB0 as input
           
            for (i=0;i<8;i++)
            {
                TRISB0 = 0;        // Drive bus low
                Data_pin = 0;    // Generate low pulse for 2us
                __delay_us(6);
                TRISB0 = 1;        // Release the bus
                __delay_us(9);
               
                if (Data_pin != 0)            // Sample bus to read bit from slave
                    {
                        result |= 1<<i;
                        __delay_us(55);   
                    }
                return result;   
            }   
    }
    
    main()
    {
        char s[20];
       
        OSCCON = 0b11110100;    // Set internal oscillator to 8 MHz
        ADCON1 = 0x0F;            // Set all pins as digital I/O
        CMCON = 0x07;             // Set all comparators as digital I/O
    
        TRISD = 0x00;                // Set PORTD as digital OUTPUT for the LCD
        LATD = 0;                  // Clear PORTD
       
        TRISB = 0xFF;                // Set PORTB as digital INPUT
        LATB = 0;                // Clear PORTB
       
        LCD_init();        // Initialize LCD module
        LCD_clr();
       
        while (1)
        {
            if (!reset())
            {
                write(Skip_ROM);           
                write(Convert_temperature);
                delay_ms(750);
               
                reset();
               
                write(Skip_ROM);
                write(Read_scratchpad);
               
                tempL = read();
                tempH = read();
               
                tempL >>= 4;
                tempH <<= 4;
                tempH += tempL;
                tempL = DEC2BCD(tempH);
                       
                sprintf(s,"%d  %d",tempL,tempH);
               
                LCD_setCursor(1,1);
                LCD_writeString(s);
            }   
        }
    }

    IMG_1352.JPG

    OneWire_DS18B20.JPG
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    10,579
    2,360
    Nov 17, 2011
  3. GiedriusStasiulis

    GiedriusStasiulis

    5
    0
    Jun 1, 2016
    Finally I had a break-trough (at least I think I have), when I decided to take baby steps and : 1. Read a presence pulse; 2. Read device family code; 3. Attempt to read temperature data. So far points 1 and 2 were accomplished successfully, I was able to read the presence pulse (0) and a family code (0x28). But the last point, I am still struggling bad. I understand that in order to read temperature values, I first need to write a command to convert temperature (0x44), then reset the OneWire, give a 0.75s delay for the conversion to be completed, and then write to the scratchpad 0xBE to read from the register. I've tried combining the codes I found in maxim website and as well some other codes I found all over the web. LCD now displays Temperature: 11, when my room temperature is currently ~27 degrees C. Please can someone check my codes to see whether there is an issue somewhere? Thanks!
    DS18B20 header file:
    Code:
    #define __XTAL_FREQ 8000000
    
    #define Data_pin RB2
    #define Data_bus TRISB2
    #define Skip_ROM 0xCC                // 0b11001100
    #define Convert_temperature 0x44    // 0b01000100
    #define Read_scratchpad 0xBE            // 0b10111110
    #define Read_deviceFamily 0x33
    
    int OneWire_reset()
    {
        Data_bus = 0;        //Set as output
        Data_pin = 0;        //Drive Low
        __delay_us(480);
        Data_bus = 1;        //Release, Set back as input
        __delay_us(70);
       
    if (Data_pin == 0)        // Sample bus
        {
            __delay_us(410);
            return 0;        // Device present
        }
        else
        {
            __delay_us(410);
            return 1;        // No device present
        }
    }
    
    int OneWire_readByte(void)
    {
        int l, result = 0;
        for(l=0;l<8;l++)
        {
            result >>= 1;
            if(OneWire_readBit())
                result |= 0x80;
        }
        return result;
    }
    
    int OneWire_readBit(void)
    {
        unsigned int Read_state = 0;
       
        Data_bus = 0;        //Set as output
        Data_pin = 0;        //Drive low
        __delay_us(6);
        Data_bus = 1;        //Release, set as input
        __delay_us(9);
        Read_state = Data_pin;
       
        return Read_state;
    }
    
    void OneWire_writeBit(unsigned int b)
    {
        Data_bus = 0;        //Set as output
           Data_pin = 0;        //Drive low
    
        if(b == 1)
        {
            __delay_us(3);
            Data_bus = 1;    //Release, set as input
            __delay_us(62);
        }
        else
        {
            __delay_us(57);
            Data_bus = 1;    //Release, set as input
            __delay_us(7);
        }
    }
    
    void OneWire_writeByte(unsigned int data)
    {
        int l;
        for(l=0;l<8;l++)
        {
            OneWire_writeBit(data & 0x01);
            data >>= 1;
        }
    }
    And the main code:
    Code:
    #define _XTAL_FREQ 8000000
    
    #include <xc.h>
    #include <stdio.h>
    #include "LCD_4bit_config.h"
    #include "DS18B20_config.h"
    #include "delay.h"
    
    OneWire_init()
    {
        int i;
        char buf1[10];
        char buf2[10];
           
        LCD_setCursor(1,1);
            LCD_writeString("Presence:");
           
            i = OneWire_reset();
               
            sprintf(buf1,"%d",i);
            LCD_setCursor(2,1);
            LCD_writeString(buf1);
           
            delay_ms(3000);
            LCD_clr();
               
            OneWire_reset();
           
            LCD_setCursor(1,1);
            LCD_writeString("Device family:");
               
            OneWire_writeByte(Read_deviceFamily);
               
            i = OneWire_readByte();
               
            sprintf(buf2,"%d",i);
            LCD_setCursor(2,1);
            LCD_writeString(buf2);
               
            delay_ms(3000);
            LCD_clr();
               
               OneWire_reset();
    }
    
    void main()
    {   
        char temp_lsb,temp_msb,temp;
       
        char buf3[10];
       
        char getBit[10];
    
        int k;
         
        OSCCON = 0b11110010;    // Set PIC18F4550 internal oscillator at 8MHz
       
        ADCON1 = 0x0F;            // Set all pins as digital I/O
            CMCON = 0x07;             // Set all comparators as digital I/O
       
        LATD = 0;                // Clear port D
        TRISD = 0b00000000;        // Set all port D pins as digital outputs
       
        LATB = 0;
        TRISB = 0x00;
       
            LCD_init();                // Initialize LCD
            OneWire_init();
                   
        while(1)
        {
                   
               if (!OneWire_reset())
               {
                   LCD_setCursor(1,1);
                LCD_writeString("Temperature:");
               
                OneWire_writeByte(Skip_ROM);         
                OneWire_writeByte(Convert_temperature);
           
                OneWire_reset();
                delay_ms(750);
               
                OneWire_writeByte(Skip_ROM);
                OneWire_writeByte(Read_scratchpad);
               
                for (k=0;k<9;k++)
                    {
                        getBit[k] = OneWire_readByte();   
                    }
                   
                temp_msb = getBit[1];
                temp_lsb = getBit[0];
                               
                temp = (temp_msb << 8) + temp_lsb;
               
                temp = temp >> 4;
               
                sprintf(buf3,"%d",temp);
                LCD_setCursor(2,1);
                LCD_writeString(buf3);
               
                delay_ms(1000);
                   }
           }
    }
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-