はっくはっくキッチン
Hack Hack Kitchen

Correcting Temperature Data of MAX31855

 2022/02/06

Introduction

According to the MAX31855 datasheet, this chip calculates the temperature from the thermoelectromotive force $E$ assuming the following relationship: $$\begin{align} E = C (t_\mathrm{R} - t_\mathrm{AMB}) \; , \end{align}$$ where $C$ is a constant (sensitivity) dependent on the type of thermocouple, $t_\mathrm{R}$ is the temperature of the measuring point (remote) and $t_\mathrm{AMB}$ is the temperature of the chip (ambient). In reality, however, there is no such linear relationship between thermoelectromotive force and temperature difference, and large discrepancies can occur, especially at temperatures below $0\,\degree\mathrm{C}$.

This has been discussed on the Adafruit forum for quite some time, and Pete (heypete) has described it in detail there and on his blog. The correction procedure is described in the MAX31855 Linearized Thermocouple Temperature (PNG file) posted on the forum. The codes can be found in an article Maxim 31855 Thermocouple Linearization by Adafruit, which is a summary of implementations posted by Jeff (jh421797) and Pete (heypete) in the forum above (both are essentially the same). However, these have the following disadvantages:

  • The clarity is not optimal, so it is difficult to see what you are doing.

  • Using the pow() function makes it slow, and the size of the binaries is a bit large.

  • Not generic because it is written as an .ino file (file for Arduino).

Therefore, I reimplemented the functions for the conversions between the thermocouple electromotive force and temperature as the Library for Thermocouple based on NIST ITS-90 Database. The library does not contain any MAX31855-specific code, but it can be very easily applied to the MAX31855 as explained below. Furthermore, all types of thermocouples in the NIST ITS-90 database are supported, as the functions are generated by a script from the NIST database. The polynomials are calculated according to the Horner's method. These have made the code much cleaner to write, slightly reduced the binary size and significantly reduced the execution time.

Correction of the temperature obtained from MAX31855

See the Library for Thermocouple based on NIST ITS-90 Database for more information about the library itself.

In the following, the unit for temperature is $\degree\mathrm{C}$ and the unit for electromotive force (emf) is mV.

For type K thermocouples, the corrected (more accurate) temperature can be calculated from the thermocouple temperature (rawTemp) and the internal cold-junction temperature (internalTemp) which are obtained from MAX31855 by writing

correctedTemp = emf2temp_K((rawTemp - internalTemp) * 0.041276 + temp2emf_K(internalTemp));

where emf2temp_K() and temp2emf_K() are the functions provided by the Library for Thermocouple based on NIST ITS-90 Database.

For thermocouples that are not of type K, replace the function names with the corresponding thermocouple (e.g. emf2temp_B) and the constant (0.041276 in the example above) with the value in the MAX31855 data sheet.

