MAX6675 Thermocouple Interface

So I have been working all day interfacing the MAX6675 Mixed-signal and digital signal processing ICs | Analog Devices Thermocouple to Digital Converter. It took me a bit to learn some basic SPI, but I think I have it down now for this chip. This chip is great and seems to work ok right now. It to me awhile to get all the conversions right, but things are looking good now.

The only thing I am still having problems with is the Open Thermocouple detection on Bit 2. It always seems to return 0 :frowning: Please let me know if you have any idea what is going on.

I hope to get this polished and up on the playground and my own site soon. Maybe make a library? Please give me your feedback!

/*
  Temperature Reading from a MAX6675
  
  Ryan McLaughlin <ryanjmclaughlin@gmail.com>
*/

#define SO 12    // MISO
#define SCK 13   // Serial Clock

#define TC_0 11  // CS Pin of MAX6607
int TC_0_calib = 0;  // Calibration compensation value in digital counts (.25[ch730]C)

void setup() {
 
 pinMode(SO, INPUT);
 pinMode(SCK, OUTPUT);
 
 pinMode(TC_0, OUTPUT);
 digitalWrite(TC_0,HIGH);  // Disable device

 Serial.begin(9600);
}


/* Create a function read_temp that returns an unsigned int
   with the temp from the specified pin (if multiple MAX6675).  The
   function will return 9999 if the TC is open.
   
   Usage: read_temp(int pin, int type, int error)
     pin: the CS pin of the MAX6675
     type: 0 for [ch730]F, 1 for [ch730]C
     error: error compensation in digital counts
     samples: number of measurement samples (max:10)
*/
unsigned int read_temp(int pin, int type, int error, int samples) {
  unsigned int value = 0;
  int error_tc;
  float temp;
  unsigned int temp_out;
  
  for (int i=samples; i>0; i--){
    digitalWrite(pin,LOW); // Enable device

    /* Cycle the clock for dummy bit 15 */
    digitalWrite(SCK,HIGH);
    digitalWrite(SCK,LOW);

    /* Read bits 14-3 from MAX6675 for the Temp 
       Loop for each bit reading the value and 
       storing the final value in 'temp' 
    */
    for (int i=11; i>=0; i--){
      digitalWrite(SCK,HIGH);  // Set Clock to HIGH
      value += digitalRead(SO) << i;  // Read data and add it to our variable
      digitalWrite(SCK,LOW);  // Set Clock to LOW
    }
  
    /* Read the TC Input inp to check for TC Errors */
    digitalWrite(SCK,HIGH); // Set Clock to HIGH
    error_tc = digitalRead(SO); // Read data
    digitalWrite(SCK,LOW);  // Set Clock to LOW
  
    digitalWrite(pin, HIGH); //Disable Device
  }
  
  value = value/samples;  // Divide the value by the number of samples to get the average
  
  /* 
     Keep in mind that the temp that was just read is on the digital scale
     from 0[ch730]C to 1023.75[ch730]C at a resolution of 2^12.  We now need to convert
     to an actual readable temperature (this drove me nuts until I figured 
     this out!).  Now multiply by 0.25.  I tried to avoid float math but
     it is tough to do a good conversion to [ch730]F.  THe final value is converted 
     to an int and returned at x10 power.
     
   */
   
  value = value + error;  // Insert the calibration error value
  
  if(type == 0) {  // Request temp in [ch730]F
    temp = ((value*0.25) * (9.0/5.0)) + 32.0;  // Convert value to [ch730]F (ensure proper floats!)
  } else if(type == 1) {  // Request temp in [ch730]C
    temp = (value*0.25);  // Multiply the value by 25 to get temp in [ch730]C
  }
  
  temp_out = temp*10;  // Send the float to an int (X10) for ease of printing.
  
  /* Output 9999 if there is a TC error, otherwise return 'temp' */
  if(error_tc != 0) { return 9999; } else { return temp_out; }
}

