• 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.
Resource icon

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
	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.
Author
Pommie
First release
Last update
Rating
0.00 star(s) 0 ratings

More resources from Pommie

EE World Online Articles

Loading

 
Top