Measuring 3 temperatures using max 6675

Hello,
I am currently doing a project to measure the temperature with 3 different thermocouples using the max6675 breakboards.
my circuit setup is the following
1 arduino uno rev 3
3 max 6675 breakboards
3 thermocouples

for each breakboard I connected them respectively to:
SO: 11 , 12, 13
CS: 10, 9, 8
SCK: 7, 6, 5
so for example first MAX is connected to the pins 11, 10 and 7 respectively.
the 5V and gnd of the arduino are connected each of them to a plate that all the 5V and gnd of the max are connected to.
my measurement code looked like this:

///////////////////
//libraries////////
///////////////////
// -SD reader
#include <SPI.h>
#include <SD.h>


// -Temp measurement
#include "max6675.h"


//****************/
//end libraries////
//****************/



//SD info
#define SD_CS    4                                                // Chip select line for SD card on Shield

//file definition values
String fileName="run";    // file name for storing data
int fileNumber=0;         // file index for fileName
File myFile;              // file object

//temp read
#define numberOfMeasurements 3
#define maxNumberOfPointsStored 15
int pinSO[numberOfMeasurements] = {13,12,11};
int pinCS[numberOfMeasurements] = {10, 9, 8};
int pinSCK[numberOfMeasurements]= { 7, 6, 5};

MAX6675 thermocouples[numberOfMeasurements] = {
  MAX6675(pinSCK[0], pinCS[0], pinSO[0]),
  MAX6675(pinSCK[1], pinCS[1], pinSO[1]),
  MAX6675(pinSCK[2], pinCS[2], pinSO[2])
};
const uint32_t minTimeMax6675=500;                                // min time in miliseconds for correct (temperature) measurement with the max6675
// in case that there are different sensors
uint32_t minTimes[numberOfMeasurements]={minTimeMax6675,minTimeMax6675,minTimeMax6675};               // min times list for each measurement
uint32_t minTime;                                // min time in miliseconds for correct (temperature) measurement with the max6675


// time variables
uint32_t previousTime=0;  // variable to save previous time to ensure that the measurement takes enought time
uint32_t initialTime=0;   // variable to save original time when the measurement began

//measurement calculation
int numberOfTimeSteps=10;
float timeSteps[]={1000, //  1   sec time steps for the different time stamps as the time increase the measurements will be less frequently
                   5000, //  5   sec
                  10000, // 10   sec
                  30000, // 30   sec
                  60000, //  1   min
                 120000, //  2   min
                 150000, //  2.5 min
                 180000, //  3   min
                 300000, //  5   min  
                 600000  // 10  min
                };

float timeStamps[]={3600000, //   1 hr
                    7200000, //   2 hr
                   10800000, //   3 hr
                   21600000, //   6 hr
                   36000000, //  10 hr
                   64800000, //  18 hr
                  118800000, //  33 hr
                  212400000, //  59 hr
                  378000000, // 105 hr
                  676800000  // 188 hr
                };


int currentInt=0;

// float updateIntervalFirstPart=1000 ;                                                  // time interval to return a measurement value in miliseconds
// float updateIntervalSecondPart=10000 ;                                                  // time interval to return a measurement value in miliseconds
// float updateInterval;
uint32_t lastUpdateTime = 0;                                                    // time counter since last returned measurement value

float sumTime=0;                                                                  // sum of time values in time interval of updateInterval
float sumMeasures[numberOfMeasurements];                                          // sum of measurements values in time interval of updateInterval
int counterPoints=0;                                                              // counter of numbers of points measured in a time interval of updateInterval


float storedMeasures[numberOfMeasurements][maxNumberOfPointsStored];                    // saving values for each measurement
float storedTime[maxNumberOfPointsStored];                                              // saving time values of each measurement done (ie., storedMeasures)

bool writeFileOnOff=1;            //if 1 it will write write data if 0 it will not write it anywhere
bool typeOfWrintingSDOrBuffer=0;  //if 1 it will write in SD if 0 it will write in buffer 


int measureIndex=0;                                                        // counter of numbers of stored measurements points

char dataStr[100] = "";
char buffer[7];

void setup() {  
  Serial.begin(9600);
  while (!Serial);
  if (writeFileOnOff & typeOfWrintingSDOrBuffer) {
    Serial.print("Initializing SD card...");
    if (!SD.begin(SD_CS)) {
      Serial.println("failed!");
    } else {
      Serial.println("OK!");  
    }
  } else {
    if (typeOfWrintingSDOrBuffer==0) { 
      Serial.print("printing on buffer...");
      Serial.println("");
    }
  }
  initialTime=millis();
  for (int i = 0; i < numberOfMeasurements; i++) {  // Start loop from the second element
    if (minTimes[i] >= minTime) {
      minTime = minTimes[i];  // Update minValue if current element is smaller
    }
  }
  // updateInterval=updateIntervalFirstPart;
}

void writeFile () {
  if (writeFileOnOff) {
    if (typeOfWrintingSDOrBuffer) {
      Serial.print("writing in SD...");
      myFile=SD.open(fileName+".csv",FILE_WRITE);
        if (myFile) {
          myFile.print(storedTime[measureIndex]);
          myFile.print(";");
          for (int i = 0; i < numberOfMeasurements; i++) {
            myFile.print(storedMeasures[i][measureIndex]);
            myFile.println(";");
          }
          myFile.close();
        } else {
          Serial.print(fileName+".csv");
          Serial.println("error while opening SD file");
        }
    } else {
      // Serial.print("writing in buffer...");
      //convert floats to string and assemble c-type char string for writing:
      ltoa( storedTime[measureIndex],buffer,10); //convert long to charStr
      strcat(dataStr, buffer); //add it to the end
      strcat( dataStr, ", "); //append the delimiter
      for (int i = 0; i < numberOfMeasurements; i++) {
        dtostrf(storedMeasures[i][measureIndex], 5, 1, buffer);  //5 is minimum width, 1 is precision; float value is copied onto buff
        strcat( dataStr, buffer); //append the converted float
        if (i!=numberOfMeasurements-1) {
          strcat( dataStr, ", "); //append the delimiter
        }
      }
      strcat( dataStr, 0); //terminate correctly 
      Serial.println(dataStr); 
    }
  } else {
    Serial.print("writing data flag OFF (change variable writeFileOnOff to 1)");
  }
}

void loop () {
  dataStr[0] = 0; //clean out string
  unsigned long currentMillis = millis();

            if (currentMillis - lastUpdateTime >= timeSteps[currentInt]) {
              //  update last display moment, once per second = once per 1000 millis
              lastUpdateTime += timeSteps[currentInt];

              if (lastUpdateTime>timeStamps[currentInt] & currentInt<numberOfTimeSteps) {
                currentInt+=1;
                Serial.println("increassing the timeStep of measurement");
                while (1) {}
                // updateInterval=updateIntervalSecondPart;
              }
              

              // storing a new average value
              
              for (int i = 0; i < numberOfMeasurements; i++) {
                storedMeasures[i][measureIndex] = sumMeasures[i] / counterPoints;
              }
              storedTime[measureIndex]=sumTime / counterPoints;

              writeFile();

              if (measureIndex >= maxNumberOfPointsStored - 1) {
                  // Reset the values of storedMeasures to the minimum value of the axis and also the sum of measurements
                  for (int i = 0; i < numberOfMeasurements; i++) {
                      for (int j = 0; j < maxNumberOfPointsStored; j++) {
                          storedMeasures[i][j] = 0;
                      }
                  }
                  for (int j = 0; j < maxNumberOfPointsStored; j++) {
                      storedTime[j] = 0;
                  }

                  measureIndex = 0;  // Reset counter
                  // Serial.println("Reseting values measureIndex==0");
                } else {
                    measureIndex++;  // Increment counter
                  // Serial.println("increasing measureIndex");
              }
              
              for (int i = 0; i < numberOfMeasurements; i++) {
                sumMeasures[i] = 0;
              }
              sumTime = 0;
              counterPoints = 0;
              // Serial.println("Reseting values counterPoints==0");
            }
 

  counterPoints += 1;

  //wait enought for the sensor
  if (currentMillis-previousTime<minTime) {
    delay(minTime-(currentMillis-previousTime));
  }

  previousTime=currentMillis;

  sumTime += currentMillis-initialTime;
  for (int i = 0; i < numberOfMeasurements; i++) {
    sumMeasures[i] += thermocouples[i].readCelsius();

  }

}

the idea is that I can choose to write the data to an SD or printed in the serial monitor.
everything 'looks' okey, when I load the sketch to the arduino with printing the data in the monitor. I leaved the waiting time in case that the loop() goes too fast for the MAX that following its datasheet it has a response of 220 ms, (I leaved to a higher value of 500 ms as sometimes I was getting NAH when doing the request on the temperature)
okey up to here everything okey, I put my finger on the thermocouple the temperature increase I remove the finger and the temperature decrease, it looks like it works.

