Forum members heypete and jh421797 have implemented the NIST K-type thermocouple equations for the Max31855 thermocouple amplifier.
The code is posted below:
You can check out the original forum thread here:
Code from jh421797
// corrected temperature reading for a K-type thermocouple // allowing accurate readings over an extended range // http://forums.adafruit.com/viewtopic.php?f=19&t=32086&p=372992#p372992 // assuming global: Adafruit_MAX31855 thermocouple(CLK, CS, DO); float correctedCelsius(){ // MAX31855 thermocouple voltage reading in mV float thermocoupleVoltage = (thermocouple.readCelsius() - thermocouple.readInternal()) * 0.041276; // MAX31855 cold junction voltage reading in mV float coldJunctionTemperature = thermocouple.readInternal(); float coldJunctionVoltage = -0.176004136860E-01 + 0.389212049750E-01 * coldJunctionTemperature + 0.185587700320E-04 * pow(coldJunctionTemperature, 2.0) + -0.994575928740E-07 * pow(coldJunctionTemperature, 3.0) + 0.318409457190E-09 * pow(coldJunctionTemperature, 4.0) + -0.560728448890E-12 * pow(coldJunctionTemperature, 5.0) + 0.560750590590E-15 * pow(coldJunctionTemperature, 6.0) + -0.320207200030E-18 * pow(coldJunctionTemperature, 7.0) + 0.971511471520E-22 * pow(coldJunctionTemperature, 8.0) + -0.121047212750E-25 * pow(coldJunctionTemperature, 9.0) + 0.118597600000E+00 * exp(-0.118343200000E-03 * pow((coldJunctionTemperature-0.126968600000E+03), 2.0) ); // cold junction voltage + thermocouple voltage float voltageSum = thermocoupleVoltage + coldJunctionVoltage; // calculate corrected temperature reading based on coefficients for 3 different ranges float b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10; if(thermocoupleVoltage < 0){ b0 = 0.0000000E+00; b1 = 2.5173462E+01; b2 = -1.1662878E+00; b3 = -1.0833638E+00; b4 = -8.9773540E-01; b5 = -3.7342377E-01; b6 = -8.6632643E-02; b7 = -1.0450598E-02; b8 = -5.1920577E-04; b9 = 0.0000000E+00; } else if(thermocoupleVoltage < 20.644){ b0 = 0.000000E+00; b1 = 2.508355E+01; b2 = 7.860106E-02; b3 = -2.503131E-01; b4 = 8.315270E-02; b5 = -1.228034E-02; b6 = 9.804036E-04; b7 = -4.413030E-05; b8 = 1.057734E-06; b9 = -1.052755E-08; } else if(thermocoupleVoltage < 54.886){ b0 = -1.318058E+02; b1 = 4.830222E+01; b2 = -1.646031E+00; b3 = 5.464731E-02; b4 = -9.650715E-04; b5 = 8.802193E-06; b6 = -3.110810E-08; b7 = 0.000000E+00; b8 = 0.000000E+00; b9 = 0.000000E+00; } else { // TODO: handle error - out of range return 0; } return b0 + b1 * voltageSum + b2 * pow(voltageSum, 2.0) + b3 * pow(voltageSum, 3.0) + b4 * pow(voltageSum, 4.0) + b5 * pow(voltageSum, 5.0) + b6 * pow(voltageSum, 6.0) + b7 * pow(voltageSum, 7.0) + b8 * pow(voltageSum, 8.0) + b9 * pow(voltageSum, 9.0); }
Code from 'heypete'
For the latest updates, please see heypete's github repo:
#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); }