void loop() {
  
  // Read the temperature and print it to serial
  Serial.print("Temp F: ");
  Serial.print(read_temp(TC_0,0,TC_0_calib,10));  
  Serial.print("\tTemp C: ");
  Serial.println(read_temp(TC_0,1,TC_0_calib,10));
 
  delay(250);
}

Just got the Open Thermocouple detection working.... I forgot to ground the T- lead!

This is great! I think a library would be excellent.

I'm curious what you're planning to use the temperature measurement for? Also what kind of accuracy are you seeing from the MAX6675?

I've been using an AD595CQ with a thermocouple to make a general purpose kitchen appliance controller, using a relay. It makes it easy to set the temperature of a water bath for various types of cooking, or control a hot pad for dough proofing, etc. I'm interested in the MAX because it's both cheaper and promises higher accuracy, which I could actually use for some more finicky stuff.

Glad you can use it, I will post when I refine the Code a bit more. I am going to be using it for a temp control ( search ac dimming for the power side of it ).

I was getting fairly good accuracy, within a degree or so out of the box without adding any calibration, however I have not checked it over the full range.

It is very nice that is is cheaper, I plan to have 4 on a board and I can do it without a multiplexer cause there cheap. (6.60ea for 25)

Where are you getting it for that cheap? Digikey shows it as over $10 for 25, and $6.60 for 50.

Maxim Direct

I wrote a library for this, but cannot seem to get my example to compile. The code is going to be posted here Google Code Archive - Long-term storage for Google Code Project Hosting. and playground Arduino Playground - MAX6675Library

I am getting the following error:

