Dallas DS18b20 temperature sensor reader -- fully working code

Rikki
2013-11-28
2014-08-25
  • Rikki

    Rikki - 2013-11-28

    By modifying the original code for the DS18s20 it was possible to make a fully functioning routine for the 12 bit DS18b20.

    Code is commented.

    All credits to Kent Schafer for the original code . Thank you Kent for the head start.

    Temperature (positive or negative) is returned in a signed integer called DSint
    Decimals are returned as a string called DSdec

    Just copy and paste the code below into a new file called DS18b20.h
    include this file in your main program code

    ' DS18b20 12 bit temperature sensor routines for the Great Cow BASIC compiler
    ' based on original code made by : Copyright (C) 2007 Kent Schafer
    '

    ' Modified by R. White (11/2013) to work with the 12 bit DS18b20 *
    '
    full temperature range from negative to positive as per datasheet
    ' NB will NOT work with DS18s20 as that is a 9 bit sensor***

    ' This library is free software; you can redistribute it and/or
    ' modify it under the terms of the GNU Lesser General Public
    ' License as published by the Free Software Foundation; either
    ' version 2.1 of the License, or (at your option) any later version.

    ' This library is distributed in the hope that it will be useful,
    ' but WITHOUT ANY WARRANTY; without even the implied warranty of
    ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    ' Lesser General Public License for more details.

    ' You should have received a copy of the GNU Lesser General Public
    ' License along with this library; if not, write to the Free Software
    ' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

    ' Original Notes: (these are original and left here for reference only .see Rev 1 notes below)
    ' This is a Dallas DS18b20 temperature device device program for Great Cow Basic.
    ' This is the minimal code to get a positive temperature reading in degrees
    ' Celsius. Has not been tested in Parasitic mode or with long lengths of wire.
    ' Kent Schafer Feb 12, 2007
    ' Rev0

    ' Rev1
    ' Modified by R. White (11/2013) to work with the 12 bit DS18b20 ****
    ' Uses Subroutine "ReadDigitalTemp" instead of function as it's complicated with decimal places
    ' modified to read negative number using XOR to convert 2's complement to signed integer
    ' Reads two bytes into 16 bit signed integer variable.
    ' A string varible "lookup table" stores the decimal digits.
    ' Timings lengthened slightly to handle long wires. Tested reliably with 3 meter cable.
    ' Oscilloscope shows 0 -> 5V (10% -90%) rise time of 14 uS with 3 Meter cable length
    ' Logic high stable time is 14uS to 28uS after pulse start
    ' serial pin needs to be defined in main program
    ' code below is commented to make it esay to follow

    'To read a value, call the ReadDigitalTemp subroutine.
    'DSint holds the decimal temperature
    'DSdec string holds the decimal places

    ' Port settings
    '#define DQ PortA.0 'better to set this port in main code as it changes from chip to chip

    Dim DSdata As Word 'need this for negative numbers . (Leave RXdata as a working byte variable)
    Dim DSdec as String 'need this for holding decimal place from pseudo "lookup table"
    Dim DSint as integer 'need this to return minus sign (set bit 15 = 1 (= negative))

    '=========ROM Commands for 1-Wire DS18S20======================================

    define SearchRom 240 '0xF0 (240)

            'Command for identifying Slave Rom codes, use as many
            'times as needed
    

    define ReadRom 51 '0x33 (051)

            'Command for single slave
    

    define MatchRom 85 '0x55 (085)

            'Command for master to identify a specific slave code
    

    define SkipRom 204 '0xCC (204)

            'Command for addressing all devices simultaneously
    

    define AlarmSearch 236 '0xEC (236)

            'Command is same as Search Rom to identify any alarm flags
    

    '==========Function Commands for for 1-Wire DS18S20=============================

    define ConvertT 68 '0x44 (68)

            'Protocol for Single Temp Conversion
    

    define WriteScratch 78 '0x4E (78)

            'Protocol for Write Scratchpad
    

    define ReadScratch 190 '0xBE (190)

            'Protocol for Read Scratchpad
    

    define CopyScratch 72 '0x48 (72)

            'Protocol for copying Scratchpad TH and TL
            'registers to EEPROM
    

    define RecallE2 187 '0xB8 (187)

            'Protocol for recalling alarm trigger values from EEPROM
    

    sub ReadDigitalTemp
    wait 250 ms ' Not needed but left in just in case
    MasterRST 'reset ds18b20
    PPulse 'request a presence pulse
    wait 1 ms
    'if mcp = 0 then return 'if no sensor present then don't bother attempting to read digital sensor. return asterix (ascii 42) to flag error
    OWout SkipRom 'bypass ds18b20 serial number read
    wait 1 ms
    OWout ConvertT 'instruct ds18b20 to begin temperature conversion to digital
    wait 1 s 'Need at least 750 milliseconds for 12 bit conversion with DS18b20

    MasterRST
    PPulse
    wait 1 ms
    OWout SkipRom 'bypass ds18b20 serial number read
    wait 1 ms
    OWout ReadScratch 'read temperature from db18b20
    wait 1 ms
    Owin 'receive temperature low byte from db18b20
    DSdata = RxData 'new first byte is low byte
    wait 1 ms
    Owin 'receive temperature high byte from db18b20
    DSdata_H = RxData 'new second byte is high byte (auto combined into 16 bit word)

    'XOR with 65535 and add oneto get 2's compliment

    If DSdata.15 = 1 then DSdata = (DSdata XOR 65535) + 1 'convert twos complement to decimal by xor'ing with 65535 and adding 1
    'only require if DS18b20 returns a negative number

    DSint = DSdata /[word] 16 ' shift right four times to lose lowest nibble (decimal data nibble). the variable now contains a round temperature number
    fraction=0
    fraction.0 = DSdata.0 'lowest nibble contains fraction of degree measured by sensor
    fraction.1 = DSdata.1
    fraction.2 = DSdata.2
    fraction.3 = DSdata.3

                                                'pseudo lookup table for decimal digits
    

    if fraction = 0 then DSdec = "0" 'manually enter decimal place numbers. Hey, its an atmega2560 there is 256K of memory available. And it's late.
    if fraction = 1 then DSdec = "0625"
    if fraction = 2 then DSdec = "125"
    if fraction = 3 then DSdec = "1875"
    if fraction = 4 then DSdec = "25"
    if fraction = 5 then DSdec = "3125"
    if fraction = 6 then DSdec = "375"
    if fraction = 7 then DSdec = "4375"
    if fraction = 8 then DSdec = "5"
    if fraction = 9 then DSdec = "5625"
    if fraction = 10 then DSdec = "625"
    if fraction = 11 then DSdec = "6875"
    if fraction = 12 then DSdec = "75"
    if fraction = 13 then DSdec = "8125"
    if fraction = 14 then DSdec = "875"
    if fraction = 15 then DSdec = "9375"

    If RxData.7 = 1 then 'rxData bit 7 will be =1 if negative temperature.
    DSint = DSint * -1 'multiply by -1 . DSint integer needs to be converted to negative number after calculations (which always return a positive number after xor) .
    end if

    end sub

    '-----SUBS-----------------------------------------

    Sub MasterRST 'Master reset low for minimum 480 us
    Dir DQ In
    Dir DQ Out
    Set DQ Off
    wait 60 10us 'new was 50 10us. changed to 60 10us for longer wires
    Dir DQ In 'HiZ
    end sub

    Sub PPulse 'Master receive DS18s20 presence pulse
    wait 100 us 'new was 70us . changed to 100us for long bus wires
    'If DQ 0 Then mcp = 2 'test code (flag that digital sensor is present)
    'cls 'test code
    'Print "OW Device ACK" 'test code
    'End if 'test code
    wait 43 10us
    Dir DQ In
    end sub

    Sub OWout (Command) #NR

    For ClocksA = 1 to 8
    Dir DQ Out
    Set DQ Off
    wait 3 us 'Need to release bus within 15 us
    If Command.0 On then
    Dir DQ In
    End if
    wait 100 us '60 us per AN2420 new datasheet indicates MAX delay is 120 us . changed to 100uS for longer wires. only relevant for writing zeros
    Dir DQ In 'HiZ the bus if still pulled low
    wait 3 us
    ROTATE Command Right 'The DS18s20 wants data LSB first
    Next ClocksA
    end sub

    Sub OWin
    For ClocksB = 1 to 8
    Rotate RxData Right 'The DS18s20 xmits data LSB first
    Dir DQ Out
    Set DQ Off 'Read time slot
    wait 6 us ' new minimum is 1uS
    Dir DQ In 'Release bus for one wire Reception
    wait 4 us
    If DQ On Then RxData.7 = 1 'new was "set rxdata 1" (and not working on 16f690)
    If DQ Off Then RxData.7 = 0 '
    new was "set rxdata 0" (and not working on 16f690)
    wait 60 us 'new change to 60 uS for use with longer wires
    Next ClocksB

    end sub

     
  • Anobium

    Anobium - 2014-08-25

    Uploaded an updated version of this code to the released code section of SourceForge, see https://sourceforge.net/p/gcbasic/code/HEAD/tree/GCBASIC/trunk/include/DS18B20.h

    I have updated header for copyright etc. This is now destined for general release. I will update the Help File as soon as practical.

    This header now has three functions:

    ReadDigitalTemp
    Readtemp
    Readtemp12

    See below for initial documentation:

      'To read a value, call the ReadDigitalTemp subroutine.
         'DSint holds the decimal temperature
         'DSdec string holds the decimal places
    
      ' Readtemp
        ' Reads temperature from a DS18B20 digital temperature sensor and store in
        ' the output variable.  The conversion takes up to 750ms.  Readtemp carries out a full 12 bit
        ' conversion and then rounds the result to the nearest full degree Celsius (byte
        ' value). For the full 12 bit value use the readtemp12 command.
    
        ' The temperature is read back in whole degree steps, and the sensor operates from
        ' -55 to + 125 degrees Celsius. Note that bit 7 is 0 for positive temperature values
        ' and 1 for negative values (ie negative values will appear as 128 + numeric value).
        ' Note the readtemp command does not work with the older DS1820 or DS18S20
        ' as they have a different internal resolution. This command is not designed to be
        ' used with parasitically powered DS18B20 sensors, the 5V pin of the sensor must
        ' always be connected.
    
      ' Readtemp12
        ' Reads 12 bit temperature data from a DS18B20 digital temperature sensor and
        ' store in variable. The conversion takes up to 750ms. Both readtemp and
        ' readtemp12 take the same time to convert.
        ' This command is for advanced users only. For standard ‘whole degree’ data use the readtemp command.
        ' The temperature is read back as the raw 12 bit data into a word variable (0.0625
        ' degree resolution). The user must interpret the data through mathematical
        ' manipulation. See the DS18B20 datasheet for more information on the 12 bit
        ' Note the readtemp12 command does not work with the older DS1820 or DS18S20 as they have a different internal resolution.
        ' This command is not designed to be used with parasitically powered DS18B20 sensors, the 5V pin of the sensor must be connected.
    
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks