PDA

View Full Version : DS18B20 connected to PIC16F628A



lilimike
- 27th November 2011, 21:07
I have found lots of threads about this and I have tried some code which gave me different values but the closest I can get to the real thing was from Bruce Reynolds.
I have one sensor which I was able to read its 64 bit serial code.
I adapter Bruce's code to display on an 2 line LCD using Darrel Taylor's LCD_AnyPin.
I have added a status LED that blinks every .5 sec to let me know the readins are happening and all I get is "T= +85.0 C "
I tried squeezing the sensor between my fingers, I tried to bring the soldering iron close to the sensor for a few seconds but no change.
If I pull out the sensor from the breadboard I get "T= -00.000 C"
I've tried using a bad 64 bit serial code to see what happens and doing so I get "T= -00.000 C" with or without the sensor present.
At this point I am wondering if my sensor is bad or if I missed something in the code...
Here is my code:

@ __config _INTOSC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_ON & _LVP_OFF & _CP_OFF
clear
DEFINE OSC 4
CMCON = 7
OPTION_REG = 0
INTCON = 0

LCD_DB4 VAR PORTB.0
LCD_DB5 VAR PORTB.1
LCD_DB6 VAR PORTB.2
LCD_DB7 VAR PORTB.3
LCD_RS VAR PORTA.4
LCD_E VAR PORTA.3
LCD_Lines CON 2 ' # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 50 ' Data delay time in us
LCD_COMMANDUS CON 2000 ' Command delay time in us

INCLUDE "LCD_AnyPin.pbp" ; *** Include MUST be AFTER LCD Pin assignments ****
PAUSE 500 : LCDOUT $FE,1 : PAUSE 250

;LCDOUT $FE,$80, "Display line 1"
;LCDOUT $FE,$C0, "Display line 2"
;DEFINE LOADER_USED 1 ' Boot loader is being used

StatLED var porta.1
Sign VAR BYTE ' + or - temp indicator
ID VAR BYTE[8] ' Array storage variable for 64-bit ROM code
Deg CON 223 ' Data to display "Deg" symbol
DQ VAR PortB.5 ' One-wire data pin "DQ" on PortC.0
Busy VAR BIT ' Busy Status-Bit
Raw VAR WORD ' RAW Temperature readings
TempC VAR WORD ' Temp in deg C
TempF VAR WORD ' Temp in deg F
Float VAR WORD ' Holds remainder for + temp C display
Cold_Bit VAR Raw.Bit11 ' Sign-Bit for +/- Temp. 1 = Below 0 deg C
Dummy VAR BYTE ' Dummy for Div32
sensor var byte
hexbyte var byte
col var byte

'-------------------------------------------------------------------------------
'these constants are available to program the sensor for 9,10,11,12 bit resolution
'DS18B20_9bit CON 011111 ; 93.75ms, 0.5°C
DS18B20_10bit CON 111111 ; 187.5ms, 0.25°C <-- My favorite
'DS18B20_11bit CON 011111 ; 375ms, 0.125°C
'DS18B20_12bit CON 111111 ; 750ms, 0.0625°C (default)
' use the statement below in your program to set the resolution
OWOUT dq, 1, [$CC, $4E, 0, 0, DS18B20_10bit] 'set resolution of sensor
'================================================= ================
'============ Main Program loop ==================================
'================================================= ================
Main:

pause 500
toggle statled

for sensor=1 to 1 'change this to match how many sensors you are reading
for hexbyte=0 to 7 'each sensor address is 8 bytes
gosub getid 'go look up each sensors address
id[hexbyte]=col 'load the ID array with the retrieved address byte
next hexbyte 'go get the rest of the address bytes
gosub readsensor 'now go read the current sensor
gosub DisplayTemp 'now display the temp of the current sensor
next sensor 'now go read another sensor
goto main

end 'end here... use reset button to read them again.
'============= subroutines ========================
ReadSensor:
OWOUT DQ, 1, [$55,str id\8,$44] 'instructs sensors to match[$55] this[ID] rom code and
'initiates[$44] temperature conversion on matching sensor
CkAgn:
OWIN DQ, 4, [busy] ' Check for still busy converting
IF busy = 0 THEN ckagn ' Still busy?, then loop
owout dq,1,[$55,str id\8,$BE] 'instructs sensors to match[$55] this[ID] and start sending back scratchpad[$BE]
OWIN DQ, 2, [Raw.LOWBYTE,Raw.HIGHBYTE]' Read two temperature bytes, then end communications
return
'-------------------------------------------------------------
DisplayTemp: ' +32.0 to +257 F
IF Cold_Bit = 1 THEN Cold ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 625 * Raw ' Multiply to load internal registers with 32-bit value
TempC = DIV32 10 ' Use Div32 value to calculate precise deg C
TempC = (Raw & $0FF0) >> 4 ' Mask middle 8-bits, shift into lower byte
Float = ((Raw.Lowbyte & $0F) * 625) ' Lower 4-bits of result * 625
LCDOUT $FE,$C0, "T= ",Sign,DEC TempC,".",DEC Float,"C "
RETURN
''------------------------------------------------------------
Cold: ' arrive here if temp is below zero C
Sign = "-" ' Display - symbol for negative temp
Dummy = 625 * ~Raw+1' Multiply to load internal registers with 32-bit value
TempC = DIV32 10 ' Use Div32 value to calculate precise deg C
LCDOUT $FE,$C0, "T= ",Sign,DEC TempC DIG 4,DEC TempC DIG 3,".",DEC3 TempC," C "
' debug "Raw", IBIN16 Raw," Dec ",(Raw>>3),$0D,$0A
RETURN
'================================================= ============
GetID:
Select Case sensor
Case 1 :LOOKUP hexbyte,[$28,$05,$EF,$BC,$02,$00,$00,$8C], col

