PaxInstruments / t400-firmware

Firmware for the Pax Instruments T400 temperature datalogger
22 stars 5 forks source link

Junction temperature errors #192

Closed charlespax closed 8 years ago

charlespax commented 8 years ago

I dipped two k-type thermocouples into liquid nitrogen (−195.79 °C 77 K; −320 °F) today. I recorded to the MicroSD card in K and again in °C. The thermocouples registered as disconnected at low temperatures. The ADC and lookup table should be able to measure down at that voltage (-6458 uV at -270 °C).

The defined temperature range is defined well enough:

#define TEMP_TYPE_K_MIN_CONVERSION -6458
#define TEMP_TYPE_K_MAX_CONVERSION 54819

Here are the plots: ln2c ln2k

There must be something else happening here. The lowest measured temperature is -235.30 °C, but liquid nitrogen should be around −195.79 °C. Maybe it was actually liquid H2 (about −269 °C 4 K or −452.2 °F), but that's doubtful. I'll have to confirm. Even if it were H2, we should still be able to measure the corresponding thermocouple voltage. Probably a firmware issue.

Here's the data:

time (s), temp_0 (C), temp_1 (C), temp_2 (C), temp_3 (C)
       1, 36.65, -, -, -
       2, 36.59, -, -, -
       3, 36.24, -, -, -
       4, 35.09, -, -, -
       5, 34.61, -, -, -
       6, 35.32, -, -, -
       7, 36.19, -, -, -
       8, 32.78, -, -, -
       9, 30.56, -, -, -
      10, 29.63, -, -, -
      11, 29.08, 1172.52, -, -
      12, 28.95, 27.75, -, -
      13, 28.81, 27.82, -, -
      14, 28.75, 27.75, -, -
      15, 28.43, 27.64, -, -
      16, 28.63, 28.02, -, -
      17, 28.16, 27.96, -, -
      18, 24.89, 1.66, -, -
      19, -31.77, -63.44, -, -
      20, -100.77, -122.06, -, -
      21, -144.98, -161.11, -, -
      22, -169.53, -177.10, -, -
      23, -180.85, -186.54, -, -
      24, -187.84, -194.54, -, -
      25, -193.00, -199.34, -, -
      26, -197.52, -205.07, -, -
      27, -203.06, -206.84, -, -
      28, -206.90, -211.83, -, -
      29, -211.83, -215.67, -, -
      30, -228.58, -230.07, -, -
      31, -235.30, -237.00, -, -
      32, -, -, -, -
      33, -, -, -, -
      34, -, -, -, -
      35, -, -, -, -
      36, -, -, -, -
      37, -, -, -, -
      38, -, -, -, -
      39, -185.32, -178.33, -, -
      40, -79.27, -63.18, -, -
      41, -30.84, -16.03, -, -
      42, 0.39, 3.94, -, -
      43, 13.76, 15.78, -, -
      44, 20.03, 20.24, -, -
      45, 26.56, 24.37, -, -
      46, 30.07, 21.91, -, -
      47, 28.22, 21.04, -, -
      48, 31.35, 20.77, -, -
      49, 34.81, 20.69, -, -
      50, 35.85, 20.75, -, -
      51, 36.32, 21.23, -, -
      52, 36.31, 29.83, -, -
      53, 36.51, 31.01, -, -
      54, 36.77, 33.62, -, -
      55, 36.13, 34.34, -, -
      56, 35.79, 34.41, -, -
      57, 35.99, 35.99, -, -
      58, 36.63, 36.05, -, -
      59, 35.45, 33.11, -, -
      60, 35.46, 32.72, -, -
      61, 35.99, 32.44, -, -
time (s), temp_0 (K), temp_1 (K), temp_2 (K), temp_3 (K)
       1, 310.12, 308.74, -, -
       2, 307.29, 307.90, -, -
       3, 304.77, 304.77, -, -
       4, 302.57, 302.78, -, -
       5, 301.78, 300.79, -, -
       6, 297.13, 276.12, -, -
       7, 252.24, 216.64, -, -
       8, 224.56, 167.41, -, -
       9, 218.65, 112.54, -, -
      10, 148.26, 82.36, -, -
      11, 112.04, 68.14, -, -
      12, 93.61, 61.32, -, -
      13, 79.38, 44.51, -, -
      14, 66.31, -, -, -
      15, 58.88, -, -, -
      16, 43.02, -, -, -
      17, 36.28, -, -, -
      18, -, -, -, -
      19, -, -, -, -
      20, -, -, -, -
      21, -, -, -, -
      22, -, -, -, -
      23, -, -, -, -
      24, 181.40, 183.42, -, -
      25, 228.94, 247.25, -, -
      26, 253.21, 274.16, -, -
      27, 271.84, 285.76, -, -
      28, 279.70, 289.94, -, -
      29, 284.46, 291.34, -, -
      30, 288.79, 292.41, -, -
      31, 291.22, 292.41, -, -
      32, 292.41, 292.62, -, -
      33, 292.70, 292.70, -, -
      34, 293.39, 292.17, -, -
      35, 294.05, 293.04, -, -
      36, 294.05, 293.63, -, -
      37, 294.19, 293.78, -, -
      38, 294.40, 297.78, -, -
      39, 294.40, 303.98, -, -
      40, 294.40, 308.10, -, -
      41, 294.64, 306.98, -, -
      42, 294.58, 306.71, -, -
      43, 294.58, 306.91, -, -
      44, 294.71, 307.24, -, -
      45, 294.72, 307.63, -, -
      46, 294.79, 308.30, -, -
      47, 294.99, 304.97, -, -
      48, 295.33, 302.90, -, -
