I hooked up the cheap thermocouple:
Fluke 51 II : -78.0 degC
MAX31855 Std: -66.00 degC
MAX31855 Corr: -75.05 degC
That is interesting: ~3.0 degC difference btw Fluke & 31855 here and a ~0.5 degC difference with the better thermocouple above.
Is that about the difference you were getting with your cheapy?
- Jeff
Max 31855 Reading High Temperatures
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
Interesting. Thanks for checking.
According to my wife my brain does garbage collection every few hours, so I have no detailed recollection of the values I measured last year when I compared the Fluke 51 II we had in the lab to the MAX31855. Your numbers sound reasonable.
According to my wife my brain does garbage collection every few hours, so I have no detailed recollection of the values I measured last year when I compared the Fluke 51 II we had in the lab to the MAX31855. Your numbers sound reasonable.
- adafruit_support_bill
- Posts: 88153
- Joined: Sat Feb 07, 2009 10:11 am
Re: Max 31855 Reading High Temperatures
You folks are famous now :)
https://learn.adafruit.com/calibrating- ... earization
https://learn.adafruit.com/calibrating- ... earization
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
Woot!adafruit_support_bill wrote:You folks are famous now :)
https://learn.adafruit.com/calibrating- ... earization
Would it be possible to link to the calibration guide above from the MAX31855 tutorial page?
In regards to a previous message, I dug up my code where I originally implemented the corrections. It's a bit hackish, but overall very similar to Jeff's except for the following differences:
1. I take into account the possibility that the cold-junction temperature may be negative, as the chip may be located in a cold environment.
2. I store the NIST coefficients in arrays and iterate through them with loops.
3. It uses more flash and RAM. It's not remotely optimized and could be made more efficient.
Here's my code, sans the debug output from my earlier tests and with extra comments. My error handling is really bad, but the code works and produces the proper corrected output. It uses the BSD-licensed Adafruit library for the MAX31855. The code written by me is public domain.
Code: Select all
#include <SPI.h>
#include "Adafruit_MAX31855.h"
#define DO 12
#define CS 11
#define CLK 10
Adafruit_MAX31855 thermocouple(CLK, CS, DO);
void setup() {
Serial.begin(9600);
Serial.println("MAX31855 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// Initialize variables.
int i = 0; // Counter for arrays
double internalTemp = thermocouple.readInternal(); // Read the internal temperature of the MAX31855.
double rawTemp = thermocouple.readCelsius(); // Read the temperature of the thermocouple. This temp is compensated for cold junction temperature.
double thermocoupleVoltage= 0;
double internalVoltage = 0;
double correctedTemp = 0;
// Check to make sure thermocouple is working correctly.
if (isnan(rawTemp)) {
Serial.println("Something wrong with thermocouple!");
}
else {
// Steps 1 & 2. Subtract cold junction temperature from the raw thermocouple temperature.
thermocoupleVoltage = (rawTemp - internalTemp)*0.041276; // C * mv/C = mV
// Step 3. Calculate the cold junction equivalent thermocouple voltage.
if (internalTemp >= 0) { // For positive temperatures use appropriate NIST coefficients
// Coefficients and equations available from http://srdata.nist.gov/its90/download/type_k.tab
double c[] = {-0.176004136860E-01, 0.389212049750E-01, 0.185587700320E-04, -0.994575928740E-07, 0.318409457190E-09, -0.560728448890E-12, 0.560750590590E-15, -0.320207200030E-18, 0.971511471520E-22, -0.121047212750E-25};
// Count the the number of coefficients. There are 10 coefficients for positive temperatures (plus three exponential coefficients),
// but there are 11 coefficients for negative temperatures.
int cLength = sizeof(c) / sizeof(c[0]);
// Exponential coefficients. Only used for positive temperatures.
double a0 = 0.118597600000E+00;
double a1 = -0.118343200000E-03;
double a2 = 0.126968600000E+03;
// From NIST: E = sum(i=0 to n) c_i t^i + a0 exp(a1 (t - a2)^2), where E is the thermocouple voltage in mV and t is the temperature in degrees C.
// In this case, E is the cold junction equivalent thermocouple voltage.
// Alternative form: C0 + C1*internalTemp + C2*internalTemp^2 + C3*internalTemp^3 + ... + C10*internaltemp^10 + A0*e^(A1*(internalTemp - A2)^2)
// This loop sums up the c_i t^i components.
for (i = 0; i < cLength; i++) {
internalVoltage += c[i] * pow(internalTemp, i);
}
// This section adds the a0 exp(a1 (t - a2)^2) components.
internalVoltage += a0 * exp(a1 * pow((internalTemp - a2), 2));
}
else if (internalTemp < 0) { // for negative temperatures
double c[] = {0.000000000000E+00, 0.394501280250E-01, 0.236223735980E-04 - 0.328589067840E-06, -0.499048287770E-08, -0.675090591730E-10, -0.574103274280E-12, -0.310888728940E-14, -0.104516093650E-16, -0.198892668780E-19, -0.163226974860E-22};
// Count the number of coefficients.
int cLength = sizeof(c) / sizeof(c[0]);
// Below 0 degrees Celsius, the NIST formula is simpler and has no exponential components: E = sum(i=0 to n) c_i t^i
for (i = 0; i < cLength; i++) {
internalVoltage += c[i] * pow(internalTemp, i) ;
}
}
// Step 4. Add the cold junction equivalent thermocouple voltage calculated in step 3 to the thermocouple voltage calculated in step 2.
double totalVoltage = thermocoupleVoltage + internalVoltage;
// Step 5. Use the result of step 4 and the NIST voltage-to-temperature (inverse) coefficients to calculate the cold junction compensated, linearized temperature value.
// The equation is in the form correctedTemp = d_0 + d_1*E + d_2*E^2 + ... + d_n*E^n, where E is the totalVoltage in mV and correctedTemp is in degrees C.
// NIST uses different coefficients for different temperature subranges: (-200 to 0C), (0 to 500C) and (500 to 1372C).
if (totalVoltage < 0) { // Temperature is between -200 and 0C.
double d[] = {0.0000000E+00, 2.5173462E+01, -1.1662878E+00, -1.0833638E+00, -8.9773540E-01, -3.7342377E-01, -8.6632643E-02, -1.0450598E-02, -5.1920577E-04, 0.0000000E+00};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
}
else if (totalVoltage > 0 && totalVoltage < 20.644 ) { // Temperature is between 0C and 500C.
double d[] = {0.000000E+00, 2.508355E+01, 7.860106E-02, -2.503131E-01, 8.315270E-02, -1.228034E-02, 9.804036E-04, -4.413030E-05, 1.057734E-06, -1.052755E-08};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
}
else if (totalVoltage > 20.644 && totalVoltage < 54.886) { // Temperature is between 500C and 1372C.
double d[] = {-1.318058E+02, 4.830222E+01, -1.646031E+00, 5.464731E-02, -9.650715E-04, 8.802193E-06, -3.110810E-08, 0.000000E+00, 0.000000E+00, 0.000000E+00};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
} else { // NIST only has data for K-type thermocouples from -200C to +1372C. If the temperature is not in that range, set temp to impossible value.
// Error handling should be improved.
Serial.print("Temperature is out of range. This should never happen.");
correctedTemp = NAN;
}
Serial.print("Corrected Temp = ");
Serial.println(correctedTemp, 5);
Serial.println("");
}
delay(1000);
}
- adafruit_support_bill
- Posts: 88153
- Joined: Sat Feb 07, 2009 10:11 am
Re: Max 31855 Reading High Temperatures
Sure, no problem. I had to wait for the tutorial to go live to post links to it. I added the links to the FAQ. I added your code to the last page of the calibration tutorial.
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
Fantastic, thanks!adafruit_support_bill wrote:Sure, no problem. I had to wait for the tutorial to go live to post links to it. I added the links to the FAQ. I added your code to the last page of the calibration tutorial.
- tonyhansen
- Posts: 31
- Joined: Fri Nov 29, 2013 12:37 am
Re: Max 31855 Reading High Temperatures
The code on above by @heypete has a couple minor bugs in it. Specifically, what happens if the calculated value of totalVoltage came out as 0? Then each of the if/else-if statements would be ignored and the default at the end (with the print statement "This should never happen.") will be executed. (The same is true for the value 20.644, but that is less likely to occur because of floating point representations.) The fix is to change the >s to >=, or to remove the redundant tests entirely. That is, change the if/else-if tests to
if (totalVoltage < 0) {
} else if (totalVoltage < 20.644) {
} else if (totalVoltage < 54.886) {
} else {
}
if (totalVoltage < 0) {
} else if (totalVoltage < 20.644) {
} else if (totalVoltage < 54.886) {
} else {
}
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
D'oh. You're right. I use >=s in the section for the internal temperature but erroneously use plain <s in the section for calculating the corrected temperature.tonyhansen wrote:The code on above by @heypete has a couple minor bugs in it. Specifically, what happens if the calculated value of totalVoltage came out as 0? Then each of the if/else-if statements would be ignored and the default at the end (with the print statement "This should never happen.") will be executed. (The same is true for the value 20.644, but that is less likely to occur because of floating point representations.) The fix is to change the >s to >=, or to remove the redundant tests entirely. That is, change the if/else-if tests to
if (totalVoltage < 0) {
} else if (totalVoltage < 20.644) {
} else if (totalVoltage < 54.886) {
} else {
}
Removing the redundant checks also makes the code a teensy bit more efficient and saves a cycle or two on comparisons.
Good catch, and thank you.
- adafruit_support_bill
- Posts: 88153
- Joined: Sat Feb 07, 2009 10:11 am
Re: Max 31855 Reading High Temperatures
Hey heypete! If you post an update w/ the corrections, I'll see that it gets into the tutorial.
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
Here you go. I used tonyhansen's suggestion to remove the redundant comparisons.adafruit_support_bill wrote:Hey heypete! If you post an update w/ the corrections, I'll see that it gets into the tutorial.
Code: Select all
#include <SPI.h>
#include "Adafruit_MAX31855.h"
#define DO 12
#define CS 11
#define CLK 10
Adafruit_MAX31855 thermocouple(CLK, CS, DO);
void setup() {
Serial.begin(9600);
Serial.println("MAX31855 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// Initialize variables.
int i = 0; // Counter for arrays
double internalTemp = thermocouple.readInternal(); // Read the internal temperature of the MAX31855.
double rawTemp = thermocouple.readCelsius(); // Read the temperature of the thermocouple. This temp is compensated for cold junction temperature.
double thermocoupleVoltage= 0;
double internalVoltage = 0;
double correctedTemp = 0;
// Check to make sure thermocouple is working correctly.
if (isnan(rawTemp)) {
Serial.println("Something wrong with thermocouple!");
}
else {
// Steps 1 & 2. Subtract cold junction temperature from the raw thermocouple temperature.
thermocoupleVoltage = (rawTemp - internalTemp)*0.041276; // C * mv/C = mV
// Step 3. Calculate the cold junction equivalent thermocouple voltage.
if (internalTemp >= 0) { // For positive temperatures use appropriate NIST coefficients
// Coefficients and equations available from http://srdata.nist.gov/its90/download/type_k.tab
double c[] = {-0.176004136860E-01, 0.389212049750E-01, 0.185587700320E-04, -0.994575928740E-07, 0.318409457190E-09, -0.560728448890E-12, 0.560750590590E-15, -0.320207200030E-18, 0.971511471520E-22, -0.121047212750E-25};
// Count the the number of coefficients. There are 10 coefficients for positive temperatures (plus three exponential coefficients),
// but there are 11 coefficients for negative temperatures.
int cLength = sizeof(c) / sizeof(c[0]);
// Exponential coefficients. Only used for positive temperatures.
double a0 = 0.118597600000E+00;
double a1 = -0.118343200000E-03;
double a2 = 0.126968600000E+03;
// From NIST: E = sum(i=0 to n) c_i t^i + a0 exp(a1 (t - a2)^2), where E is the thermocouple voltage in mV and t is the temperature in degrees C.
// In this case, E is the cold junction equivalent thermocouple voltage.
// Alternative form: C0 + C1*internalTemp + C2*internalTemp^2 + C3*internalTemp^3 + ... + C10*internaltemp^10 + A0*e^(A1*(internalTemp - A2)^2)
// This loop sums up the c_i t^i components.
for (i = 0; i < cLength; i++) {
internalVoltage += c[i] * pow(internalTemp, i);
}
// This section adds the a0 exp(a1 (t - a2)^2) components.
internalVoltage += a0 * exp(a1 * pow((internalTemp - a2), 2));
}
else if (internalTemp < 0) { // for negative temperatures
double c[] = {0.000000000000E+00, 0.394501280250E-01, 0.236223735980E-04 - 0.328589067840E-06, -0.499048287770E-08, -0.675090591730E-10, -0.574103274280E-12, -0.310888728940E-14, -0.104516093650E-16, -0.198892668780E-19, -0.163226974860E-22};
// Count the number of coefficients.
int cLength = sizeof(c) / sizeof(c[0]);
// Below 0 degrees Celsius, the NIST formula is simpler and has no exponential components: E = sum(i=0 to n) c_i t^i
for (i = 0; i < cLength; i++) {
internalVoltage += c[i] * pow(internalTemp, i) ;
}
}
// Step 4. Add the cold junction equivalent thermocouple voltage calculated in step 3 to the thermocouple voltage calculated in step 2.
double totalVoltage = thermocoupleVoltage + internalVoltage;
// Step 5. Use the result of step 4 and the NIST voltage-to-temperature (inverse) coefficients to calculate the cold junction compensated, linearized temperature value.
// The equation is in the form correctedTemp = d_0 + d_1*E + d_2*E^2 + ... + d_n*E^n, where E is the totalVoltage in mV and correctedTemp is in degrees C.
// NIST uses different coefficients for different temperature subranges: (-200 to 0C), (0 to 500C) and (500 to 1372C).
if (totalVoltage < 0) { // Temperature is between -200 and 0C.
double d[] = {0.0000000E+00, 2.5173462E+01, -1.1662878E+00, -1.0833638E+00, -8.9773540E-01, -3.7342377E-01, -8.6632643E-02, -1.0450598E-02, -5.1920577E-04, 0.0000000E+00};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
}
else if (totalVoltage < 20.644) { // Temperature is between 0C and 500C.
double d[] = {0.000000E+00, 2.508355E+01, 7.860106E-02, -2.503131E-01, 8.315270E-02, -1.228034E-02, 9.804036E-04, -4.413030E-05, 1.057734E-06, -1.052755E-08};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
}
else if (totalVoltage < 54.886 ) { // Temperature is between 500C and 1372C.
double d[] = {-1.318058E+02, 4.830222E+01, -1.646031E+00, 5.464731E-02, -9.650715E-04, 8.802193E-06, -3.110810E-08, 0.000000E+00, 0.000000E+00, 0.000000E+00};
int dLength = sizeof(d) / sizeof(d[0]);
for (i = 0; i < dLength; i++) {
correctedTemp += d[i] * pow(totalVoltage, i);
}
} else { // NIST only has data for K-type thermocouples from -200C to +1372C. If the temperature is not in that range, set temp to impossible value.
// Error handling should be improved.
Serial.print("Temperature is out of range. This should never happen.");
correctedTemp = NAN;
}
Serial.print("Corrected Temp = ");
Serial.println(correctedTemp, 5);
Serial.println("");
}
delay(1000);
}
- adafruit_support_bill
- Posts: 88153
- Joined: Sat Feb 07, 2009 10:11 am
Re: Max 31855 Reading High Temperatures
Thanks! Updated.
- Declan
- Posts: 11
- Joined: Mon Aug 17, 2015 4:48 am
Re: Max 31855 Reading High Temperatures
Hi,
I have a Adafruit Thermocouple Amplifier MAX31855 breakout board.
As we only use J-Type thermocouples, I have replaced the MAX31855K with the MAX31855J.
Using the sketch provided, my temperature readings are approx +10 C higher that actual temperature being read.
I see from the MAX31855 datasheet that the Sensitivity of the K-Type is 41.276 (μV/°C) and the J-Type is 57.953 (μV/°C).
Where would I be able to change this in the sketch examples?
Is it possible to read the faults, if any, from the MAX31855?
I have a Adafruit Thermocouple Amplifier MAX31855 breakout board.
As we only use J-Type thermocouples, I have replaced the MAX31855K with the MAX31855J.
Using the sketch provided, my temperature readings are approx +10 C higher that actual temperature being read.
I see from the MAX31855 datasheet that the Sensitivity of the K-Type is 41.276 (μV/°C) and the J-Type is 57.953 (μV/°C).
Where would I be able to change this in the sketch examples?
Is it possible to read the faults, if any, from the MAX31855?
- heypete
- Posts: 32
- Joined: Sat Jan 11, 2014 4:50 pm
Re: Max 31855 Reading High Temperatures
In my sketch you'd need to changeDeclan wrote:Hi,
I have a Adafruit Thermocouple Amplifier MAX31855 breakout board.
As we only use J-Type thermocouples, I have replaced the MAX31855K with the MAX31855J.
Using the sketch provided, my temperature readings are approx +10 C higher that actual temperature being read.
I see from the MAX31855 datasheet that the Sensitivity of the K-Type is 41.276 (μV/°C) and the J-Type is 57.953 (μV/°C).
Where would I be able to change this in the sketch examples?
Is it possible to read the faults, if any, from the MAX31855?
Code: Select all
thermocoupleVoltage = (rawTemp - internalTemp)*0.041276;
Code: Select all
thermocoupleVoltage = (rawTemp - internalTemp)*0.057953;
- The NIST formula for K-type thermocouples defines coefficients to calculate the expected thermocouple voltage for a given temperature for two temperature ranges -270C to 0C and 0C to +1372C. J-type thermocouples have ranges from -270C to +760C and +760C to 1200C. The number of and values of the coefficients differ for each type. See here for details.
- The NIST formula also has exponential terms for K-type but not for J-type. The exponential terms would need to be removed for computing results with J-type thermocouples.
- NIST also defines reverse coefficients (for converting mV to degrees) for both types. As above, the temperature ranges and coefficients differ.
If you have any issues, let me know. I'd be happy to edit the code so should work for J-type thermocouples, but I have no way of testing it since I don't have any thermocouples of that type. If you're willing to be the guinea pig and do some tests, that'd be cool. :)
- Declan
- Posts: 11
- Joined: Mon Aug 17, 2015 4:48 am
Re: Max 31855 Reading High Temperatures
heypete,
Thanks for your reply - I have looked at our code and it looks awesome.
However,
is way over my head...
I would be more than happy to be the guinea pig as I would learn loads and hopefully others would be able to benefit.
Thanks for your reply - I have looked at our code and it looks awesome.
However,
Code: Select all
Additionally, you would need to change several aspects of the calculations:
I would be more than happy to be the guinea pig as I would learn loads and hopefully others would be able to benefit.
- Declan
- Posts: 11
- Joined: Mon Aug 17, 2015 4:48 am
Re: Max 31855 Reading High Temperatures
Sorry, I forgot to mention that I am only reading positive temperatures in the range 0 - 400 C
Please be positive and constructive with your questions and comments.