;add more sensors here
end select
return

Thanks for pointing me the right way,

Mike

Heckler
- 28th November 2011, 04:32
Are you using a Pull-Up resistor on the onewire data line??

Here is an example project I wrote that is now located in the WIKI section under projects... It is also based on Bruce's code examples over at Rentron.


http://www.picbasic.co.uk/forum/content.php?r=374-How-to-read-a-one-wire-DS18B20-temperature-sensor-or-nine-of-them

It was written for a 16F690, so you may need to modify the configuration to fit your PIC.

There are two parts to my example...
The first is to read the serial numbers of the sensors.
The second to read one or more of the sensors connected to the SAME pin on your PIC.
(pay attention to the comments in the example code and it will tell you how to change the code to fit your number of sensors)

lilimike
- 28th November 2011, 06:03
Hi,
Yes I am using a 4.7k pull-up and I had seen your code, I had actually used the top part (modified for 16F628A)to read my device's 64 bit serial code and I used the bottom part and double-checked with the code on Bruce's website.
Unless the AnyPin is conflicting, I have a feeling my sensor is burned or something, I'm not sure why I can read its code and I get a reading of 85 degrees C but I will order some more and compare with new ones.

Thanks for replying.

Mike

Darrel Taylor
- 28th November 2011, 20:24
85 deg. C is the default power-on state of the temperature reading.
If you get 85 deg. then you are successfully reading the device.
If it stays at 85, then a conversion is not being performed.

Your program works here in the simulator, so it probably comes down to this.

Check the part number on the DS18B20.
If it is followed by a "P" or "PAR", then it's a parasitic power ONLY device.

A parasitic power only device will not perform a conversion if powered like a normal DS18B20.
You must drive the DQ line high for the duration of the conversion for it to complete.

lilimike
- 29th November 2011, 00:17
Wow!
I do have a P (In the part number that is):surprise:
So that is a different datasheet, difference in the code and different connection.
Pin 3 of DS18B20 originally presumed to be VDD is now NC so disconnected.
I modified the code as follow:

ReadSensor:
OWOUT DQ, 1, [$55,str id\8,$44] 'instructs sensors to match[$55] this[ID] rom code and
'initiates[$44] temperature conversion on matching sensor
high DQ ; added for parasite device
pause 750 ; added for parasite device
low DQ ; added for parasite device
CkAgn:
OWIN DQ, 4, [busy] ' Check for still busy converting
IF busy = 0 THEN ckagn ' Still busy?, then loop
owout dq,1,[$55,str id\8,$BE] 'instructs sensors to match[$55] this[ID] and start sending back scratchpad[$BE]
OWIN DQ, 2, [Raw.LOWBYTE,Raw.HIGHBYTE]' Read two temperature bytes, then end communications
return

I should have used another port to drive an MOSFET but I don't have one right now and it still works by driving the DQ high.

So its all good now.

Thank you Darrel

Mike

Darrel Taylor
- 29th November 2011, 02:38
Great!

Since you are using 10-bit resolution, you only need to pause ~188mS.
Yes, it's still "<-- My favorite".

And it's probably best to release the pin instead of driving it low after the conversion.

high DQ
pause 188
input DQ

lilimike
- 29th November 2011, 05:07
I changed the wait to 188 - tested ok
I was not aware that INPUT pin# was a way to release the pin and I kind of felt unsure as to why I set it low, I guess it was a psychological way of undoing the high.
Anyways looking in the PBP bible 5.41 it says that using TRISB.5 = 1 is a more efficient way, not sure if it is just because it is faster to write when setting all pins to input at once.
I figured not using anything might be even more efficient so I just removed the last line altogether and the reading is still good.

So do you think leaving it out is ok or is there a chance it might create issues?

Mike

Darrel Taylor
- 29th November 2011, 17:30
Anyways looking in the PBP bible 5.41 it says that using TRISB.5 = 1 is a more efficient way ...
It does say that, doesn't it?
Well, it's not entirely correct.

It would be more efficient than the first example in the manual INPUT 0, because it has to figure out what pin 0 refers to.
But there is no difference at all between INPUT PORTB.5 and TRISB.5 = 1. They both generate the exact same code.


I figured not using anything might be even more efficient so I just removed the last line altogether and the reading is still good.
So do you think leaving it out is ok or is there a chance it might create issues?

That should be OK too.
The following OW commands will control the TRIS bit and leave it in INPUT mode when it's finished.

lilimike
- 29th November 2011, 23:18
Excellent!

Thank you Darrel.

Mike