1-wire-network DS18B20 negative degree missing

Haroen

Member
Hai all,
I've tested the code with Author Westaust55 who wrote "WA55 1-Wire Tutorial_RevE with TOC" from the thread...
http://www.picaxeforum.co.uk/showthread.php?15306-One-Wire-Devices-Networks/page2
(Chapter 14.2 DS18B20 Temperature Sensor)

When putting the sensor in the fridge the temperature dropped from +25.0°C to +0.0°C but then to +127.0°C instead of -1.00°C

In the PE manual BASIC commands there should be someting like...
Code:
if b1 > 127 then neg ; test for negative
let b1 = b1 - 128 ; adjust neg value
implemented in the start of procedure:
Code:
DisplayTheTemp:
	; this dislays the temperature in variable w0
	IF bit15 <> 0 THEN
		tempsign ="-"
		w0 = -w0 				; two's complement the value read in to get the absolute portion with no sign bit
	ELSE
		tempsign ="+"
	ENDIF
But how to implement in the above Multidrop sourcecode?
 
Last edited:

hippy

Technical Support
Staff member
It depends on how one is reading the temperature. READTEMP sets bit 7 for negative, READTEMP12 returns a two's complement value which will have bit 15 set when negative ...

Code:
[b]ReadTemp[/b] DS18B20_PIN, b3
If b3 >= $80 Then
  b3 = b3 & $7F           ; or b3 = b3 - 128, or a number of other options
  SerTxd( "-", #b3, "C )
Else
  SerTxd( "+", #b3, "C )
End If
Code:
[b]ReadTemp12[/b] DS18B20_PIN, w3
If w3 >= $8000 Then
  w3 = -w3 / 16
  SerTxd( "-", #w3, "C )
Else
  w3 = w3 / 16
  SerTxd( "+", #w3, "C )
End If
When using One-Wire commands to read the temperature, using OWIN and OWOUT, that's the equivalent of READTEMP12.
 

westaust55

Moderator
From the BASIC code listing at post 14 in the thread you linked to,



instead of the line (in 2 places):

w1 = w1 / 16 ; assumes positive range only and extracts only the integer portion



in each location replace with the following:


GOSUB DisplayTheTemp:
 

Haroen

Member
@Hippy
Your short ReadTemp12 code works just fine with reading down like +2, +1, +0, -0, -1, -2...
But implemented within the Multidrop code procedure "DisplayTheTemp:" it goes down like +2, +1, +0, +127, +128,...
Ignoring the - sign and w0=w0-127!?
Code:
DisplayTheTemp:
	; this dislays the temperature in variable w0
	IF w0>=$8000 THEN
		tempsign ="-"
		w0 = -w0 / 16
	ELSE
		w0 = w0 / 16
		tempsign ="+"
	ENDIF...
@westaust55
I've included the specific code where there is no "w1 = w1 / 16" to replace with "GOSUB DisplayTheTemp:".
Code:
14.2 DS18B20 Temperature Sensor
#PICAXE 40X1
#NO_DATA ; these commands prevent the Programming Editor over writing valid 1-Wire serial numbers
#NO_TABLE ; that have previously been saved to EEROM
#TERMINAL 4800
SETFREQ m4 ; this can be adjusted to m8 but then need to change the Terminal command above to 9600
;
;
; -----[ EEPROM Data ]-----------------------------------------------------
;
; -----[ Variables ]-------------------------------------------------------
;
SYMBOL device = b4
SYMBOL res_bits = b5
SYMBOL delay = b14
SYMBOL datasize = b15
SYMBOL tempsign = b16
SYMBOL loop_prt = b17
SYMBOL resolution = b18
SYMBOL OW_Net = b19 ; The permanent inbuilt DS18B20 temp sensor data input is pin 2, for one-wire network
use pin 7
SYMBOL EEmem_ptr = b20
;
; next variables used for binary/decimal for ASCII conversion
SYMBOL empty = b23
SYMBOL tenth = b24
SYMBOL hund = b25
SYMBOL thou = b26
SYMBOL tentho = b27
;
; -----[ Initialization ]--------------------------------------------------
;
Init:
PAUSE 1000 ; this delay is to give the Programming Editor terminal Window time to establish
;
WA55 1-Wire Tutorial_RevE with TOC.doc Page 29 of 75 15/06/2010
;
; -----[ Program Code ]----------------------------------------------------
;
Main:
FOR resolution = 9 to 12 ; try each of the resolutions the BS18B20 has available
datasize = resolution - 9 ; a value 0 to 3 which is used to part of setting up the DS18B20 config
register for resolution
SERTXD (CR, LF, CR, LF, "Resolution = ", #resolution, " bits", CR, LF)
FOR device = 1 to 6 ; First we set up the resolution configuration register for every device
we know about
OW_Net = 7
IF device = 1 THEN
OW_Net = 2 ; device 1 is a single device on pin 2. the other 5 are multidrop on pin
7
ENDIF
GOSUB Get_Dev_Sn_From_EE ; Places the device family type, serial number and CRC into variables
b6 to b13 with the family type in b6 and the CRC in b13
GOSUB Set_Res ; set the temp sensor config register for the desired resolution ( 9 to 12
bits)
NEXT device
; the following part addresses each temp sensor one at a time and sends the Convert T command, pauses then reads in
the temp data
FOR device = 1 to 6 ; for every available device on the system
OW_Net = 7
IF device = 1 THEN
OW_Net = 2 ; device 1 is a single device on pin 2. the other 5 are multidrop on pin
7
ENDIF
GOSUB Get_Dev_Sn_From_EE ; Places the device family type, serial number and CRC into variables
b6 to b13 with the family type in b6 and the CRC in b13
SERTXD(CR, LF, "Dev ", #device, " S/N = ", #b6, " ", #b7," ", #b8," ", #b9," ", #b10," ", #b11, " ",#b12," ",
#b13, " & Dev Temp is: ")
IF b6 = $28 THEN ; check that it is a DS18B20 Temp sensor $28 = 40 as family type
OWOUT OW_Net, %1001,($55, b6, b7, b8, b9, b10, b11, b12, b13, $44 ) ; send ‘reset before’ then
‘Match ROM’ and then S/N for device then ‘convert T’ then apply ‘pullup’
PAUSE delay ; wait the necessary period with extra/strong data line pull-up while
conversion takes place
OWOUT OW_Net, %1001,($55, b6, b7, b8, b9, b10, b11, b12, b13, $BE ) ; send ‘reset before’ then
‘Match ROM’ and then S/N for device then ‘Read Scratchpad’ then apply ‘pullup’
OWIN OW_Net, %1010,(b0,b1) ; read the temperature data into word variable w0 (w0 = b1:b0 -
NOTE 1-Wire systems do the lsb first)
GOSUB DisplayTheTemp
IF OW_Net = 2 THEN ; only for the a single DS18B20 then also do a comparative
READTEMP12 command
READTEMP12 OW_Net, w1
WA55 1-Wire Tutorial_RevE with TOC.doc Page 30 of 75 15/06/2010
w1 = w1 / 16 ; assumes positive range only and extracts only the integer portion
sertxd (" and = ", #w1 ) ; transmit the integer temperature value to the PC
ENDIF
ENDIF
NEXT device
SERTXD (CR,LF) ; skip a line for ease of viewing
; the following part broadcasts the converts T to all the devices, waits the delay period just once and them indivdually
reads each temp back
OW_Net = 2 ; set up to send COnvert T to the one device on pin 2
OWOUT OW_net,%1001,($CC,$44) ; send ‘reset’ then ‘skip ROM’ ‘ then ‘convert T’ then apply ‘pullup’
OW_Net = 7 ; set up to send Convert T to all the devices on pin 7
OWOUT OW_net,%1001,($CC,$44) ; send ‘reset’ then ‘skip ROM’ ‘ then ‘convert T’ then apply ‘pullup’
PAUSE delay ; wait the necessary period with extra/strong data line pull-up while
conversion takes place
FOR device = 1 to 6 ; now read the temp back individually from every available device on
the system
OW_Net = 7
IF device = 1 THEN
OW_Net = 2 ; device 1 is a single device on pin 2. the other 5 are multidrop on pin
7
ENDIF
GOSUB Get_Dev_Sn_From_EE ; Places the device family type, serial number and CRC into variables
b6 to b13 with the family type in b6 and the CRC in b13
SERTXD(CR, LF, "Dev ", #device, " S/N = ", #b6, " ", #b7," ", #b8," ", #b9," ", #b10," ", #b11, " ",#b12," ",
#b13, " & Dev Temp is: ")
IF b6 = $28 THEN ; check that it is a DS18B20 Temp sensor $28 = 40 as family type
OWOUT OW_Net, %1001,($55, b6, b7, b8, b9, b10, b11, b12, b13, $44 ) ; send ‘reset before’ then
‘Match ROM’ and then S/N for device then ‘convert T’ then apply ‘pullup’
PAUSE delay ; wait the necessary period with extra/strong data line pull-up while
conversion takes place
OWOUT OW_Net, %1001,($55, b6, b7, b8, b9, b10, b11, b12, b13, $BE ) ; send ‘reset before’ then
‘Match ROM’ and then S/N for device then ‘Read Scratchpad’ then apply ‘pullup’
OWIN OW_Net, %1010,(b0,b1) ; read the temperature data into word variable w0 (w0 = b1:b0 - NOTE 1-
Wire systems do the lsb first)
GOSUB DisplayTheTemp
IF OW_Net = 2 THEN ; only for the a single DS18B20 then also do a comparative
READTEMP12 command
READTEMP12 OW_Net, w1
w1 = w1 / 16 ; assumes positive range only and extracts only the integer portion
SERTXD (" and = ", #w1 ) ; transmit the integer temperature value to the PC
ENDIF
ENDIF
WA55 1-Wire Tutorial_RevE with TOC.doc Page 31 of 75 15/06/2010
NEXT device
SERTXD (CR,LF)
NEXT resolution
GOTO Main
;
; -----[ Subroutines ]-----------------------------------------------------
;
;
;
Get_Dev_Sn_From_EE:
EEmem_ptr = device - 1 * 8 + 1
READ EEmem_ptr, b6
INC EEmem_ptr
READ EEmem_ptr, b7
INC EEmem_ptr
READ EEmem_ptr, b8
INC EEmem_ptr
READ EEmem_ptr, b9
INC EEmem_ptr
READ EEmem_ptr, b10
INC EEmem_ptr
READ EEmem_ptr, b11
INC EEmem_ptr
READ EEmem_ptr, b12
INC EEmem_ptr
READ EEmem_ptr, b13
RETURN
;
; ---------------------------------------------------------------------------
;
Set_Res:
IF b6 = $28 THEN ; check that it is a DS18B20 Temp sensor $28 = 40
delay = 760 >> datasize ; 12 bit = 760ms, 11 bit = 380ms, 10 bit = 190ms and 9 bit =
95ms
res_bits = datasize * $20 OR $1F
OWOUT OW_Net, %1001,($55, b6, b7, b8, b9, b10, b11, b12, b13 ) ; send ‘reset before’ then ‘Match
ROM’ then SN for device then apply ‘pullup’
OWOUT OW_Net, %1010,($4E, 0,0, res_bits) ; send ‘Write to Scratchpad‘ to write to TH, TL and config
register. Set config to specified resolution
ENDIF
RETURN
;
; ---------------------------------------------------------------------------
;
DisplayTheTemp:
; this dislays the temperature in variable w0
IF bit15 <> 0 THEN
tempsign ="-"
w0 = -w0 ; two's complement the value read in to get the absolute
portion with no sign bit
ELSE
tempsign ="+"
ENDIF
WA55 1-Wire Tutorial_RevE with TOC.doc Page 32 of 75 15/06/2010
;
; now work out decimal fractional portion to suit the required resolution
w1 = 0
On datasize GOTO Bits09, Bits10, Bits11, Bits12 ; jump to appropriate point and exclude unneccesary bits
Bits12: IF bit0 = 1 THEN : w1 = w1 + 0625 : ENDIF
Bits11: IF bit1 = 1 THEN : w1 = w1 + 1250 : ENDIF
Bits10: IF bit2 = 1 THEN : w1 = w1 + 2500 : ENDIF
Bits09: IF bit3 = 1 THEN : w1 = w1 + 5000 : ENDIF
; now fractional pasrt doen we can alter w0 to work out the whole/Integer portion to suit the required resolution
w0 = w0 AND $07FF >> 4 ; mask off all the 5 sign bits and shift right 4 bits to leave only integer portion
; break out the digits into ASCII codes and diplay the relevant digits corresponding to accuracy
BINTOASCII w1 , empty, tenth, hund, thou, tentho
; now display the temperature as reported by the current sensor
SERTXD( tempsign, #w0, ".") ; display the sign and integer/whole part
SERTXD (tenth)
IF datasize > 0 THEN : SERTXD (hund) : ENDIF
IF datasize > 1 THEN : SERTXD (thou) : ENDIF
IF datasize > 2 THEN : SERTXD (tentho) : ENDIF
RETURN
;
;
; -----[ Interrupt Routine (if used) ]-------------------------------------
;
;Interrupt:
; RETURN
; =================================================
; THE END
; =================================================
@Marks
I've read the thread and will study and try the codes, thanks.

I'm starting to think that the problem lay's somewhere else like further in the procedure DisplayTheTemp code where w0 is altered just once somehow...
Code:
; now fractional pasrt doen we can alter w0 to work out the whole/Integer portion to suit the required resolution
	w0 = w0 AND $07FF >> 4 																; mask off all the 5 sign bits and shift right 4 bits to leave only integer portion
 
Last edited:

Haroen

Member
I've tried the BASIC commands example code for OWIN and OWOUT with a 40X2 vB.3 firmware and get strange temperature readings 400 to 444 for 25°C to 28°C!?
Code:
#PICAXE 40X2
#NO_DATA
#NO_TABLE
#TERMINAL 4800
SETFREQ m4

MAIN:
	; Read raw temperature value from DS18B20
	; (this achieves a similar function to the readtemp12 command)
	owout D.7,%1001,($CC,$44)
	; send ‘reset’ then ‘skip ROM’
	; then ‘convert’ then apply ‘pullup’
	pause 750 ; wait 750ms with strong pullup
	owout D.7,%0001,($CC,$BE)
	; send ‘reset’ then ‘skip ROM’
	; then ‘read temp’ command
	owin D.7,%0000,(b0,b1) ; read in result
	sertxd (#w0,CR,LF) ; transmit value
Goto MAIN
Could this problem of my multidrop code be the firmware?
 

lbenson

Senior Member
Note that the OWIN/OWOUT commands return the equivalent of READTEMP12, so you have to divide your values by 16 to get whole degrees: 400/16=25 and 444/16=27.75.
 

Haroen

Member
...so you have to divide your values by 16 to get whole degrees: 400/16=25 and 444/16=27.75.
You're right and it works great in the short BASIC command code but not in the DS18B20 Multidrop code.
I even stripped the procedure "DisplayTheTemp" compleetly and replaced it with the short BASIC command code as result the -1C becomes +2047C instead and -2C becomes +2046C!?
 

hippy

Technical Support
Staff member
Perhaps post your stripped-down code then people can take a look at it to see if there is something wrong.

Westaust55's code looks right to me so perhaps there is something wrong elsewhere. That would also explain why you are not getting the results expected with my code either. Perhaps print out the raw value of w0 on entry to the DisplayTemp routine.

"W0 = w0 AND $07FF >> 4" should only ever give a value in w0 between $00 and $7F, 0 and 127, so it's not clear why 2047 or anything greater than 127 is being shown.
 

Haroen

Member
I've got it running now and the issue was not in the procedure DisplayTheTemp but in the main loop for reading the temperaturen data.:

westaust55 has code like
Owin ow_net, %1010, (b0, b1)

Hippy has code like
Owin ow_net, %0000, (b0, b1)

Difference is only in the owin MODE with %0000 working great, but why?
 
Last edited:

hippy

Technical Support
Staff member
Difference is only in the owin MODE with %0000 working great, but why?
Not sure. Westaust55's code sets 'apply strong pullup after data' and 'reset pulse sent after data', mine doesn't.

It may come down to how the DS18B20 is wired, whether just one or multiple devices expected to be connected, what the full sequence of OWOUT and OWIN commands are.
 

Haroen

Member
@Hippy
Thanks, I Will keep that in mind When changing the network.

In Westaust55 his code "14.2 DS18B20 Temperature Sensor" he presets a device count and some device serial numbers in ROM.
Code:
EEPROM 0, (6) ; count of devices 
EEPROM 1, (40, 217, 147, 226, 0, 0, 0, 251) ; serial number for device 1 - this is on pin 2 
EEPROM 9, (40, 16, 123, 94, 1, 0, 0, 62) ; serial number for device 2 - this is on pin 7 
EEPROM 17, (40, 218, 158, 94, 1, 0, 0, 102) ; serial number for device 3 - this is on pin 7 
EEPROM 25, (40, 97, 114, 94, 1, 0, 0, 98) ; serial number for device 4 - this is on pin 7 
EEPROM 33, (40, 35, 147, 94, 1, 0, 0, 110) ; serial number for device 5 - this is on pin 7 
EEPROM 41, (40, 55, 135, 94, 1, 0, 0, 138) ; serial number for device 6 - this is on pin 7
How to best clear the ROM from a previous search with a start position to an end position everytime a button is pressed to search for devices again?

Should I use EEPROM like Westaust55 did or should I use the WRITE command for every location?
And with what (character like "0" of "space") should I clear a location?
 
Last edited:

westaust55

Moderator
The EEPROM statement is more a compiler directive and loads the data into EEPROM at the time the program is loaded.

WRITE stores the data into EEPROM at the time of execution while the program is running.

Hence to change the information while running the program you need to use the WRITE command.
 

Haroen

Member
Then I Will have to clear every address 0 tot (31x8)+8 with a loop.
What character will be recognised as a cleared address?
 

westaust55

Moderator
As a suggestion, consider to clear just EEPROM location 0 to a value of 0.

instead of:
EEPROM 0, (6) ; count of devices


Use:
EEPROM 0, (0) ; count of devices
or
WRITE 0,0

Then when you do a search you can save each found device address in EEPROM and increment the counter in location 0.
 

Haroen

Member
@westaust55
Resetting and Incrementing just the counter in location 0 address in EEPROM is genius!

This saves WRITE-loop time, programming time and program space for clearing every ROM address,
 
Top