In file included from /Applications/arduino-0012/hardware/cores/arduino/WProgram.h:4,

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:80: error: expected unqualified-id before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:80: error: expected `)' before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:80: error: expected `)' before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:111: error: expected unqualified-id before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:111: error: expected `)' before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:111: error: expected `)' before 'int'

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:144: error: expected identifier before '(' token

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:144: error: expected `)' before '(' token

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:144: error: expected ',' or '...' before '(' token

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:144: error: expected initializer before ')' token

/Applications/arduino-0012/hardware/tools/avr/bin/../lib/gcc/avr/4.3.0/../../../../avr/include/stdlib.h:176: error: '__compar_fn_t' has not been declared

In file included from /Applications/arduino-0012/hardware/cores/arduino/WProgram.h:6,

Any ideas?

Got it working... http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1232303758/0

The library is available at Arduino Playground - MAX6675Library Check it out!

Ryanjmclaughlin, I looked on Maxim Direct and it says $15.00. But on Sparkfun it's only $12. Can you please give me the link where you got it from? Thanks

It seems like they have raised their prices since the last time I got them. Most recently I bought some larger quantities from Newark.

Sparkfun is the cheapest for single quantities. I really love those guys!

You can also pick them up on my site http://ryanjmclaughlin.com/shop/max6675-thermocouple-to-digital-chip/ I have also created some breakout boards for the chip that are for sale as well. Check it out ryanjmclaughlin.com. Use "NewCustomer" at checkout for 10% off an order through the end of the month.

Ryan -

Wish I had seen your post first, but I didn't so I tackled this without the benefit of your experience.

I downloaded the Spi library and used it without tweaking.

// Demo application to read MAX6675 chip using
// Serial Peripheral Interface (SPI)

#include <Spi.h>

// Pin connections to Arduino:
// chip select = 10 = SS_PIN
// clock = 13 = SCK_PIN
// MAX6675 output = 12 = MISO_PIN

#define DESELECT digitalWrite( SS_PIN, HIGH )
#define SELECT digitalWrite( SS_PIN, LOW )

void setup()
{
DESELECT; // deselect the MAX6675
Spi.mode( ( ( 1 << SPR1 ) | ( 1 << CPHA )) ); // set SPI interface mode 1, 2Mhz clock
Serial.begin( 9600 );
}

void loop()
{
unsigned char highByte = 0;
unsigned char lowByte = 0;
float tempF;
short ivalue;

delay(500);

// select the device, wait > 100nS, read two bytes, deselect
SELECT;
delayMicroseconds(1);
highByte = Spi.transfer( 0 );
lowByte = Spi.transfer( 0 );
DESELECT;

// if bit 3 is high thermocouple is unconnected
if (lowByte & (1<<2)) {
Serial.print("Not connected ");
Serial.print(highByte, HEX);
Serial.print(" ");
Serial.println(lowByte, HEX);
}
else {
// temperature value is in bits 6-0 of highByte and 7-2 of lowByte
ivalue = ( highByte << 5 | lowByte >> 3 );
tempF = ivalue * 0.25 * 1.8 + 32.0;
Serial.println( tempF );
}
}

The only problem I've run into is the self-heating of the MAX6675, on the order of 10C or more at room temperature. Connecting the t/c leads at a point that matches the chip temperature is going to be a challenge.

Jim

Thanks JimG. That seems to work great. I just wrote my own at the time because I wanted a smaller footprint for the library than having to use the SPI library.

Thanks for this info!

I'd just like to add my thanks to this thread: I've been looking for a high-temperature-capable method of getting temps into the Arduino, and this is perfect [smiley=thumbsup.gif]

As I don't need the Fahrenheit conversion nor part-degree accuracy, I'd planned to bit-shift the result 2-bits to the left, which I guess should be faster than doing a f.p. multiply by 0.25? I could also simply ignore the final 2 bits of data when reading the port...

Anyway, the electronic bits are due here Monday, hopefully I'll have something cobbled together shortly afterwards :slight_smile:

You could prob just drop the last two as you said. The raw output of the chip is a 0-4095 coresponding to 0-1023degC. I havn't tried it though.

FYI I now have breakout boards for this chip to a thermocouple connector on my site. http://ryanjmclaughlin.com

Very well made and easy to use... I might add Nice work!

FYI I now have breakout boards for this chip to a thermocouple connector on my site. http://ryanjmclaughlin.com

Yeah, I saw those, they look neat. What's the postage cost to the UK?

At the moment, I'm only going to be using one thermocouple, as I experiment, but in the future, I may look at getting one of your multi-chip boards... I like the idea of being able to read 6 or so sensors using just 3 Arduino pins...

Cheapest shipping is $5USD standard post. Or other options too.

Keep in mind you need 2 pins SO, SCK, plus one for each chips CS pin. So, 4ch is 6 pins of I/O for the max6675 chips.

I had wondered about using a shift register to drive the appropriate CS. As a minimum, I think I would need:

1 pin for the clock (SR & MAX would all use this clock)
1 pin for SR latch
1 pin for SR serial out
1 pin for MAX serial in.

The sequence would be:

1 Write the appropriate 8-bit value into the SR (e.g. 00010000 to pick the 5th chip) using SR & clock
2 Pulse LATCH to activate the CS.
3 Read 16 bits from the MAX using the clock.
4 Pick another number, and goto step 1

With 1 SR, that's up to 8 MAXs with 4 pins. I'm not sure if each MAX chip output would need to be buffered?

Superb!

The thermocouple & MAX chip arrived this morning, so, once I'd spent a frustrating and delicate 1/2 hour attaching the MAX chip to a DIP socket, it was time to quickly breadboard up a simple circuit:

Guess what? It works perfectly! So, thank you Ryan for working out how to do it & for sharing :slight_smile:

This evening, I will try it out as it's supposed to be used.... in the exhaust stream of an engine...

Hi!
I've been trying to reproduce the design here, but something isn't right.
I can get indication of thermocouple error OK when it's not connected, but when i try to get the readings it shows 0.00 celsius degrees on ambient temperature. If I get the thermocouple very hot then there is some reading different from 0. I've even switched the max6675 with another one, brand new, and the same happened. (both were samples from maxim).
The strangest thing happens when I try to measure the voltage across the pins with a multimeter. With the test leads on ground and pin 11 (SO) the display reads somthing other than 0.00, but always under the room temperature.
Any ideas? Do I need a pull-down resistor on SO?
Couldn't find any reference on the internet about a similar behavior.
I'm using an Arduino Mega.

Thanks