Teensy 3 Temperature Calculation

Status
Not open for further replies.

adrianfreed

Well-known member
Has anyone already done the tricky temperature calculation from the result of an analogRead(38) to degrees C or F?
Thanks.
 
Just tried it today. I derived something that makes a bit of sense from Freescale's sign-inverted, reciprocal computation. They compute temperature as a delta of -1.715 mV/C where 25C measures 719 mV.

Converting from volts to C: slope is negative, and reciprocal of 1.715 mV/C, which gives

deltaC = - 583.0904 deltaV

I set the 1.2V reference in a hopeful attempt to get stability;
I used 12 bit conversions, with no averaging;

deltaV = deltaA2D * 1.2 / 4096

deltaC = deltaA2D * (1.2 / 4096) * -583.0904 = deltaA2d * -0.17083

25C is 719 mV which the A/D would read as 2454.19

The result, if one used floating-point arithmetic would be:

C = 25.0 + 0.17083 * (2454.19 - a2d)

It is possible to scale everything to stay in the world of integer arithmetic. Scaling everything by 16384 (2 ** 14) produces the following. I add 8191 to the multiplied result to round the result rather than truncating it.

= 25 + (2799 * (2454 - a2d)
= 25 + 419.25 - 0.17083 * a2d
= 444.25 - 0.17083 * a2d

To test...
2454 --> 25.033 C
2448 --> 26.06 C

I performed a further optimization in my code scaling by an additional factor of 100 to make reporting of 1/100 C easier:

100 * C = 44424.93 - 17.0827 * a2d

Scaling by 4096 (that's the max available to prevent integer overflow in 32 bits),

17.0827 * 4096 = 69970.845 rounded to 69971
44424.93 * 4096 = 181964504.1 rounded to 181964504

c * 100 = (181964504 - 69971 * a2d) >> 12

To print the value, I use "sniprintf" (integer only snprintf):

sniprintf(mybuf, sizeof(mybuf), "a2d: %04x %d temp: %d temp: %d.%02d\r\n", a2d, a2d, temp100c, temp100c/100, temp100c % 100);

And now some output from a teensy3 riding on top of my monitor:

Code:
a2d: 095a 2394 temp: 3528 temp: 35.28
a2d: 0958 2392 temp: 3562 temp: 35.62
a2d: 095a 2394 temp: 3528 temp: 35.28
a2d: 0956 2390 temp: 3597 temp: 35.97
a2d: 0958 2392 temp: 3562 temp: 35.62
a2d: 0957 2391 temp: 3580 temp: 35.80
a2d: 095a 2394 temp: 3528 temp: 35.28
a2d: 0959 2393 temp: 3545 temp: 35.45
a2d: 0958 2392 temp: 3562 temp: 35.62
 
This would make a very nice addition to the library: readTemperatureC(). Along with setTemperatureCalibration(offset, gain).

And someday, temperature compensation for the ADC and clocks.
 
Temperature compensation of clocks would be cool. I looked at that, and concluded that a little constant temperature oven (plus a separate, well regulated, constant drain power supply) was easier than compendating for voltage and temperature-related drifts. Mainly because I lacked data on the temperature dependency; and getting it would require making an accurate oven anyway.
 
Nantonos, agreed. It's quick and cheap to add components for a few things: accurate clocks, accurate ADC, accurate temperature, external flash, graphics driver without a big display buffer, probably zap resistant touch sensing, etc. But it's cool and a good learning exercise to do as much as possible as few additional components as possible.

Oops! I think I've wandered off topic. :eek:
 
Temperature compensation of clocks would be cool. I looked at that, and concluded that a little constant temperature oven (plus a separate, well regulated, constant drain power supply) was easier than compendating for voltage and temperature-related drifts. Mainly because I lacked data on the temperature dependency; and getting it would require making an accurate oven anyway.

Here is some fun inspired by you.
Screen Shot 2014-09-07 at 6.40.15 PM.png

No accurate oven used, just a hot water bottle, a GPS receiver, and a insulated box. What you see is the measured PPM error of the RTC vs. the reported mV reading produced by Channel 38 @ 12 bits of resolution, 32 samples per reading, and 1024 readings decimated / averaged (Channel 38 appears very noisy) over a small range of temperatures. This approach is unlikely to be ever as accurate as using a external DS18B20 thermally epoxied to the RTC crystal, but it saves a buck or two and it's pretty easy to implement. You may even be able to hold the RTC to within 2PPM without any external components.

But - you will likely have to calibrate every RTC compensation function individually, as the RTC PPM error and the MCU temperature response will vary. So not the easiest approach, but something fun to experiment with. Of course, there is no warranty re: accuracy, drift, etc. of the thermal sensor inside the chip so I'll likely continue to use DS18B20's for temperature readings of the RTC crystal, but it was fun to run this experiment to see if the MCU thermal sensor was a potential alternative to an active sensor.

Lastly, because the slope of the thermal function is negative re: the temperature, even though the temperature inside the box is going up, the indicated mV is going down to the left of the apex of the PPM error curve. The readings on the right side of the apex were made using a ice pack. Nothing terribly scientific, but amusing nonetheless.
 
Last edited:
Status
Not open for further replies.
Back
Top