Introducting - Integer Library for the MAX31855* thermocouple

Introducing a fast efficient Integer library for the MAX31855 K-Type thermocouple chip.

There are in fact a couple of other MAX31855 libraries. I tried them all. I settled on a library that Cory J. Fowler created as a starting point. I do not wish to use floating point for any scripting, as it is slow and unnecessary. I then started to rebuild Cory's library from the ground up. I also include a facility to 'fake thermocouple data', which is very helpful when debugging your projects. I have debugged this library extensively, and have high confidence in it's stability. I currently use the code to monitor a wood stove smoke pipe temperature ranging from 90 to 800 degrees C.

Things that are not obvious.

  • You only need to read the 'HOT' temperature. The 'COLD' is in fact the temperature of the chip itself.

  • Decimal bits for 'HOT' return integer 0 to 3. 0= 0.00 , 1=0.25, 2=0.50 and 3=0.75
    To use the 'bits' simply multiply the decimal bits by 25 and print that after printing a decimal point "." See the code example.

-Decimal bits for 'COLD' return integer 0 to 15. 0= 0.00 , 1= 0.0625 ... 15 =0.9375 No example included.

  • ThermalCouple.dataAvailable(SS_PIN) reads the chip register. You should not poll this continuously as the chip takes 70 to 100mS to complete. Once read successfully, the raw data is held and can be examined as often as you wish using ThermalCouple.dataRead(select). In the real world, temperatures rarely fluctuate in less than a second.

I hope you find the library useful!

This Adafruit board is extremely stable and easy to use.

Their included library however is not SPI, blocks, no fault bits, and uses more pins.

The library and following example is hosted here:

/*************************************************************************** 
  Library for the MAX31855* thermocouple chip from Maxim Semiconductor
  Written by S George Matthews with starting contributions from Cory J. Fowler
              MAX31855@fickleview.com     Rev 1.1
  BSD license, all text above must be included in any redistribution.
 **************************************************************************
 
This library uses integer only, no floating point to bog things down.
Only degrees C are returned. If you inhabit one of the two countries left in the World that 
still use Fahrenght, then you can code your own conversions.

Despite that I return only integer, there are decimal bits available that you can print out.
See examples.


 */
 
 
#include <SPI.h>
#include <Streaming.h>   // Serial.print alternative
#include <MAX31855_DEG_C.h>

// Pin used for Chip Select typicaly 10 with mmost shields that use SPI, so select another pin
// Place MAX31855_DEG_C_lib folder in Arduino/Libraries. Restart Arduino to picup the new library

#define SS_PIN 6            // MAX31855 Thermal couple board select pin

 #define HOT_THERMO_SELECT      0   // Returns signed compensated Hot-External temperature in degrees C rounded to the nearest degree, no decimal bits
 #define HOT_THERMO_SELECT_DEC  3   // Returns decimal bits.  1= .25, 2= .50, 3= .75

#define FAULT_THERMO_SELECT    4  // Returns the fault data as follows:
   #define FAULT_THERMO_SHORT_VCC 4
   #define FAULT_THERMO_SHORT_GND 2
   #define FAULT_THERMO_OPEN      1
   
#define DEBUG_TEMP

MAX31855_DEG_C ThermalCouple(SS_PIN);  

void setup() 
{
  Serial.begin(57600);
       pinMode(10, OUTPUT);    // If pin 10 is not used, it MUST be set as follows or SPI library will not work
  digitalWrite(10, HIGH);

  // put your setup code here, to run once:


}

void loop() 
{
  // put your main code here, to run repeatedly: 
  
       if(!(millis() % 1000))  // Every second
       {
        updateLEDtempDisplay();
       }
}

void updateLEDtempDisplay()
{
   if( ThermalCouple.dataAvailable(SS_PIN) )  // Always true for fake data
   {
    if (ThermalCouple.dataRead(FAULT_THERMO_SELECT))  //  Always 0 when fake data set in library
    {

     #ifdef DEBUG_TEMP
     Serial << F("ThermalCouple.dataRead(FAULT_THERMO_SELECT): ") << ThermalCouple.dataRead(FAULT_THERMO_SELECT) << endl;
     #endif
    }
    else
    {
      #ifdef DEBUG_TEMP
     Serial << F("ThermalCouple.dataRead(HOT_THERMO_SELECT): ") << ThermalCouple.dataRead(HOT_THERMO_SELECT) << endl;
     
     // Each decimal bit represents .25 degrees.
     Serial << F("With decimal: ") << ThermalCouple.dataRead(HOT_THERMO_SELECT) << "." << 25 * ThermalCouple.dataRead(HOT_THERMO_SELECT_DEC) << endl << endl;

     #endif
    }
    
    
    }
    else  // Fault reported
    {
       #ifdef DEBUG_TEMP
       if(!(millis() % 1000))  // Every second
       {
       Serial << F("ThermalCouple.dataAvailable(SS_PIN) reports not available. Wired SPI up correctly? Try #define DEBUG_DATA in the library") << endl;
       #endif
     }
    }
}

