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.
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,
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.
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.