PDA

View Full Version : Why? Temp conversion C to F code from Rentron (Bruce)



Heckler
- 17th May 2011, 14:52
Hey Group, and Bruce

Below are two snippets of code from Bruce's website Rentron http://www.rentron.com/PicBasic/one-wire3.htm

Thank you Bruce for the code... It works great by the way.

However I can not figure out a portion of it...
I have eliminated the parts that send Debug Data and the parts that do deg C conversion. I just need a routine that returns deg F.

Here is a section of the code as Bruce posted it...


Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 625 * R_Temp ' Multiply to load internal registers with 32-bit value
TempC = DIV32 10 ' Use Div32 value to calculate precise deg C
Dummy = 1125 * R_Temp
TempF = DIV32 100
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 4,_
DEC TempF DIG 3,DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ELSE
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 3,_
DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ENDIF
TempC = (R_Temp & $0FF0) >> 4 ' Mask middle 8-bits, shift into lower byte
Float = ((R_Temp.Lowbyte & $0F) * 625) ' Lower 4-bits of result * 625
SEROUT2 DISP,BAUD, [INS,LINE2, " TempC = ",Sign,DEC TempC,".",DEC Float,Deg,"C "]
SEROUT2 DISP,BAUD, [INS,LINE4, "Raw", IBIN16 R_Temp]
RETURN




Here is that same portion of code cleaned up for my needs...


Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 1125 * R_Temp
TempF = DIV32 100
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
ELSE
TempF = TempF + 3200
ENDIF
RETURN ' with TempF loaded with current temp in deg F



My question surrounds this section of the code... This If/Then/Else looks redundant. But If I remove one of them then the code does not work. Why??

Works:

IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
ELSE
TempF = TempF + 3200
ENDIF
RETURN ' with TempF loaded with current temp in deg F

Does not Work(returns too low of a value):

IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
RETURN ' with TempF loaded with current temp in deg F

Thanks

Bruce
- 17th May 2011, 15:38
The first IF condition in the original displays 1 more digit prior to the decimal point.

Jerson
- 17th May 2011, 15:49
Hi Dwight

I hope you don't mind me taking this for you.

We start here with an assumption of temperature higher than 0deg
You may skip this if you put it inside the IF/ELSE as I showed
Sign = "+"



' This one does temperature * 11.25
Dummy = 1125 * R_Temp
TempF = DIV32 100

' yes, this checks for 67.95+32.00
' if the reading goes above this value,
' it must be a negative value(offset binary values), so, the else comes into play
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
Sign = "+"
ELSE
TempF = TempF + 3200
Sign = "-"
ENDIF
RETURN ' with TempF loaded with current temp in deg F
' and Sign having the sign of the temperature

PS: I noticed Bruce already answered your query before I posted.

Heckler
- 17th May 2011, 17:02
The first IF condition in the original displays 1 more digit prior to the decimal point.

Yes, I could see that in the original code, the first debug was there to display one more digit for temp>99.

That is why I thought that I could remove the second "TempF = TempF + 3200".

But it appears that I need to keep both of them in the code to get the correct temperature conversion??

Or am I missing something?

My goal is to have a section of code that will return degrees F for at least a range of say -20 F to +120 F (-30 to +50 C) I dont care about fractional digits. I am also trying to keep it small, as I am running out of room in my PIC. I don't need extreme accuracy +- 1 deg or so is ok.