The relation between this formula and the method given above (MAX31855 Linearized Thermocouple Temperature) is as follows: $$\begin{align} t_\mathrm{corr} = \underbrace{ \mathrm{emf2temp}( \underbrace{ \underbrace{ \underbrace{(t'_\mathrm{R} - t_\mathrm{AMB})}_\text{step 1} \cdot C}_\text{step 2} + \underbrace{\mathrm{temp2emf}(t_\mathrm{AMB})}_\text{step 3} }_\text{step 4} )}_\text{step 5} \; , \end{align}$$ where

$t_\mathrm{corr}$

the corrected temperature

$t'_\mathrm{R}$

the thermocouple temperature (rawTemp) obtained from MAX31855. A prime $'$ has been added to $t_\mathrm{R}$ to imply that it is not very accurate (and should be corrected).

$t_\mathrm{AMB}$

the cold-junction temperature (internalTemp) obtained from MAX31855.

$C$

the sensitivity used by MAX31855 (see equation (1))

If you want to use a linear expression to convert $t_\mathrm{AMB}$ (internalTemp) to electromotive force (see Mike's (zike) post), you can write:

correctedTemp = emf2temp_K((rawTemp - internalTemp) * 0.041276 + internalTemp * 0.04073);

(See the MAX31855 data sheet for the constants used in this equation).

Comparison

For reference, I compared the binary size and execution time of the Arduino implementations using my Library for Thermocouple based on NIST ITS-90 Database and HeyPete's MAX31855-Linearization. (In the following tables, these are referred to as TPKato and heypete , respectively.)

The used code for the comparison can be found at https://github.com/TPKato/arduino-max31855-nist.

Environment

  • gcc version 11.2.0 (+ Arduino IDE 1.8.19)

  • Arduino libraries

    • SPI at version 1.0

    • Wire at version 1.0

    • Adafruit_MAX31855_library at version 1.3.0

    • Adafruit_BusIO at version 1.10.3

  • Arduino Nano

Results

Binary size (Type K thermocouple, code for execution time measurement is not included)

TPKato 8490 bytes
heypete 9386 bytes

Execution time $\tau_\mathrm{exec}$

Mean value of 10 measurements, approximately every 1 second.

$\overline{\tau_\mathrm{exec}} / \mathrm{\mu{}s}$ $\overline{t_\mathrm{raw}}/\degree\mathrm{C}$ $\overline{t_\mathrm{int}}/\degree\mathrm{C}$ $\overline{t_\mathrm{corr}}/\degree\mathrm{C}$
TPKato $\phantom{0}619.6$ $25.75$ $26.19$ $25.73$
heypete $6654.2$ $25.75$ $26.14$ $25.74$

The only major difference is that the Horner's method is used instead of pow(), but the results show that the performance is much better. Furthermore, the main code is much cleaner and easier to understand by rewriting the conversions between electromotive force and temperature into functions.

Appendix: Derivation of the equations above

General discussion

In general, when determining the temperature with thermocouples, the voltage $E$ caused by the Seebeck effect and the temperature at the cold-junction $t_\mathrm{AMB}$ are measured. If the voltage $E$ is a function of the temperatures $T_1$ and $T_2$ of the two junctions $E(T_1, T_2)$, holds: $$\begin{align} E(T_1, T_2) = \int_{T_1}^{T_2} \left( S_\mathrm{B}(T) - S_\mathrm{A}(T) \right) \mathrm{d} T \; , \end{align}$$ where $S_\mathrm{A}(T)$ and $S_\mathrm{B}(T)$ are respectively the Seebeck coefficients of the metals A and B of which the thermocouple consists. Therefore: $$\begin{align} E(T_1, T_2) &= E(T_1, T_3) + E(T_3, T_2) \\ E(T_1, T_2) &= -E(T_2, T_1) \end{align}$$ (breaking-up and swapping the interval of integration). Substituting the temperatures of the measuring point $t_\mathrm{R}$, the temperature of the reference junction $t_\mathrm{AMB}$ and $0\,\mathrm{\degree{}C}$ for $T_1$, $T_2$ und $T_3$, then $$\begin{align} E(t_\mathrm{R}, t_\mathrm{AMB}) &= E(t_\mathrm{R}, 0\,\mathrm{\degree{}C}) - E(t_\mathrm{AMB}, 0\,\mathrm{\degree{}C}) \; . \end{align}$$ Thus: $$\begin{align} E(t_\mathrm{R}, 0\,\mathrm{\degree{}C}) &= E(t_\mathrm{R}, t_\mathrm{AMB}) + E(t_\mathrm{AMB}, 0\,\mathrm{\degree{}C}) \; . \end{align}$$ (Alternatively, equation (4) can be applied with $T_1 = t_\mathrm{R}$, $T_2 = 0\,\mathrm{\degree{}C}$ and $T_3 = t_\mathrm{AMB}$.)

If $t^0_\mathrm{TC}(E)$ is a function to determine the temperature from the electromotive force with respect to $0\,\mathrm{\degree{}C}$ $E(t, 0\,\mathrm{\degree{}C})$, the following equation gives the temperature $t_\mathrm{R}$ to be determined: $$\begin{align} t_\mathrm{R} & = t^0_\mathrm{TC}(E(t_\mathrm{R}, 0\,\mathrm{\degree{}C})) \\ &= t^0_\mathrm{TC}( \underbrace{E(t_\mathrm{R}, t_\mathrm{AMB})}_\text{measured} + E( \underbrace{t_\mathrm{AMB}}_\text{measured}, 0\,\mathrm{\degree{}C}) ) \end{align}$$

In practice, $E(t, 0\,\mathrm{\degree{}C})$ and $t^0_\mathrm{TC}(E)$ are unknown and should be calculated using the appropriate tables or approximations.

Example

As an example, below is an excerpt from the table of electromotive forces for type K thermocouples (based on all.tab from NIST, unit of electromotive force: mV).

$t/ \mathrm{\degree{}C}$ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9
0 0.000 0.039 0.079 0.119 0.158 0.198 0.238 0.277 0.317 0.357
10 0.397 0.437 0.477 0.517 0.557 0.597 0.637 0.677 0.718 0.758
20 0.798 0.838 0.879 0.919 0.960 1.000 1.041 1.081 1.122 1.163
30 1.203 1.244 1.285 1.326 1.366 1.407 1.448 1.489 1.530 1.571
40 1.612 1.653 1.694 1.735 1.776 1.817 1.858 1.899 1.941 1.982

If, for example,

  • $t_\mathrm{AMB} = 24\,\mathrm{\degree{}C}$ and

  • the measured electromotive force is $0.529\,\mathrm{mV}$

then the temperature $t_\mathrm{R}$ can be determined from equation (9) and this table as follows. $$\begin{align*} t_\mathrm{R} &= t^0_\mathrm{TC}( \underbrace{0.529\,\mathrm{mV}}_{E(t_\mathrm{R}, t_\mathrm{AMB})} + \underbrace{0.960\,\mathrm{mV}}_{E(t_\mathrm{AMB}, 0\,\mathrm{\degree{}C})} ) \\ &= t^0_\mathrm{TC}(1.489\,\mathrm{mV}) \\ &= 37\,\mathrm{\degree{}C} \end{align*}$$

In other words, $E(t, 0\,\mathrm{\degree{}C})$ corresponds to finding the electromotive force from the corresponding temperature in the table, and $t^0_\mathrm{TC}(E)$ corresponds to finding the corresponding temperature by searching a value of the electromotive force in the table.

However, such a table is not suitable for computer processing, so approximated functions are used.

Linear assumption

Assuming that the Seebeck coefficients are independent of temperature, equation (3) can be expressed as follows: $$\begin{align} E(T_1, T_2) = C (T_1 - T_2) \end{align}$$ ($C = - S_\mathrm{B} + S_\mathrm{A}$). If we again substitute $t_\mathrm{R}$ and $t_\mathrm{AMB}$ into $T_1$ and $T_2$, we obtain $$\begin{align} E(t_\mathrm{R}, t_\mathrm{AMB}) &= C (t_\mathrm{R} - t_\mathrm{AMB}) \; . \end{align}$$ This gives $$\begin{align} t'_\mathrm{R} &= \frac{1}{C}E(t_\mathrm{R}, t_\mathrm{AMB}) + t_\mathrm{AMB} \; . \end{align}$$ Here in equation (12), $'$ has been added to $t_\mathrm{R}$ to imply a linear assumption (i. e. not very accurate).

Equation (11) is exactly what is in the MAX31855 data sheet, and it outputs the $t'_\mathrm{R}$ calculated in this way. However, this assumption can only be made as a very rough approximation (within a limited temperature range).

Correction

The more accurate measuring point temperature can be obtained by

  1. calculating back the electromotive force $E(t_\mathrm{R}, t_\mathrm{AMB})$ from $t'_\mathrm{R}$ und $t_\mathrm{AMB}$ which are obtained from MAX31855 and

  2. equation (9) is applied again with this value (and $t_\mathrm{AMB}$).

For this purpose, substituting equation (11) into equation (9) yields $$\begin{align} t_\mathrm{R} & = t^0_\mathrm{TC}(C (t_\mathrm{R} - t_\mathrm{AMB}) + E(t_\mathrm{AMB}, 0\,\mathrm{\degree{}C})) \end{align}$$ (See equation (2)). $t^0_\mathrm{TC}(E)$ corresponds to the function emf2temp() and $E(t, 0\,\mathrm{\degree{}C})$ to the function temp2emf().