Help with temperature sensor math
AGCB
Posts: 327
in Propeller 1
I have a temperature program working which displays readings from DS18B20 sensors on a TV.
What I need help with is calculating by hand how the output from the sensor gets displayed in degrees F on the TV. I've tried to follow the math in the methods but do not come out with anything close. I've included the pertinent parts of the code which does work. I'd like to be able to create a conditional statement, but using the actual displayed value does not work, hence the desire to use the actual readout of the sensor. Thanks, Aaron
A few observations of data are
when output
= 65260 display says 0F 'output is loaded is 3rd to last line of ReadTemperature method
=65397 display says 16F
= 298 display says 65F
What I need help with is calculating by hand how the output from the sensor gets displayed in degrees F on the TV. I've tried to follow the math in the methods but do not come out with anything close. I've included the pertinent parts of the code which does work. I'd like to be able to create a conditional statement, but using the actual displayed value does not work, hence the desire to use the actual readout of the sensor. Thanks, Aaron
A few observations of data are
when output
= 65260 display says 0F 'output is loaded is 3rd to last line of ReadTemperature method
=65397 display says 16F
= 298 display says 65F
OSsensor :=readTemperature(D_temp) 'from main method PUB readTemperature(addr) | temp,dsOut '' Read the temperature from a DSxxxxx sensor, and return it. ' Blocks while the conversion is taking place. ow.reset ow.writeByte(ow#MATCH_ROM) ow.writeAddress(addr) '64 bit address of device being addressed ow.writeByte(ow#CONVERT_T) ' Wait for the conversion repeat waitcnt(clkfreq/100 + cnt) if ow.readBits(1) 'we Have a reading! Read it from the scratchpad. ow.reset ow.writeByte(ow#MATCH_ROM) ow.writeAddress(addr) '64 bit address of device being addressed ow.writeByte(ow#READ_SCRATCHPAD) dsOut := ow.readBits(16) 'degF := (temp << 4)*9/5+32 output := dsOut temp := ~~dsOut * 625 ' extend sign, 0.0001° units return temp pub showf(temp,places) | tp,Modulus 'places = number of decimal places to show '' Print temperature in degrees Fahrenheight w/(places) number of decimals ' -- temp is passed in C case places 'this added by AG 0 : Modulus:=0 'integer only 1 : Modulus:=10 '1 decimal 2 : Modulus:=100 '2 3 : Modulus:=1000 '3 4 : Modulus:=10_000 '4 if (temp > 0) temp := temp * 9 / 5 + 32_0000 else temp := 32_0000 - (||temp * 9 / 5) if (temp < 0) 'if negative tv.out("-") ||temp 'print degrees w/ selectable number of decimal places if Modulus==0 tv.dec(temp / 10_000) ' print whole portion truncated else tv.dec(temp / 10_000) ' print whole portion tv.out(".") tv.dec(temp // Modulus) ' print fractional portion tv.out(176) tv.str(string("F "))
Comments
The sensor value is in 1/16ths of a degree C, so temp gets set to the value in 0.0001 deg C units. sets temp to 0.0001 deg F units.
The fiddling around with signs is probably due to integer rounding issues differing from +ve to -ve values
I just figured it out! The dsOUT value needs to be sign extended. output := ~~dsOut Then it works
T = ~~dsOut*625*9 /5 +320,000 all over 10,000