DS18B20 Questions

AlbertZ

Senior Member
This forum has been a great help to me on a previous project
http://www.picaxeforum.co.uk/showthread.php?24819-Pinewood-Derby-Stopwatch-Timer&highlight=pinewood+derby
and hopefully you guys can help me sort this one out.

My Grandson has an idea for a science fair project (heat of fusion of water) and he will need a precision thermometer that reads in degrees Celsius. I have built a few PICAXE projects before and thought that this would be an interesting project to tackle. After researching the web I decided on an HD44780 display driven by an AXE132 serial interface. The temperature sensor I chose was the DS18B20 because there seemed to be a lot of information available and the degree of precision achievable. I decided to use an 18M2 controller because that is what I had on hand.

After more scrounging around the internet, I hacked together the attached code. Now we get to my problem – it doesn’t work. When I run it through the simulator it returns the following result:

Input(Word) Output
0 0.00oC
16000 -24.00oC
32000 -48.00oC
48000 -72.00oC
64000 -96.00oC
65536 -0.06oC

It should be returning an output of -55oC to 125oC.

Aside from the fact that this code doesn’t work, I want to be able to understand it rather than blindly copy someone else’s work. So here is the first question:
On Line 45 there is a test for positive or negative . If I read the code correctly this should return a number between 0.00 and 1.99. Somehow it is supposed to interpret the integer as a zero or one and make a determination if the number is negative. It seems to me that there is a line of code missing. Am I interpreting this correctly? Is there a better way to isolate the sign bit?

Going to Line 47 generates another question. What is the purpose of generating a two’s complement? At first I was puzzled how the code generated a two’s complement until I realized that the symbol was for a bitwise XOR function. The binary value of $FFFF is all ones. By XORing the Temperature12 value with $FFFF and adding 1 we get the two’s complement. But why go through all that?

I would appreciate any help in understanding this code and getting it to do what it is supposed to do.


Code:
' ************** TemperatureSensorSerial.bas **************
'This program runs on a PICAXE 18-M2 at 4MHz which reads the temperature from a
' DS18B20 temperature sensor & sends it to an HD44780 compatible 16x2 serial LCD display.
' 
' Developed by Albert Zalner February 6, 2015.

' *** Constants ***
 symbol LCD = C.6     ' Assign LCD to port C.6

 ' *** Variables ***
 symbol  Temp =  b20     	' calculation variable
 symbol  Temperature12 = w11  ' Temperature word using b22 & b23
 symbol  TempC_100 = w12      ' Temperature value in C * 100 (uses b24 & b25)
 symbol  Tempsign = bit0      ' The sign of the temperature reading
 symbol  Whole = b2		'The whole temperature reading
 symbol  Fract = b3		'The fraction temperature reading


' *** Directives ***
 #com 3       	' specify download port
 #picaxe 18M2      ' specify processor
 #no_data       ' save time downloading
 #terminal off      ' disable terminal window
  
' *** Initialize the LCD *** 
' *** Control commands are all prefixed by the number 254 *** 
iniLCD:
serout LCD,N2400, (254,1)		'Clear Display
pause 800					' pause 800 mS for LCD initialization
serout LCD,N2400, (254,128)		'Move to Line 1, Position 1
serout LCD,N2400, ("The Temperature")		'Output Text

main:
	serout LCD,N2400, (254,196)		'Move to line 2, position 4
	call ReadTemp12Sensor			'Read the temperature
	goto main					'loop to beginning
	
ReadTemp12Sensor:
	'**************************************************************
	'** Read DS18B20 & display temperature in 12 bit resolution  **
	'**************************************************************
ReadTemp12 B.3, Temperature12		'Read the DS18B20 temp sensor
Pause 800					'pause 800 ms per DS18B20 spec
TempSign = Temperature12 / 256 /128	'Isolate the MSB bit
If TempSign  = 0 then Positive 	'Test for negative
Temperature12 = Temperature12 ^ $ffff + 1		'Take 2's complement

Positive:
TempC_100 = Temperature12 * 6			'TC = value = 0.0625, TC*100 = 6.25
Temperature12 = Temperature12 * 25 / 100	'the rest of the value
TempC_100 = TempC_100 + Temperature12	'the temperature value * 100 in C
Whole = TempC_100 / 100				'separate the whole degrees
Fract = TempC_100 % 100				'separate the fractional degrees
If TempSign  > 0 then				'temp is negative
	Serout LCD,N2400,("-")			'send negative symbol
