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
.inofile (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
-
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
-
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
-
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().