Here is my(Bruce's) complete subroutine which seems to work correctly:


'===========subroutine==========================
GetTemp:
OWOUT comm_pin, 1, [$CC, $4E, 0, 0, DS18B20_9bit] 'set resolution 9 bit Start_Convert:
OWOUT Comm_Pin, 1, [$CC, $44] 'Skip ROM search & do temp conversion

Wait_Up:
OWIN Comm_Pin, 4, [Busy] ' Read busy-bit
IF Busy = 0 THEN Wait_Up ' Still busy..?, Wait_Up..!
OWOUT Comm_Pin, 1, [$CC, $BE]
OWIN Comm_Pin, 2, [R_Temp.Lowbyte, R_Temp.Highbyte] ' Read two bytes
GOSUB Convert_Temp
RETURN
'================================================= ===============================
Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 1125 * R_Temp
TempF = DIV32 100
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
ELSE
TempF = TempF + 3200
ENDIF
tempf=tempf/100 'keep only whole digits
RETURN
'-----------------------------------------------------------------------------
Yikes: ' Display full range -C to -F conversion
Sign = "-" ' Display - symbol for negative temp
TempF = ~R_Temp / 16 ' Begin conversion from -C to deg +/-F
IF TempF >=18 THEN ' Check for -degrees F "-18 C = -0.4 F"
TempF = ((((TempF + 50) * 9) /5) -122) ' -C to -F below -17 deg C
ELSE ' Else result = +deg F
TempF = ((((-TempF + 50) * 9) /5) -58)
ENDIF
RETURN
'================================================= =


But It seems that I still need both instances of... TempF = TempF + 3200
and that is what is puzzling me.

Isn't it the case that only one or the other will be executed? Yet if I remove one of them then I get the wrong temperature??

Possibly(likely) I need to go back and do some more testing.


Thanks

Demon
- 17th May 2011, 17:11
...

Bruce first compares TempF to 6795, then he adds 3200 to complete the calculation.

That's why it's in both sides of the IF.

Heckler
- 17th May 2011, 17:26
Robert,

your version makes sense to me... and that is what I was trying to accomplish. Yet when I removed one (or took it outside of the IF/Then) it did'nt seem to work right.

I will have to do some more testing tonight.
(dang work is getting in the way right now:mad:)

thanks


PS. as I listed in an earlier post I am trying to tighten up my code. I know Bruces code is optimized to give accurate fractional degrees, which I don't need.

If anybody has more compact code that only gives whole numbers I would be grateful. If anywhere I am weak in PIC Basic programming, it is in the Math area.

Thanks

Demon
- 17th May 2011, 17:42
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 4,_
DEC TempF DIG 3,DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ELSE
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 3,_
DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ENDIF


I don't follow Bruce's math (big surprise).
6795 + 3200 = 9995
But the If comment compares TempF with 99.5?

Why not add 3200 before and compare with 9950:



TempF = TempF + 3200
If TempF > 9950 THEN ' over 99.5, requires hundreds digit
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 4,_
DEC TempF DIG 3,DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ELSE
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 3,_
DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
Endif

Demon
- 17th May 2011, 17:48
...If anybody has more compact code that only gives whole numbers I would be grateful....

Again, assuming I am not as confused as you are.

The 1st part of the If adds a hundreds digit, the 2nd part removes a leading 0. If you don't care for a leading 0, these are the elements that you are interested in:



TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 4,_
DEC TempF DIG 3,DEC TempF DIG 2,Deg,"F "]


- Add that 3200.
- Use Digits 4, 3 and 2 of TempF.

Heckler
- 17th May 2011, 18:11
Actually, as my subroutine shows, I am just interested in a routine that returns the temperature in deg F, in a variable (TempF).

That is why in my example, I have allready removed all the SEROUT statements. And that is where my confusion comes in... after removing all the SEROUT statements I could see the (I believe) redundancy in the code portion we are discussing. BUT after removing the redundancy... I was not getting a correct reading of temperature.

More testing is needed, it may have been the wee hours that I was doing the testing:o.

Thanks

Demon
- 17th May 2011, 18:25
If anybody has more compact code that only gives whole numbers I would be grateful. If anywhere I am weak in PIC Basic programming, it is in the Math area.

Then just Return after adding 3200 and let the calling routine use digits 4, 3 and 2 of TempF.

Demon
- 17th May 2011, 18:34
Bruce version:



Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 625 * R_Temp ' Multiply to load internal registers with 32-bit value
TempC = DIV32 10 ' Use Div32 value to calculate precise deg C
Dummy = 1125 * R_Temp
TempF = DIV32 100
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 4,_
DEC TempF DIG 3,DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ELSE
TempF = TempF + 3200
SEROUT2 DISP,BAUD, [INS,LINE1, " TempF = ",Sign,DEC TempF DIG 3,_
DEC TempF DIG 2,".",DEC2 TempF,Deg,"F "]
ENDIF
TempC = (R_Temp & $0FF0) >> 4 ' Mask middle 8-bits, shift into lower byte
Float = ((R_Temp.Lowbyte & $0F) * 625) ' Lower 4-bits of result * 625
SEROUT2 DISP,BAUD, [INS,LINE2, " TempC = ",Sign,DEC TempC,".",DEC Float,Deg,"C "]
SEROUT2 DISP,BAUD, [INS,LINE4, "Raw", IBIN16 R_Temp]
RETURN




Here is that same portion of code cleaned up for my needs...



Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 1125 * R_Temp
TempF = DIV32 100
IF TempF >6795 THEN ' Over 99.5 deg F..?
TempF = TempF + 3200
ELSE
TempF = TempF + 3200
ENDIF
RETURN ' with TempF loaded with current temp in deg F




My untested version:



Convert_Temp: ' +32.0 to +257 F
IF Cold_Bit = Real_Cold THEN Yikes ' If Cold_Bit = 1, it's below "0" deg C
Sign = "+"
Dummy = 1125 * R_Temp
TempF = DIV32 100
TempF = TempF + 3200 ' Digits 4, 3 and 2
RETURN
Yikes:
...
RETURN


Don't forget you also have to clean up the Yikes subroutine for temps below +32F.