Photon w/ MAX31855 Thermocouple Amplifier (intermitent response)


#1

As in the title, I’m trying to read two thermocouples through two MAX31855 amps into Photon.

Problem is it usually reports 0.0F 95% of the time or something close to reality the other 5%.
Unfortunately the zeros are happening quite often…
Keep sampling until I get a good read and meanwhile toss out anything = 0???

3v3 to the amps from photon
5.15v to photon

Here’s my code if it would help:

// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_MAX31855.h"

// This #include statement was automatically added by the Particle IDE.
#include "SimpleTimer.h"

SimpleTimer timer;

int T_DO   = D5;
int T_CS   = D4;
int T_CLK  = D3;
int B_DO   = D2;
int B_CS   = D1;
int B_CLK  = D0;

int top_relay = D6;
int bot_relay = D7;

int SETPOINT  = 300;    //TEMP IN F 

volatile double TOP_T;
volatile double BOT_T;

typedef enum stateType_enum{
    top_on, top_off, bot_on, bot_off
} stateType;
stateType topState = top_off;
stateType botState = bot_off;

Adafruit_MAX31855 TopThermo(T_CLK, T_CS, T_DO);
Adafruit_MAX31855 BotThermo(B_CLK, B_CS, B_DO);







void setup()
{

//timer.setInterval(1 * 60 * 1000, publishData);

Time.zone(-7);

pinMode(top_relay,OUTPUT);
    digitalWrite(top_relay,LOW);   // OFF
pinMode(bot_relay,OUTPUT);
    digitalWrite(bot_relay,LOW);   // OFF
}





void loop() {

    timer.run();
    
   
    TOP_T = TopThermo.readFarenheit();
    BOT_T = BotThermo.readFarenheit();

    
    
    
    switch(topState){
        case top_on:
            if (TOP_T >= SETPOINT)
                {
                digitalWrite(top_relay,LOW);
                topState = top_off;
                }
            else {}
        break;

        case top_off:
            if (TOP_T <= SETPOINT)
                {
                digitalWrite(top_relay,HIGH);
                topState = top_on;
                }
            else {}
        break;
    }

switch(botState){
        case bot_on:
            if (BOT_T >= SETPOINT)
                {
                digitalWrite(bot_relay,LOW);
                botState = bot_off;
                }
            else {}
        break;

        case bot_off:
            if (BOT_T <= SETPOINT)
                {
                digitalWrite(bot_relay,HIGH);
                botState = bot_on;
                }
            else {}
        break;
    }

    Particle.publish("TOP",String(TOP_T,1));
    Particle.publish("BOTTOM",String(BOT_T,1));
delay(10 * 1000);

}

void publishData(){
   // Particle.publish("TOP",String(TOP_T,1));
   // Particle.publish("BOTTOM",String(BOT_T,1));

}

#2

Does this have something to do with SPI and having chosen the wrong pins?
It seemed as if you could somewhat arbitrarily chose any digital pin in the examples…

–or–

https://forums.adafruit.com/viewtopic.php?f=19&t=96088
^^^ This guy suggests a 4k7 resistor between ground and CLK. Does that have any merit?


#3

Are you using a breakout board or have you wired the MAX31855 yourself?
If you are using the Adafruit breakout they have a 10k pull-up and a protection diode on CLK so adding a 4k7 pull-down on the same pin seems odd to me, but for a quick test whether this helps I’d not see a problem.
If it helps I’d maybe rather remove the 10k pull-up and bridge the diode. This setup is only required for 5V µCs.

Also have you got common GND and are you supplying the breakout from Vin or 3v3? I’d go with Vin <-> Vin
The 3Vo pin on the breakout is an output so don’t connect the Photons 3v3 to that.


#4

Scruff!

Thanks for the reply. I guess some pictures would have helped.

  • Yes Breakout MAX31855 boards
  • 3v3 to Vin pins
  • Ground is shared between the two boards - coming directly from ACDC 5v transformer. (better if it was FROM photon?)

Maybe I’ll give the 4k7 pull down a shot …


#5

How good is the DC coming from there? The Photon doesn’t like ripple very much and the amp quality might be influenced too :wink:


