A lot of errors with two thermocouples

Hi,
I am running two of these:

with these:
http://www.ebay.com/itm/K-Type-10cm-Probe-Thermocouple-Temperature-Measurement-Sensor-70cm-/310570751975?pt=LH_DefaultDomain_0&hash=item484f7597e7
and an SPI OLED display.

The wireing is quite straightforward:

//SPI
const byte SPI_CLK = 13;
const byte SPI_MOSI = 11;
const byte SPI_MISO = 12;

//OLED
const byte OLED_CS = 7;
const byte OLED_DC = 8;
const byte OLED_RESET = 9;

//Thermocouple
const byte TC1_CS = 2;
const byte TC2_CS = 4;

That is, they all share CLK, the two thermocouple amplifiers share MISO. The full code (with some preparations for further functionality) is below.

Now, unfortunately, I get alot of NAN from the thermocouples. Every maybe 30 seconds, a reading is successful, and the temperature is plausible. I would assume that the cheap thermocouples are just garbage, but the strange thing is: successful reading are highly correlated. They haven at the same time or at least within one or two seconds in 95% of the time. That doesn't seem to be something that happens through defective tp ... any idea, anyone?
If I just disconnect one thermocouple, it is not better in any way.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MAX31855.h>
#include <Servo.h>
#include <CapacitiveSensor.h>

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

//SPI
const byte SPI_CLK = 13;
const byte SPI_MOSI = 11;
const byte SPI_MISO = 12;

//OLED
const byte OLED_CS = 7;
const byte OLED_DC = 8;
const byte OLED_RESET = 9;

//Thermocouple
const byte TC1_CS = 2;
const byte TC2_CS = 4;

//Servo
const byte SERVO = 4;

//Buttons
const byte BUT_SEND = 5;

//Adafruit_SSD1306 display(SPI_MOSI, SPI_CLK, OLED_DC, OLED_RESET, OLED_CS);
Adafruit_SSD1306 display(11, 13, 8, 9, 7);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16
static unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

Adafruit_MAX31855 thermocouple[] = { Adafruit_MAX31855(SPI_CLK, TC1_CS,
SPI_MISO), Adafruit_MAX31855(SPI_CLK, TC2_CS, SPI_MISO) };
double temp[] = {0,0,0,0};

CapacitiveSensor button[] = {CapacitiveSensor(5,A0),\
                             CapacitiveSensor(5,A1),\
                             CapacitiveSensor(5,A2),\
                             CapacitiveSensor(5,A3),\
                             CapacitiveSensor(5,A4),\
                             CapacitiveSensor(5,A5)};
boolean buttonState[]  = {false,false,false,false,false,false};
boolean buttonAction[] = {false,false,false,false,false,false};
long    buttonTime[]   = {0,    0,    0,    0,    0,    0};
const byte BUTTON_N = 6;
const byte DEBOUNCE_DELAY = 20;

void setup() {
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  display.clearDisplay();
}

void loop() {
  //controlButtons();
  displayTemperatures(0,2);
  delay(1000);
}

void displayTemperatures(byte l1, byte l2) {
  double tempNow[] = { 0,0,0,0 };

  boolean error[]={false,false};

  display.setTextSize(1);
  display.setTextColor(WHITE);

  for(int i=0; i<2; i++)
  {
    tempNow[2*i] = thermocouple[i].readCelsius();
    if(!isnan(tempNow[2*i]))
    {
      temp[2*i]=tempNow[2*i];
    }
    else
    {
      error[i]=true;
    }

    tempNow[2*i+1] = thermocouple[i].readInternal();
    if(!isnan(tempNow[2*i+1]))
    {
      temp[2*i+1]=tempNow[2*i+1];
    }
    else
    {
      error[i]=true;
    }
  }

  display.clearDisplay();
  for(int i=0; i<2; i++)
  {
    display.setCursor(2*10,i*2*10);
    display.print(temp[2*i]);
    display.print("/");
    display.print(temp[2*i+1]);
    display.print("      ");
    display.setCursor(0, 2*i*10);
    if(error[i])
    {
      display.print("E");
    }
    else
    {
      display.print(" ");
    }
  }
  display.display();
}

I have never used OLED or capacitive sensors so I don't know if they can have any effect on your SPI interface.

If it where me. I would start with one thermocouple and the serial interface. When I have verified that I am getting consistently good readings, I would then add the second thermocouple. I would continue too build and test, resolving the problems along the way.

I also believe that pin 10 must be used as a CS for something. I believe the TWI sets up the pin even if it is not used.

I know that I have not been much help but I do offer my moral support.

Thanks anyway :slight_smile: I hoped for someone with an easy anther, since I always have to lie in front of my fireplace for testing :slight_smile:

