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.
And a closer look,
The Schematic,
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,
I've attached a monochrome image. See below.
If you run hyperterminal you will get this,
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.
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 :
;******************************************************************* ; 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.