How come my DS18S20 code still works?


Closed Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Sep 2007
    Location
    Australia
    Posts
    15

    Default How come my DS18S20 code still works?

    I have been trying for 2 weeks to get my project working properly and now I am at my wits end.
    Part of my project is to read a DS18S20 and display the correct termperature on a 2x16 lcd display. I have searched the forum and all the examples for reading the device are the same so I just used it and it worked great.
    Problem is I cannot understand what the count_remain variable actually does. I am also confused about the count_per_c variable. So I did what any older person would do and just remarked them out of the code to see what would happen. But nothing did. Everything worked the same.

    the code is as follows:

    Hope someone can help

    Wilson

    @ DEVICE pic16F628a, INTRC_OSC_NOCLKOUT,LVP_OFF,WDT_OFF,MCLR_OFF,PROTEC T_OFF
    @ DEVICE pic16F628a, CPD_OFF
    trisa =%00100000
    trisb =%00000000
    cmcon =%00000111 'Comparators Off
    Define LCD_BITS 4
    Define LCD_DREG PORTB
    Define LCD_DBIT 0
    Define LCD_RWREG PORTA
    Define LCD_RWBIT 4
    Define LCD_RSREG PORTA
    Define LCD_RSBIT 3
    Define LCD_EREG PORTA
    Define LCD_EBIT 2
    Define LCD_COMMANDUS 5000
    Define LCD_DATAUS 100
    Define LCD_INITMS 2

    pause 100

    DQ VAR PORTB.5 ' One-wire data pin
    temperature VAR WORD ' Temperature storage
    'I removed the next two lines
    'count_remain VAR BYTE ' Count remaining
    'count_per_c VAR BYTE ' Count per degree C

    loop:
    LCDOUT $FE, 1
    LCDOut $FE, $C0, "Temp ", dec(temperature / 100)," C "

    OWOut DQ, 1, [$CC, $44] ' Start temperature conversion
    pause 750 'NEEDED FOR TEMP STABILIZING

    'and the following three lines
    'waitloop:
    'OWIn DQ, 4, [count_remain] ' Check for still busy converting
    'IF count_remain = 0 Then waitloop

    OWOut DQ, 1, [$CC, $BE] ' Read the temperature

    'as well as the last bits of the next two lines
    OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE]', Skip 4, count_remain, count_per_c]

    temperature = (((temperature >> 1) * 100) - 25)' + (((count_per_c - count_remain) * 100) / count_per_c)

    goto loop

  2. #2
    Join Date
    Sep 2007
    Location
    Australia
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    I have studied (but not fully understood) the 18S20 data sheet and concluded that all that needs to happen is...

    1: Initiate the device (start the conversion)
    2: Wait until the conversion is complete (pause for at least 750ms)
    3: Read what is in the register.

    I have it running okay. The LCD displays the raw temp i.e. the register value in decimal as well as hex and whether bit 0 is set or not.

    It seems that the value in the 18S20 register is actually 0.5 degrees centigrade units
    so I figured out why not just divide it by 2 to get the temperature.


    Code:
    @ DEVICE pic16F628a, INTRC_OSC_NOCLKOUT,LVP_OFF,WDT_OFF,MCLR_OFF,PROTECT_OFF
    @ DEVICE pic16F628a, CPD_OFF
    trisa =%00100000
    trisb =%00000000
    cmcon =%00000111 'Comparators Off
    Define LCD_BITS 4
    Define LCD_DREG PORTB
    Define LCD_DBIT 0
    Define LCD_RWREG PORTA
    Define LCD_RWBIT 4
    Define LCD_RSREG PORTA
    Define LCD_RSBIT 3
    Define LCD_EREG PORTA
    Define LCD_EBIT 2
    Define LCD_COMMANDUS 5000
    Define LCD_DATAUS 100
    Define LCD_INITMS 2
    
    pause 100
    
    DQ VAR PORTB.5 ' One-wire data pin
    temperature VAR WORD ' Temperature storage
    decimal var byte
    loop:
    	 
    OWOut DQ, 1, [$CC, $44] ' Start temperature conversion
    pause 750 'Needed to complete conversion
    OWOut DQ, 1, [$CC, $BE] ' Read the temperature
    OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE]
    
    'just check if bit0 is set
    decimal = temperature mod 2
    if decimal = 1 then 'if set, it must be .5
    decimal =5
    else
    decimal = 0
    endif
    
    ' raw value is the register value
    lcdout $FE,1, "Raw ", dec(temperature)," ", hex(temperature), " ", dec(decimal)
    
    LCDOut $FE, $C0, "Temp ", dec(temperature /2), ".", dec(decimal), " C"
    
    goto loop

    My LCD displays
    Raw 44 2C 0
    Temp 22.0 C

    When I touch the 18S20 for five seconds I get

    Raw 55 37 5
    Temp 27.5 C

    I am not sure how accurate it is because I do not have a reference temperature.
    I tried putting the 18S20 under my tongue but I got a shock.
    It seems to work okay but I am not convinced it is the correct way to go about it.

    Am I on the right track or just plain lucky that it works?

    Wilson

  3. #3
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,648


    Did you find this post helpful? Yes | No

    Lightbulb

    Hi,

    At this time, there's another thread running about the 18S20 or 18B20 ...

    just have a look to the methods used ...

    http://www.picbasic.co.uk/forum/showthread.php?t=7079

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  4. #4
    Join Date
    Sep 2007
    Location
    Australia
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Thanks Alain

    As I mentioned when I started the thread, I have already searched the forum read all the posts about the 18S20.
    The only thing I learned was that someone wrote a piece of code a long time ago and it seems to be the defacto standard- everyone uses it. The samples are the same, comments and all. Thats okay. Cutting and pasting is easy but it doesn't help me learn.

    Wilson

  5. #5
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,648


    Did you find this post helpful? Yes | No

    Talking

    Hi, Wilson

    Learning is on your own whatever the book ...

    so just trying to understand what happens is ... enough !!!

    Why not cut and paste ... if you know what you're pasting ...

    LOL ...

    Following you, ... you also can make it work without Owin ansd Owout ... just toggling pins on the adequate moment ...

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  6. #6
    Join Date
    Mar 2006
    Location
    Pennsylvania, USA.
    Posts
    130


    Did you find this post helpful? Yes | No

    Default

    Have you looked at Bruce's website? His Rentron Electronics site has some tutorials on using one wire devices, and explains it very well. He used the 18b20 in his examples, but I was able to get an 18s20 working after reading his explanations. I'm not where I can look it up, but I think the count remaining is a way of checking to see if the temperature conversion is completed or not, instead of just waiting a set amount of time like the 'pause' command does. So just pausing 750ms eliminates the need to check if the conversion is completed. Bruce also has an example that uses DIV32 to get better precision, but for my application anything within three degrees was close enough. Here is the link to the first example.

    http://www.rentron.com/PicBasic/PBP1-wire.htm

    Jerry.
    If your oscilloscope costs more than your car...

  7. #7
    Join Date
    Sep 2007
    Location
    Australia
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Thanks Jerry,

    Been there and it helped a little bit but I still don't know what the count_remain is.
    You could be right but I'm still not sure. To be honest, I don't think anybody knows exactly what it is. I'll just treat it as a Dallas magic number.

    I monitored its value and it jumps around from 1 to 16 when the device temperature rises and falls, but when the temperature stabilises, it just sits around 8 to 9.
    Anyhow I think I had a major breakthrough.

    The temperature of my device right now reads 002AH
    temperature2 = (temperature >> 1) effectively divides the value by 2 and gets rid of the radix point and now equals 0015h beacause of this move.

    Because Dallas gave us this formula with the assumption everyone can follow it,
    I just used it and hoped for the best.
    first I moved 0015h left 8 bits so it becomes 1500h
    then subtract 2.5 degree C (100h/4 = 40h =0.25C in Hex)
    so 1500h minus 0040h = 14C0h

    Dallas says count_per_C = 10h and I picked a number for count_remain - 9h
    so 10h minus 9h = 7h then Dallas says to multiply this by 100h then divide 10h
    okay, 7h * 100h = 0700h then divide by count_per_C (10h) = 0070h
    now I have 14C0h + 70h = 1530h
    so the 15h = 21C and the decimal part, 30h = 30h/100h = 48/256 = 0.1875 or 0.19
    So my display now shows 21.19 C

    Code:
    DQ VAR PORTB.5 ' One-wire data pin
    temperature VAR WORD ' Temperature storage
    temperature2 VAR WORD
    temperature3 VAR WORD
    count_remain VAR BYTE ' Count remaining
    count_per_c VAR BYTE ' Count per degree C
    fractemp var word
    
    loop:
    	 
    OWOut DQ, 1, [$CC, $44] ' Start temperature conversion
    pause 750 'NEEDED FOR TEMP STABILIZING
    
    waitloop:
    OWIn DQ, 4, [count_remain] ' Check for still busy converting
    IF count_remain = 0 Then waitloop
    OWOut DQ, 1, [$CC, $BE] ' Read the temperature
    OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE, Skip 4, count_remain, count_per_c]
    
    temperature2 = (temperature >> 1)
    
    temperature3= (temperature2 <<8 -64) + (((count_per_c - count_remain) * 100) / count_per_c)
    fractemp = ((temperature3 <<8 >>8*64) >>8)
    
    lcdout $FE,1, "Raw ", hex(temperature)," ", hex(temperature2), " ", dec(count_remain)
    lcdout $FE, $C0, "Real ", dec(temperature2), ".", dec2(fractemp)
    
    goto loop
    I don't know how accurate the fraction part is but I reckon the whole number is okay

    Bottom line is Jerry, I need someone willing to point out mistakes, offer sugestions or give constructive critisism.

    Wilson

  8. #8
    Join Date
    Mar 2006
    Location
    Pennsylvania, USA.
    Posts
    130


    Did you find this post helpful? Yes | No

    Default

    Hi Wilson,

    I am back where I can access better resources, and I think I can explain this satisfactorily now. The Dallas 18s20 offers a 9 bit thermometer that can measure from -55 degrees C. up to 125 degrees, a total range of 180 degrees C. Nine bit resolution allows for numbers from 0 to 511, so if the temperature is -55 degrees we would read a 0, and a reading of 511 would equate to 125 degrees. However, the ninth bit is used to provide a positive or negative reading, so our resolution now drops to 8 bits, from 0 to 255. Starting at -55 degrees C we should read 0, and +125 degrees will result in 255. Each step is roughly .7, but the device only measures in half degree steps, so as you guessed before, dividing by 2 will get you close. The Dallas 18B20 (a different chip!) offers user selectable resolution of 9 to 12 bits, consequently it can distinguish smaller changes in temperature, less than a half of a degree. The 18S20 uses the Count Remain byte to allow the user to calculate a little better resolution, so if you need to know the difference between say 20.5 degrees and 21.0 degrees you can calculate it if you need to. My guess is that internally the 9 bit chip really converts to higher resolution, and puts the extra bits in the Count Remain byte, but that is only my guess. The steps must be different, that would explain why the Count Per Degree C. is fixed at 10h in their formula.
    Realistically most of us don't need that much precision, anything within two or three degrees will be close enough. Dallas/Maxim shows the accuracy as being 0.5 degrees C. in the middle range, and most other manufacturers give an accuracy of +/- 2.0 degrees C. in their high precision sensors.
    In my earlier post I was mistaken (happens often!), you can perform time slot reads to see if the conversion is finished, or you can just pause 750ms like you did. Temperature doesn't usually change so fast that you can't waste a few milliseconds waiting for the conversion to finish, however if your application is doing other things as well then reading the time slot will be faster. If you were trying to service USB ports or something then you might not want to pause that long.
    I have two identical LABX-USB boards, running identical programs, using two identical 18S20 chips, and they are always two degrees different, even sitting side by side on my bench. Part of this discrepancy is likely due to my conversion to Fahrenheit, but it is close enough for my application.

    Jerry.
    If your oscilloscope costs more than your car...

  9. #9
    Join Date
    Sep 2007
    Location
    Australia
    Posts
    15


    Did you find this post helpful? Yes | No

    Default

    Hello Jerry.

    Excellent explanation. Now I understand it a lot better.

    You are right, I really do not need that much accuracy but it was good to find out how it can be done.

    Thanks very much.

    Wilson

  10. #10
    Join Date
    Aug 2007
    Posts
    15


    Did you find this post helpful? Yes | No

    Default Re: How come my DS18S20 code still works?

    my code just gives me the same output, I'm trying to use 4 7 segment displays can you all help me I am useing a 18f452
    clear
    define osc 20
    include "modedefs.bas"

    trisa=%11111111 ' a as input
    trisb=0 'port b as output
    trisd=%00001111 'portd as output 7-4 & 0-3 as input
    digit var byte
    pattern var byte
    digit1 var portd.7
    digit2 var portd.6
    digit3 var portd.5
    digit4 var portd.4
    'DS18S20_9bit con %00011111;93.75ms,0.5c
    'DS18S20_10bit con %00111111;187.5ms,0.25c
    'DS18S20_11bit con %01011111;375ms,0.125c
    DS18S20_12bit con %01111111;750ms,0.0625c default

    i var word
    DQ var PORTA.4 ' one wire data pin

    Temp_C var word
    SignC var word
    Busy var byte
    Negative var word
    Positive var word

    Temper var word
    count_remain var byte
    count_per_c var word


    digit4=0
    digit3=0
    digit2=0
    digit1=0



    Start:
    temper.lowbyte=0
    temper.highbyte=0
    count_remain=0

    owout DQ,1,[$CC,$B4] 'test for parasite power or external supplies
    pause 10 'wait for power test

    owout DQ,1,[$CC,$4E,0,0,DS18S20_12bit]


    owout DQ,1,[$CC,$44] 'start conversion

    Waitloop: ' check for still busy converting
    owin DQ,4,[count_remain]
    if Count_remain=0 then goto Waitloop

    owout DQ,1,[$CC,$BE] 'read scratchpad

    owin DQ,0,[temper.lowbyte,temper.highbyte,skip 4,count_remain,count_per_c]

    'calculate temperature in c to 2 decimal
    temp_C=((( Temper>>1)*100)-25)+(((count_per_c - count_remain)*100)/count_per_c)
    ' 7 segment 4 led display


    digit=Temp_C dig 3 'get 1000s
    gosub convert
    portb=pattern
    digit4=0
    digit3=0
    digit2=0
    digit1=1

    pause 5

    digit=Temp_C dig 2 'get 100s
    gosub convert
    portb=pattern
    digit4=0
    digit3=0
    digit2=1
    digit1=0
    portb.7=1

    pause 5

    digit=Temp_C dig 1 'get 10s
    gosub convert
    portb=pattern
    digit4=0
    digit3=1
    digit2=0
    digit1=0
    portb.7=0
    pause 5

    digit=Temp_C dig 0 'get 1s
    gosub convert
    portb=pattern
    digit4=1
    digit3=0
    digit2=0
    digit1=0

    pause 5
    digit4=0


    goto Start

    end


    convert:
    lookup digit,[$3f,$06,$5b,$4f,$66,$6d,$7d,$07,$7f,$6f],pattern
    portb=pattern
    return

Similar Threads

  1. Manchester coding/decoding Code help
    By financecatalyst in forum Code Examples
    Replies: 0
    Last Post: - 25th August 2009, 19:05
  2. Making Program Code Space your playground...
    By Melanie in forum Code Examples
    Replies: 15
    Last Post: - 19th July 2008, 08:26
  3. Why doesn't my code for 18f452 work on 18f252?
    By senojlr in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 23rd December 2005, 02:42
  4. Timer PIC16F57
    By leonel in forum mel PIC BASIC Pro
    Replies: 25
    Last Post: - 1st July 2005, 08:14
  5. Port control code Yelp!!
    By andyf in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 8th May 2005, 22:36

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts