One Wire Temperature sensor (DS1820) to PC interface. 2010-07-05

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,
Code:
;*******************************************************************
;	Title	One Wire temperature reader
;	Author	Mike Webb
;	Date	10th January 2009
;	Pic	10F200 or 12F509
;*******************************************************************

errorlevel	-302,-224

#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	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
rlf	OwFlags,f
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

call	OwWriteByte
call	SendSpace
movlw	0x100-9
movwf	FSR		;very dodgey - relies on unused bits being 1
swapf	OwByte,W
call	SendNibble
movfw	OwByte
call	SendNibble
incfsz	FSR,F
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.
Author
Pommie
First release
Last update
Rating
0 ratings