end if
Serout LCD,N2400,(#Whole)		'Send temp to LCD as a whole number
Serout LCD,N2400,(".")			'send decimal point
'*** To ensure the fraction is double digits ***
Temp = Fract / 10				'Calc the first digit of fract
Serout LCD,N2400,(#Temp)		'send first decimal digit to LCD
Temp = Fract % 10				'Calc the second digit of fract
Serout LCD,N2400,(#Temp)		'send second decimal digit to LCD
Serout LCD,N2400,(%11010010)		'send degree character
Serout LCD,N2400,("C")			'send letter “C”
Return
 

eggdweather

Senior Member
The code:
~~~
If TempSign = 0 then Positive 'Test for negative
Temperature12 = Temperature12 ^ $ffff + 1 'Take 2's complement

Positive:
~~~
Reads If the temperature sign is 0 then GOTO positive, the goto is optional. The result of the test will be either 0 or 1 or FALSE or TRUE, so if 1 or TRUE it goes to 'positive'
otherwise, if negative (previous result was 0), XOR the Temperature12 reading with 0xFFFF inverting all the bits, then add 1 to create a 2's complement number because negative numbers are held in 2's complement form.
In two's-complement representation, positive numbers are represented as themselves with negative numbers represented by the two's complement. Perhaps a way of looking at the problem is that computers can't subtract, well that was the original reason for using a complement scheme. For example, take the 10's complement and say you can only add:
10-9 is the same as 10+1=11, forget the carry (the 10 overflow) and the result =1 (correct) The 10's complement of 9 is 1
10-8 is the same as 10+2=12, forget the carry (the 10 overflow) and the result =2 (correct) The 10's complement of 8 is 2
10-2 is the same as 10+8=18, forget the carry (the 10 overflow) and the result =8 (correct) The 10's complement of 2 is 8, always add up to 10

So that's why they use 2-complement, you can do the same maths in any number base by complementing the negative numbers and then adding.
 

eclectic

Moderator
@AlbertZ
Just out of interest, I copied your code, then modified it to use
Sertxd

Code:
' ************** TemperatureSensorSerial.bas **************
'This program runs on a PICAXE 18-M2 at 4MHz which reads the temperature from a
' DS18B20 temperature sensor & sends it to an HD44780 compatible 16x2 serial LCD display.
' 
' Developed by Albert Zalner February 6, 2015.
' *** Constants ***
 symbol LCD = C.6     ' Assign LCD to port C.6
 ' *** Variables ***
 symbol  Temp =  b20      ' calculation variable
 symbol  Temperature12 = w11  ' Temperature word using b22 & b23
 symbol  TempC_100 = w12      ' Temperature value in C * 100 (uses b24 & b25)
 symbol  Tempsign = bit0      ' The sign of the temperature reading
 symbol  Whole = b2  'The whole temperature reading
 symbol  Fract = b3  'The fraction temperature reading

' *** Directives ***
 #com 3        ' specify download port
 #picaxe 18M2      ' specify processor
 #no_data       ' save time downloading
  #terminal 4800
    
' *** Initialize the LCD *** 
' *** Control commands are all prefixed by the number 254 *** 
iniLCD:
pause 2000     ' pause 800 mS for LCD initialization
sertxd  ("The Temperature")  'Output Text
main:
 
 call ReadTemp12Sensor   'Read the temperature
 goto main     'loop to beginning
 
ReadTemp12Sensor:
 '**************************************************************
 '** Read DS18B20 & display temperature in 12 bit resolution  **
 '**************************************************************
ReadTemp12 B.3, Temperature12  'Read the DS18B20 temp sensor
Pause 800     'pause 800 ms per DS18B20 spec
TempSign = Temperature12 / 256 /128 'Isolate the MSB bit
If TempSign  = 0 then Positive  'Test for negative
Temperature12 = Temperature12 ^ $ffff + 1  'Take 2's complement
Positive:
TempC_100 = Temperature12 * 6   'TC = value = 0.0625, TC*100 = 6.25
Temperature12 = Temperature12 * 25 / 100 'the rest of the value
TempC_100 = TempC_100 + Temperature12 'the temperature value * 100 in C
Whole = TempC_100 / 100    'separate the whole degrees
Fract = TempC_100 % 100    'separate the fractional degrees
If TempSign  > 0 then    'temp is negative
 sertxd ("-")   'send negative symbol
end if
sertxd (#Whole)  'Send temp to LCD as a whole number
sertxd (".")   'send decimal point
'*** To ensure the fraction is double digits ***
Temp = Fract / 10    'Calc the first digit of fract
sertxd (#Temp)  'send first decimal digit to LCD
Temp = Fract % 10    'Calc the second digit of fract
sertxd (#Temp)  'send second decimal digit to LCD
;sertxd (%11010010)  'send degree character
sertxd ("C", cr,lf      )   'send letter “C”
Return
18M2, on an AXE091 board, in a cold workroom.
Nearby thermometer shows ~15.5 'C

I blew on the DS18B20 for a few seconds.
However, I am NOT going outside to do further tests. :- )

e
 

Attachments

marks

Senior Member
Hi Albertz,
i think your code is working correctly you just need to use the correct input values
thats keen eclectric nice weather 26'c here as cool as it going to get tho

for 125'c / .0625 = 2000
s0 -55'c / .0625 = -880

using eggdweather theorem

65535 -880 +1 = 64656 ie (-55'c)

so the ds18b120 return the values between 64656 to 2000

so our negative numbers are above 64655
our test value could be anything really above 2000

if we look at there test value ie 1 *256*128 = 32768
so anything above that is negative

http://www.picaxeforum.co.uk/showthread.php?15464-DS18B20-Code-Examples
 

AlbertZ

Senior Member
The code:
~~~
If TempSign = 0 then Positive 'Test for negative
Temperature12 = Temperature12 ^ $ffff + 1 'Take 2's complement

Positive:
~~~
Reads If the temperature sign is 0 then GOTO positive, the goto is optional. The result of the test will be either 0 or 1 or FALSE or TRUE, so if 1 or TRUE it goes to 'positive'
otherwise, if negative (previous result was 0), XOR the Temperature12 reading with 0xFFFF inverting all the bits, then add 1 to create a 2's complement number because negative numbers are held in 2's complement form.
In two's-complement representation, positive numbers are represented as themselves with negative numbers represented by the two's complement. Perhaps a way of looking at the problem is that computers can't subtract, well that was the original reason for using a complement scheme. For example, take the 10's complement and say you can only add:
10-9 is the same as 10+1=11, forget the carry (the 10 overflow) and the result =1 (correct) The 10's complement of 9 is 1
10-8 is the same as 10+2=12, forget the carry (the 10 overflow) and the result =2 (correct) The 10's complement of 8 is 2
10-2 is the same as 10+8=18, forget the carry (the 10 overflow) and the result =8 (correct) The 10's complement of 2 is 8, always add up to 10

So that's why they use 2-complement, you can do the same maths in any number base by complementing the negative numbers and then adding.
Thanks! That clearly explains the requirement for the two's complement. I thought that was a clever way the original code author implemented this on an 18M2. It took me a while to figure this out until I realized that the binary of $FFFF is all ones.
 

geoff07

Senior Member
Serout writes to your display. Sertxd writes to the terminal so can be used during debugging without affecting the program function.

You might be able to simplify your code a little: to convert raw positive temp readings from readtemp12 into a word variable in tenths of a degree: W_temp_deg = W_temp_deg * 25/40
I didn't need negative temps but detection and conversion has been explained, the method depends on your chip (easiest on an X1/2 where IF bit SET is available).

To extract the digits into individual bytes:
Code:
extract_digits:  
   B_tenths    = W_temp // 10 
   B_units     = W_temp /  10  // 10 
   B_tens      = W_temp /  100 // 10 
   return
 

AlbertZ

Senior Member
Hi Albertz,
i think your code is working correctly you just need to use the correct input values
thats keen eclectric nice weather 26'c here as cool as it going to get tho

for 125'c / .0625 = 2000
s0 -55'c / .0625 = -880

using eggdweather theorem

65535 -880 +1 = 64656 ie (-55'c)

so the ds18b120 return the values between 64656 to 2000

so our negative numbers are above 64655
our test value could be anything really above 2000

if we look at there test value ie 1 *256*128 = 32768
so anything above that is negative

http://www.picaxeforum.co.uk/showthread.php?15464-DS18B20-Code-Examples
Hello marks,
OK, I understand why and how we use the two’s complement to work with negative numbers.
But I’m still left with a code that doesn’t work (I think) and I still don’t understand the test for positive or negative. Here are the results of my simulation:
WORD INPUT DISPLAY
65535 -0.06
64656 -55.00
54000 -81.00
44000 -66.00
32000 -48.00
22000 -33.00
12000 -18.00
6000 -9.00
4000 -6.00
3000 -68.50
2000 125.00
1500 93.75
1000 62.50

Now when I look at the DS18B20 data sheet I see that it returns a 16 bit word (or two 8 bit words). However, in the simulation I am only inputing a single 8-bit word. Am I somehow losing the sign bit in the process? If so, why am I hitting the nail on the head for 125.00 and -55.00?
This has me wondering because the word variable [Temperature12] is only 8 bits (b22 & b23).
What am I missing here?
 

premelec

Senior Member
YES! read into a WORD variable which is 16 bits - not a byte variable... :) [I only took fast look at earlier code...]
 

AlbertZ

Senior Member
YES! read into a WORD variable which is 16 bits - not a byte variable... :) [I only took fast look at earlier code...]
YES! I sometimes get my words and bytes confused. Therefore we should be able to read integer numbers up to 65535.

From this I can only conclude that something is haywire with the code for it to return these crazy values.
 

AlbertZ

Senior Member
i think your code is working correctly you just need to use the correct input values
I finally figured it out! I assumed that the integer values were linear. WRONG!

I went back to the DS18B20 datasheet and converted the hex values to decimal, then inserted these into the simulation. Low and behold, the output was spot on.

Best part is now I not only have a working set of instructions, but I understand what is going on.

Thanks to all for your patience.

Al
Temp_Data_Relationship.png
 

hippy

Ex-Staff (retired)
The READTEMP12 values returned are definitely linear, represented as 16-bit two's complement values, but having understood it in terms of how you need to in order to use it is what counts most.
 

hippy

Ex-Staff (retired)
In most cases unused pins can be left unconnected.

It is not recommended to tie unused pins directly to ground in case those pins are inadvertently made output high; that would create a hard short to 0V which can damage the PICAXE chip.
 

AlbertZ

Senior Member
In most cases unused pins can be left unconnected.

It is not recommended to tie unused pins directly to ground in case those pins are inadvertently made output high; that would create a hard short to 0V which can damage the PICAXE chip.
Thank You!
 
Top