1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice
Pommie

One Wire Temperature sensor (DS1820) to PC interface.

Here is a project I worked on a while ago that I’ve finally got around to documenting. It inte

  1. Pommie
    Here is a project I worked on a while ago that I’ve finally got around to documenting.

    It interfaces Dallas One Wire (OW) temperature devices to a PC using the smallest Pic chip available, the 10f200. The 10f200 can hold 256 instructions and has 16 bytes of RAM so fitting the OW search algorithm in it was rather challenging. It can also use a 12F509.

    What the device actually does is to interrogate the Dallas chips one at a time, find their ROM IDs, do a conversion and send a string to the PC containing all the information. It is powered from the RS232 port and works with the 2 USB to RS232 converters that I have.

    Here it is with 3 DS13S20s attached. You can attach as many as you like in theory but you will probably have to add an external power supply.
    [​IMG]

    And a closer look,
    [​IMG]

    The Schematic,
    [​IMG]

    Parts list,
    A preprogrammed 10F200 or 12F509.
    2 x 1K resistors
    2 X 10uF electrolitic capacitors
    2 x 0.1uF capacitors
    1 x 1N4148 diode.
    1 x 78L05 voltage regulator

    The board,
    [​IMG]
    I've attached a monochrome image. See below.

    If you run hyperterminal you will get this,
    [​IMG]

    Not very useful and so I’ve written a little VB application to demonstrate how to extract the ROM and temperature information. See below. (anyone familiar with the Dallas devices will recognize the above as the ROM ID followed by the scratch pad area.)

    This is what the VB app does. This is the 3 ROM Ids and temperatures.
    [​IMG]


    The code is rather hard to follow as it uses every trick in the book to minimize ROM and RAM usage. But here it is anyway,
    Code (text):

    ;*******************************************************************
    ;   Title   One Wire temperature reader
    ;   Author  Mike Webb
    ;   Date    10th January 2009
    ;   Pic 10F200 or 12F509
    ;*******************************************************************

        errorlevel  -302,-224
        radix   dec

        #ifdef  __12F509

        include "p12f509.inc"
        __CONFIG   _MCLRE_ON & _CP_OFF & _WDT_ON & _IntRC_OSC

    OW_Bit  equ 4
    RS_Bit  equ 2
    #define DataLow     b'11111111' - (1<<OW_Bit) - (1<<RS_Bit)
    #define DataHigh    b'11111111' - (1<<RS_Bit)
    #define DataBit     GPIO,OW_Bit
    #define b_RS232Out  GPIO,RS_Bit

        cblock  0x10
    RomBuffer:8 ;must be on 16 byte boundary
    temp
    OwByte:0
    Discrepency
    OutByte
    OwCount
    OwFlags
    BitIndex
    OwTemp
    LastDiscrepency
        endc
        endif  


        #ifdef  __10F200

        include "p10f200.inc"
        __CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_ON

    OW_Bit  equ 2
    RS_Bit  equ 0
    #define DataLow     b'11111111' - (1<<OW_Bit) - (1<<RS_Bit)
    #define DataHigh    b'11111111' - (1<<RS_Bit)
    #define DataBit     GPIO,OW_Bit
    #define b_RS232Out  GPIO,RS_Bit

        cblock  0x10
    RomBuffer:8     ;must be on 16 byte boundary
    temp
    OwByte:0    ;shares same location as Discrepency
    Discrepency
    OutByte
    OwCount
    OwFlags
    BitIndex
    OwTemp
    LastDiscrepency
        endc
        endif  


    #define OwSkipRom   0xcc
    #define OwConvert   0x44
    #define OwReadScratchPad    0xbe
    #define OwSearchRom 0xf0
    #define OwMatchRom  0x55

    #define b_OwPresent OwFlags,7
    #define b_ClrBit    OwFlags,6
    #define b_Done      OwFlags,5
    #define b_IsGetBit  OwFlags,4
    #define b_SendRom   OwFlags,3


            org 0

            movwf   OSCCAL
            clrf    7       ;turn of comparators (10f204/6)
    start       movlw   DataHigh    ;release line
            tris    GPIO
            movlw   0xdf        ;make GPIO2 I/O
            option
    First       clrf    LastDiscrepency ;restart search rom
            bcf b_Done     
    Next        bcf DataBit
            btfsc   b_Done      ;Have we completed list
            goto    start       ;Yes so restart
            clrf    BitIndex    ;start at first bit
            call    OwReset
            movlw   OwSearchRom ;Send search rom command
            call    OwWriteByte
            clrf    Discrepency
    GetBits     clrf    OwFlags     ;clear all bit variables
            call    OwReadBit   ;get bit A
            rlf OwFlags,f
            call    OwReadBit   ;get bit B
            rlf OwFlags,f
            movlw   0x03
            xorwf   OwFlags,w   ;If A=1 && B=1 then no devices present
            btfsc   STATUS,Z   
            goto    start       ;Restart
            xorlw   0x03
            btfss   STATUS,Z
            goto    Not00
    ;A=0 and B=0
            movfw   BitIndex
            subwf   LastDiscrepency,w
            btfsc   STATUS,Z
            goto    RomIndexEqualLD
            btfss   STATUS,C
            goto    RomIndexGTLD
            call    GetBit      ;RomIndex < LastDiscrepency
            btfss   STATUS,C
            goto    SetMarker
            goto    SendRomBit
    Not00       btfsc   OwFlags,1   ;set ROM bit to match Bit A
            call    SetBit
            btfss   OwFlags,1
            call    ClrBit
            goto    SendRomBit
    RomIndexGTLD    call    ClrBit      ;RomIndex > LastDiscrepency
    SetMarker   movfw   BitIndex
            movwf   Discrepency
            goto    SendRomBit
    RomIndexEqualLD call    SetBit      ;RomIndex = LastDiscrepency
    SendRomBit  call    GetBit
            call    OwSendCarry
            incf    BitIndex,f
            btfss   BitIndex,6
            goto    GetBits
            movfw   Discrepency
            movwf   LastDiscrepency
            btfsc   STATUS,Z
            bsf b_Done

            bsf b_SendRom   ;this was a subroutine but due to lack of
    OwMatch     call    OwReset     ;stack space it was put in line and a flag
            movlw   OwMatchRom  ;used to indicate the return address
            call    OwWriteByte
            movlw   RomBuffer   ;=0x10 = 0001 0000
            movwf   FSR
    SendRom     movfw   INDF
            call    OwWriteByte
            incf    FSR,F
            btfss   FSR,3       ;bodgey, FSR=0x18
            goto    SendRom
            btfss   b_SendRom
            goto    Continue    ;taken 2nd time around

            movlw   OwConvert
            call    OwWriteByte
            bcf b_SendRom

            bsf DataBit     ;drive data line high by
            movlw   DataLow     ;setting to output for
            tris    GPIO        ;parasitic power devices
            call    Delay1      ;wait for conversion
            movlw   DataHigh    ;release data line
            tris    GPIO        ;by setting to input

    SendSerial  decf    FSR,F       ;FSR=0x18 when entering
            btfss   FSR,4       ;will be clear when FSR=0x0f
            goto    OwMatch
            swapf   INDF,W
            call    SendNibble
            movfw   INDF
            call    SendNibble
            goto    SendSerial

    Continue    movlw   OwReadScratchPad
            call    OwWriteByte
            call    SendSpace
            movlw   0x100-9
            movwf   FSR     ;very dodgey - relies on unused bits being 1
    ReadLoop    call    OwReadByte  ;but no choice as out of RAM!!
            swapf   OwByte,W
            call    SendNibble
            movfw   OwByte
            call    SendNibble
            incfsz  FSR,F      
            goto    ReadLoop
            movlw   0x0d        ;send cr/lf
            call    Send
            movlw   0x0a
            call    Send
            goto    Next        ;go get next rom ID
           
    GetBit      bsf b_IsGetBit  ;Get bit RomBuffer[BitIndex]
            goto    DoBit
    ClrBit      bsf b_ClrBit    ;Clear bit RomBuffer[BitIndex]
            btfss   b_ClrBit
    SetBit      bcf b_ClrBit    ;Set bit RomBuffer[BitIndex]
            bcf b_IsGetBit
    DoBit       rrf BitIndex,W
            movwf   OwTemp
            rrf OwTemp,f
            rrf OwTemp,W
            andlw   0x07
            iorlw   RomBuffer
            movwf   FSR
            movfw   BitIndex
            andlw   0x07
            clrf    OwTemp
            movwf   OwCount
            bsf STATUS,C
    GetBitLoop  rlf OwTemp,f    ;will clear the carry bit
            decf    OwCount,F
            btfss   OwCount,7
            goto    GetBitLoop
            movfw   OwTemp
            btfsc   b_IsGetBit
            goto    DoGetBit    ;carry must be clear
            btfsc   b_ClrBit
            goto    IsClrBit
            iorwf   INDF,f
            retlw   0
    IsClrBit    xorlw   0xff
            andwf   INDF,f
            retlw   0
    DoGetBit    andwf   INDF,w
            btfss   STATUS,Z
            bsf STATUS,C
            retlw   0

    OwReset     movlw   DataLow     ;pull line low
            tris    GPIO
            movlw   .750/4      ;delay 750uS
            movwf   temp
            decfsz  temp,W
            goto    $-2
            movlw   DataHigh    ;release line
            tris    GPIO
        ;   movlw   .68/4       ;delay 68uS
        ;   movwf   temp
        ;   decfsz  temp,W
        ;   goto    $-2
        ;   bcf b_OwPresent
        ;   btfss   DataBit     ;pulled low?
        ;   bsf b_OwPresent ;yes so chip present
        ;   movlw   .480/4      ;delay 480uS
            movlw   .548/4      ;combined times
    ExitDelay   movwf   temp
            decfsz  temp,W
            goto    $-2
            retlw   0

    OwWriteByte movwf   OwByte      ;store byte to write
            movlw   .8      ;send 8 bits
            movwf   OwCount
    OwWriteLoop rrf OwByte,f    ;move bit to carry
            call    OwSendCarry ;send it
            decfsz  OwCount,F   ;sent all bits
            goto    OwWriteLoop ;no, so loop
            retlw   0

    OwReadByte  movlw   .8      ;get 8 bits
            movwf   OwCount
    OwReadByteLoop  call    OwReadBit   ;returns bit in carry
            rrf OwByte,F    ;move carry into byte
            decfsz  OwCount,F   ;finished?
            goto    OwReadByteLoop  ;no, so carry on
            retlw   0

    OwSendCarry btfss   STATUS,C    ;is carry clear
            goto    OwSend0     ;yes, so goto send zero
    OwSend1     movlw   DataLow     ;pull line low
            tris    GPIO
            goto    $+1     ;wait 4uS
            goto    $+1
            movlw   DataHigh    ;release line
            tris    GPIO
    Exit60      movlw   .60/4       ;wait 60uS
            goto    ExitDelay

    OwSend0     movlw   DataLow     ;pull line low
            tris    GPIO
            movlw   .60/4       ;wait 60uS
            movwf   temp
            decfsz  temp,W
            goto    $-2
            movlw   DataHigh    ;release line
            tris    GPIO
            movlw   .4/4
            goto    ExitDelay

    OwReadBit   movlw   DataLow     ;pull line low
            tris    GPIO
            goto    $+1     ;wait 4uS
            goto    $+1
            movlw   DataHigh    ;release line
            tris    GPIO
            movlw   .12/4       ;Wait 12uS
            movwf   temp
            decfsz  temp,W
            goto    $-2
            bcf STATUS,C
            btfsc   DataBit
            bsf STATUS,C
        ;   movlw   .60/4       ;Wait 60uS
            goto    Exit60      ;Delay

    SendSpace   movlw   ' '     ;0x20
            goto    Send

    SendNibble  andlw   0fh     ;keep lower nibble
            movwf   temp        ;save for later
            movlw   0x100-10    ;test if greater
            addwf   temp,W      ;than 10
            movlw   "0"     ;add "0"
            btfsc   STATUS,C    ;or, if greater than 10
            movlw   "0"+7       ;add "A"-10
            addwf   temp,W      ;do add and fall through to send it
       
    Send        movwf   OutByte     ;sends data inverted so no MAX232 needed
            bsf b_RS232Out  ;start bit
            call    BitDelay
            bsf STATUS,C    ;will be first stop bit
    SendLoop    rrf OutByte,F   ;move bit to carry
            bsf b_RS232Out
            btfsc   STATUS,C
            bcf b_RS232Out
            call    BitDelay
            bcf STATUS,C    ;ensure 0 shifted into outbyte
            movfw   OutByte     ;will be zero when 8 bits + 1 stop bit sent
            btfss   STATUS,Z
            goto    SendLoop
            bcf DataBit     ;ensure data line is low

    ;fall through for second stop bit.

    ; at 1 meg instructions and 9600 baud
    ; delay is 1,000,000/9600 = 104 cc
    ; the calling loop and the call/return = 13
    ; therefore delay needs to be 91 cycles

    BitDelay    movlw   .30
            movwf   temp
    DelayLoop   decfsz  temp,F;     (3*30)-1 = 89 + 2 = 91
            goto    DelayLoop
            clrwdt          ;kick the dog
            retlw   0

    Delay1      clrf    OwTemp      ;approx 1 second delay
            movlw   .40
            movwf   OwCount
    del     call    BitDelay
            decfsz  OwTemp,F
            goto    del
            decfsz  OwCount,F
            goto    del
            retlw   0



        if  ($>0xff)
        messg   "Memory Overflow"
        endif
        end
     
    Note, it is essential that the pic has the correct oscillator calibration value so use a new one or recalibrate it with the Pickit2 software.

    The attachments are the VB files, Hex files and board image.

    Mike.