charlespax commented 8 years ago

I'm not doing the junction temperature offset correctly. I need to back-calculate the respective thermocouple voltage for the junction temperature and subtract it from the measured voltage. That then gives the correct thermocouple voltage.

I changed the firmware to display the measured voltage rather than calculated temperature. Then I connected a small voltage source made from a battery and voltage divider to simulate a low temperature reading. The voltage displayed on the T400 was consistent with the voltage measured using a Fluke 89.

charlespax commented 8 years ago

The thermocouple temperature equation we've implemented works as follows:

  1. Measure thermocouple voltage V_t
  2. Find temperature T_T corresponding to the measured voltage V_t
  3. Measure MCP9800 junction temperature T_j
  4. Get thermocouple temperature by adding T_t + T_j

This is how we should implement it:

  1. Measure MCP9800 junction temperature T_j
  2. Use the lookup table to find the voltage V_j corresponding to temperature T_j
  3. Measure thermocouple voltage V_t
  4. Calculate the compensated voltage V = V_t - V_j
  5. Use the lookup table to find the thermocouple temperature T_t corresponding to the compensated voltage V

If we do things the wrong way, the difference between the calculated temperature and the actual temperature increase as the thermocouple temperature increases.

charlespax commented 8 years ago

But is this consistent with observations? From my testing I know the ADC can measure down to the voltages we expect to see when measuring liquid nitrogen. However, this does not explain whey the numbers disappear from the screen and data stream.

charlespax commented 8 years ago

Commit 5b3b10739bb8ab2055c9f76df15511b241b9b570 builds in Arduino hourly 2015/12/14 11:26, using 28,648 bytes of the total 28,672 bytes leaving 24 bytes available.

We can grab some extra bytes by truncating the temperature lookup table, with each entry giving us an additional four bytes. Liquid nitrogen boils at −195.79 °C, so we really don't need to measure anything below -200 °C. That frees up seven table entries, leaving us with 52 bytes. A propane torch will get to around 1200 °C. Truncating the high end to 1210 °C frees up sixteen entries, leaving us with a total with a total 116 bytes.

We can go further in grabbing bytes. probably better to take from the low end. I would rather release a firmware update later that increases the measurement range than ship a device that gives nonsense numbers and release a bug fix later. I think a reasonable approach is to truncate the table to free up bytes, implement the bug fix, then re-add lookup entries to use any remaining bytes.

We could move some things to the SPI flash (chip #191) to free up space. The lookup table, font, and strings are good candidates. I think this would require a fair amount of work, so we should only do it if necessary. Let's see what kind of temperature range we get with the table truncation method first.

The lookup table uses the int32_t (4 bytes) variable type. The measured thermocouple voltage ranges from -6458 to +54819. We can switch to uin16_t (2 bytes) if we add 6458 uV to the measured thermocouple voltage and shift all the lookup table numbers accordingly. Everything would functionally remain the same. Voltage range in the lookup table would range from 0 to 62,277, which is with in 0 to 65,535 range of uint16_t. This would give us an extra 328 bytes for a total of 352 bytes if this is the only change we make.

charlespax commented 8 years ago

Okay, in commit 313d4b2d641e504ef4f863ffe3c48ed252f30c33 I converted the lookup table from int32_t to uint16_t and made the necessary adjustments to the lookup function. Flashed to a T400. Appears to function as it has been. The code compiles to 28,364 bytes. we have 284 bytes available.

charlespax commented 8 years ago

In commit 1a8832b82f8d0e1dbd3e11c0adddededb3185c5b I added an empty function GetJunctionVoltage(double jTemp) to functions.cpp. This is where we would implement code that takes the junction temperature and determines the corresponding thermocouple voltage from the lookup table. We still have 266 bytes available.

charlespax commented 8 years ago

In commit f6c471ed8490dbf3c6a0f03e4b396030b9c85777 I think I've actually implemented the junction temperature compensation properly. I have to do more testing, but initial casual tests don't reveal any problems.

There are now 166 bytes available.

charlespax commented 8 years ago

It looks like there's more to this. The T400 I'm using is measuring voltages too high. This is a v12 modified to be v13, so there may be something else going on here. I'm making another v14 board to test again.

charlespax commented 8 years ago

The messed up measurements I was getting were form a crappy device I made to output voltage. I thought it was the filtration circuit causing problems, so I tried several hardware configurations, measuring the output voltage on a Fluke 89 and on a T400 and calculating the offset (fluke - t400).

Here is a plot of the the offset vs voltage. offets

Here is the offset as a percentage of the Fluke 89 measured value. errors

After realizing the problem was coming from my measurement setup I configured the board with the original filtration configuration and performed the measurements again. In this graph the purple line shows the offset voltage vs. measured voltage. Since it's nice and linear we can apply a calibration factor. The red line is approximately what we would expect from a calibrated measurement. values

Taking new measurements with calibrated firmware gives wonderful results. Here you can see we're pretty tight in on the Fluke 89 temperatures. t400-offsets

There's still some work to do on this. In the above measurements, the junction voltage was calculated manually and programmed into the firmware. The cold junction voltage function needs to be implemented properly. See https://github.com/PaxInstruments/t400-firmware/issues/196

zigastegu commented 6 years ago

Fluke reference: http://assets.fluke.com/manuals/87_89iv_umeng0300.pdf image