I like the idea you made it completely integer, small footprint, probably fast, well done!
do you have measured performance / footprint ?

(did 31855 recently myself - MAX31855 library - Libraries - Arduino Forum - )

small possible bug

 if(_data)                  
 {
  return true;
 }
 else
 {
 return false;
 }
}

if the read results in _data being 0x0000 it will return false ...
zero degrees, no status bits set , can happen (small chance ok but still) or ?

update:
Have you tested negative temperatures? I had a bug in my 31855 lib for them, confirmed and fixed today..

Hmmm... yes, a very small chance that _data will return false at 0 degrees.
However both HOT and COLD would have to be absolute 0.00 and 0.000

Yes, works on negative inputs, both HOT and COLD.

Give the Library a try.

looked at the code and my first tip is to put

#define HOT_THERMO_SELECT 0 // Returns signed compensated Hot-External temperature in degrees C rounded to the nearest degree, no decimal bits
#define HOT_THERMO_SELECT_DEC 3
etc

in the .h file so you can use them also in the .CPP file making the code more readable. Now it is full of magic numbers.

code could look like this (used a switch() to see more structure)

int MAX31855_DEG_C::dataRead(byte _selectData)
{ 
  _extractedDataH = _data >> 18 ;           // D31 to D18 last two bits decimal part
  _extractedDataC = (_data & 0xFFF0) >> 4;  // D14 to D2 aligning last 4 bits for the decimal portion

  switch(_selectData)
  {
  case FAULT_THERMO_SELECT:  
    return (_data & 0x7);

  case  HOT_THERMO_SELECT_DEC:
      return _extractedDataH & 0x3;

  case COLD_THERMO_SELECT_DEC:
      if (bitRead(_data,15))                     // D15 cold junction sign bit
      { 
        _extractedDataC += 0xFFFFF000;          // Make 8+4 bit a 32 bit number negative with leading ones
      }
     return _extractedDataC;
  ...

Hi, thanks for writing this library.

I am hoping to use it but when I run the code it gives me a

error: no match for 'operator<<' in 'Serial << (const __FlashStringHelper*)({...})'

on this line of code: Serial << F("ThermalCouple.dataRead(FAULT_THERMO_SELECT): ") << ThermalCouple.dataRead(FAULT_THERMO_SELECT) << endl;

I also noticed on the line : if (ThermalCouple.dataRead(FAULT_THERMO_SELECT))

that dataRead is not highlighted yellow like dataAvailable is.

Any help getting this code up and running would be great. My background is not in coding, so forgive me for not understanding everything, I'm working on it.

Your need to add:

#include <Streaming.h> // Serial.print alternative

" that dataRead is not highlighted yellow like dataAvailable is. "
These highlight colours are associated with keywords and is unrelated to any data returned.
I'll update the file to avoid confusion, however, the code will work fine as-is.

An extra 'Tab" in the Keywords.h file was the issue.
Fixed and committed to Github.
Thanks.

I recently solved an issue that had caused intermittent thermocouple shorted errors using the MAX31855.
The ungrounded USB power supply allowed the Arduino to 'float' causing spurious errors.
I grounded the Arduino to the chassis of the furnace and all has been well for months.
In retrospect, a common ground is good practice for any setup.

Hello George,
I know this is quite an old thread but I am facing a similar problem as you are the MAX31855 is intermittently setting fault bits I have an ungrounded thermocouple Type K connected to it, the MAX31855 is on a breakout board from Adafruit so I hope they have taken care of filtering issues.
The breakout board is connected to an Arduino Nano and is powered by an unregulated transformer power supply.
The usb on the nano is connected to a PC for serial data.
You said you grounded the arduino the furnace chassis? could you elaborate in more detail.

Make sure the Arduino ground (negative) is tied to the chassis of whatever you are monitoring.

Also bear in mind that most thermocouple probes have one wire connected to their stainless steel outer shell and exposed braided wire. If you touch ground (chassis), the probe will short and generate a probe fault.

I resolved that issue by winding a thin layer of fiberglass cloth around the probe and covered that with a small pipe. This electrically isolated the probe from the chassis, but also will reduce the response time.