my issue comes when time passes..... after some minutes, the thermocouple temperatures measured they stabilize and at one point they do not change anymore... like I repeat of putting the finger on and off and the value does not change..... also while printing there are small variations of the temperature of , for example 0.1 °C between one and other measure over same thermocouple/max6675 but after a moment the temperature stays the same, like it does not change at all, always the same value (with exception of the time, as I am printing, time/temp1/temp2/temp3, so the buffer variable is being correctly updated.)
I have checked and re checked my sketch without finding any problem with it.
I would appreciate if anyone has an insight over this, if it is a hardware/software problem:

  • the 5V of the arduino does not have enough power for 3 MAX6675?
  • the MAX6675 and thermocouples are some cheap ones from amazon, maybe this could be an issue?
  • my knowledge in C++ is as rudimentary as it can... so maybe is something in my code?
    any insight would be appreciated

Not number 1
Possibly number 2
For number 3 you can easily find out by writing a very simple sketch using just one thermociuple and printing to the serial monitor once a second.

1 Like

try the MAX6675_test.ino sketch, it gives a status which might give a clue.

Your schematic is not helpful to me. Please post an annotated version, making sure to show all connections and power sources. The MAX6675 draws about 200 µA max, for a total of 600 µA, so the Arduino should have no issue powering them. Data Sheet

What other components are connected? Which thermocouples are you using?

Hello @jim-p ,
thanks for the insight,
okey for 1,
the thing that bothers me with 2 is that they 'work' for some time and then this happens. I increased the minTime (by this section of the code in the loop():

  if (currentMillis-previousTime<minTime) {
    delay(minTime-(currentMillis-previousTime));
  }

it looked that when I increased this value (from the data sheet I was using 220 ms) but when I went to 500 now it looks like it works correctly, which is bizarre.
for 3 it is what my code is doing, it prints in the serial monitor the 3 temps, but the thing is that at one point the 3 temps stabilize.

@robtillaart thanks will have a look
@gilshultz
sorry for not being clear.
I have my arduino uno rev3
what is connected to it:
only the 3 max6675.
i have:
the pins of the arduino 5, 6 and 7 connected to the SCK of each MAX
the pins of the arduino 8, 9 and 10 connected to the CS of each MAX
the pins of the arduino 11, 12 and 13 connected to the SO of each MAX
so for example I have the pin 5 to SCK of the max[0] the pin 8 to the CS of the max[0] and the pin 11 to the SO of the max[0].
then I have a jumper connected to the 5V that then goes to a dominos that has 3 outs cables which each of them connected to the 5V of each MAX
same for the GND (as for the 5V)
the thermocouples that I am using are of type K like this one https://www.amazon.fr/dp/B0D9LS5ZT7?ref=ppx_yo2ov_dt_b_fed_asin_title and the MAX are these ones: Barabesty Lot de 5 modules de capteur de température MAX6675 K pour thermocouple : Amazon.fr: Commerce, Industrie et Science

Not really. The data sheet says 220ms maximum so you would want to wait for a time greater than that. Waiting exactly 220ms or even 225ms could result in preventing the IC from doing another conversion, so you will read the same value
The internal timing of the IC may vary with temperature so I would wait at least twice that time, 440ms to make sure you get a new measurement.

I understand, what I dont get is why, it looks like it 'saturates' the breakboard, I mean yeah having two times the same measurement okey.... but after the point in time I mentionned in the first post, the temperature reminds constant without changing at all not only 'between' two measures but all the measures after that one (for hours for example)

As I said if you wait exactly 220ms and the internal timing drifted to 222ms say after 30 minutes, then every reading after that will be the same since you did not give it enough time to start a new conversion.

1 Like

but lets say it goes to 300ms.
you do a reading, then a second reading in less than 300ms lets say 220ms (so you get the same value) then you do another reading so now it has passed 440ms, but still it gives the same value and next 660...etc.. I dont get why it will stay stock in the same value

The time is not cumulative. The 220ms timer resets and starts over again every time you take a reading.

1 Like

thank you for all the clarification, one last questions regarding this issue, (right now I put 440 and it looks like it is working correctly!):

  1. is there any more 'clean way' to do this waiting of different sensors than what I did?
    I mean this:
if (currentMillis-previousTime<minTime) {
    delay(minTime-(currentMillis-previousTime));
  }
  1. how can one 'know' this value to set? as the data sheet says 220ms.

Actually it states 0.22 seconds not 220ms. So, 0.22 could mean 0.221 ... 0.225ms
If it is indeed a genuine Analog Devices IC then if you wait 226ms it should work every time.
Considering it is a very old IC from Maxim then the one you have could be a clone and who knows what the timing could be.

There may be but optimizing someone else's code is not one of my strong points.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.