#6

I do have a small osciliscope… How much ripple is too much?

It is a random wall wart for who knows what. I’ll check the brand.

Do you think my pin selection is okay? (see code) Or should I be using SPI specific pins? (i’ve seen people not use them and have success)


#7

I haven’t looked into the library implementation but given the fact that you can supply the pins I’d say it uses SW SPI (aka bitbanging) so any pin should be fine.


#8

My apologies for the lack of response. Im back in my workshop now but unsure where to start troubleshooting…

Would a capacitor across the powersupply be a good place to start?

Still same symptoms… both top and bottom thermocouple read 0.00 95% of the time.
The other 5% are actual readings.


#9

So I’m back in the shop and still cant figure out the issue.

If I ‘read internal’ I get reasonable values!!! Otherwise reading far/cels gives readings of zero…

Starting to think that i’ve got bad thermocouples.


#10

Since it’s some time, what does your current setup look like?
Have you now tried the 4k7?
Have you added the cap on the supply side of the Photon?
Is the code still the same?

I’d try a stripped down test code that only uses one sensor at a time and reads it with a slow pace.
Once you get consistent good readings you can extend the project.
Since the arrival of Software Timers by default I don’t see much benefit in using SimpleTimer anymore.

You could also give this alternative library a try
https://build.particle.io/libs/adafruit-max31855/0.0.3/tab/example/serial-thermocouple.cpp

BTW, since you are only using your state variables to know what state your relay pins are, you can actually just digitalRead() these pins even when they are set for OUTPUT.
This can help streamline the code and doesn’t impact execution time that much. If performance was an issue, you could use pinReadFast() and pinSetFast()/pinResetFast() instead.

In order to reduce the active code a bit more you could employ arrays and loops like this

#include <Adafruit_MAX31855.h>
#include <math.h>

const int SETPOINT   = 300;    //TEMP IN F 

struct controlData_t {
  const int pinCLK;
  const int pinCS;
  const int pinDO;
  const int pinRelay;
  const int tempThreshold;
  double    tempCurrent;
  Adafruit_MAX31855* sensor;  
};

controlData_t control[] = { 
  { D3, D4, D5, D6, SETPOINT, NAN, NULL }, 
  { D0, D1, D2, D7, SETPOINT, NAN, NULL }, 
};
const int controls = sizeof(control) / sizeof(control[0]);

void setup()
{
  Time.zone(-7);

  for (int c = 0; c < controls; c++) {
    control[c].sensor = new Adafruit_MAX31855(control[c].pinCLK, control[c].pinCS, control[c].pinDO);
    pinMode(control[c].pinRelay, OUTPUT);
    pinResetFast(control[c].pinRelay);   // OFF
  }
}

void loop() {
  char msg[32];

  for (int c = 0; c < controls; c++) {
    control[c].tempCurrent = control[c].sensor->readFarenheit();

    // reapplying the same pin state over and over again should not pose a problem but reduces code lines
    digitalWriteFast(control[c].pinRelay, control[c].tempCurrent < control[c].tempThreshold);
  }

  snprintf(msg, sizeof(msg), "TOP: %.1f, BOTTOM: %.1f", control[0].tempCurrent, control[1].tempCurrent);
  Particle.publish("Temp", msg, PRIVATE);

  delay(10 * 1000);
}

#11

I appreciate the in depth response!!!
your code is something id have to spend some time looking at to understand.

I have not tried the 4k7 resistor OR the cap…

HOWEVER - When I remove ONE of the amps/thermocouple out of the equation, the single remaining amp/thermocouple report temperature as expected and all is well!!

So I need to dig into why having TWO MAX31855 causes trouble…??
I have read this before and need to find that post…


#12

SOLVED!!!

So it turns out that if the thermocouples cannot be touching…
The problem was that I had everything fed through a hole in a project box.
The SS mesh sheathing of the two thermocouple leads were touching…
Not sure why that is the case but I will live.

It also appears that my thermocouple leads are identified backwards.

All is well now and I am reading two temps from two thermocouples from two max31855!

Thanks @ScruffR for your help!