So, what I did now:

  • Test a single thermocouple with serial example. Worked like a charm, so those things are not the problem by themselves.
  • Add all the libraries to the code. Didn't change anything, still worked.
    Back to the original setup:
  • Disconnected one amplifier physically: other one still has errors
  • Removed one amplifier from the code: other one still has errors
  • Physically removed OLED: still errors
  • Removed OLED from the code: still errors

I'm starting to think it's something in the wireing ...

the next test should be 2 thermocouples with serial

if that works, two thermo couples with the OLED.

BTW, a NAN is often an indication of a division by zero.
Do you have a link to the library used?
Datasheet?

maybe the sensors need a time out after a read. e.g. a delay(1000) between reads..

Yes, I'll test that next year. Guests are about to arrive :slight_smile:

Here is a link to the library:

The example says:

if (isnan(c)) {
     Serial.println("Something wrong with thermocouple!");
   } else {

Here is a datascheet for the chip on the breakout:

and here are the layout files for the breakout:

Make sure you understand how SPI works when you are using more than one SPI device. The master device ( the arduino ) has to correctly manipulate the CS line to each device that it wants to communicate with.

It should be possible to determine from the information about the interface board, how often it takes a reading.

There is something buggy in the library

compare

double Adafruit_MAX31855::readInternal(void) 
{
  uint32_t v;
  v = spiread32();
  // ignore bottom 4 bits - they're just thermocouple data
  v >>= 4;
...

to
// stripped comments

double Adafruit_MAX31855::readCelsius(void)
{
  int32_t v;
  v = spiread32();

  if (v & 0x7) {
    // uh oh, a serious problem!
    return NAN; 
  }
  ...
}

Seems that the readInternal throws away 4 status? bits where readCelsius checks them and returns a NAN.
So at least the library seems not consitent.

Reading the datasheet the 3 bits tested that generate the NAN indicate: [PAGE 8, 2nd column]
Bits D0, D1, and D2 of the output data are normally low.

  • Bit D2 goes high to indicate a thermocouple short to VCC,
  • Bit D1 goes high to indicate a thermocouple short to GND,
  • Bit D0 goes high to indicate a thermocouple open circuit.

Three possible causes you need to investigate.

@robtillaart
readInternal reads the internal thermometer of the chip. That always works for me in any setup. I don't think it is inconsistent not to display errors in the external thermocouple when reading the internal one.
Anyway, that was interesting information. Thanks! However, all these things should lead to errors independent of the way I read the sensors, shouldn't it?

@michinyon
I thought I do understand SPI. Is there anything in the code that says I don't?

Happy new year, BTW :slight_smile:

I did more testing and indeed, the problem starts as soon a I connect the second amplifier, despite the fact that

claims it is possible with shared pins.
I have attached a photo of my setup, in case I am misunderstanding something completely.

ElCaron:
@robtillaart
readInternal reads the internal thermometer of the chip. That always works for me in any setup.
...
However, all these things should lead to errors independent of the way I read the sensors, shouldn't it?[

I know it reads the internal sensor. but if it does not check for errors (it just shifts them out!) it is far easier not to fail ....
it just ignores.

What I meant was: If there is short or open circuit, it should be be working in a single TC setup :slight_smile:

is it possible that 2 MAX31855's draw just too much current?

The datasheet says max I_CC is 1500uA ... Also, my USB supply is rated for 2A.

yes but there is an Arduino in between that as its own limits ...

Adafruit_MAX31855 thermocouple[] = { Adafruit_MAX31855(SPI_CLK, TC1_CS,
SPI_MISO), Adafruit_MAX31855(SPI_CLK, TC2_CS, SPI_MISO) };

Have you tried defining thermocouples as separate entities instead of part of an array?

@riva
Yes, I have. Also, the problem already starts when I just connect a second element in addition to the first one.

@robtillaart
Still unlikely with 1.5mA. But Ill test it. I will also have a look which line exactly causes the malfunction.

ElCaron:
@riva
Yes, I have. Also, the problem already starts when I just connect a second element in addition to the first one.

What if you use pulldown resistors on the MOSI, CS & CLK buses?

I think I found the problem. I tried to power the second amplifier from a breadboard power supply with common ground with the Arduino. Then I wanted to see if the DO or CLK line causes the errors. What I found was, that only connecting the power pins, even from another supply, where enough to trigger the problem. So what I found was that the housings of the two thermocouples were electrically connected via an aluminium tube for ventilation - though I have to admit that I didn't know they were not allowed to.
No, after I isolated one of the couples and made sure that not even the braided metal covers of the cables touch, the isolated one works properly. The other one, which goes into the metal exhaust pipe, still gives errors about every second reading. I can live with that, if I have to.

@Riva:
The communication seems to work fine, since I can always read the internal temperature.

Grounds of the different power supplies and the Arduino should be connected to create a common ground
(= reference for all signals)

Thanks, I have done that. It is also in my last posting :wink: