Writing Data to SDCard with Multplex Shield

Hello, I'm working on a project utilizing 6, T-type thermocouples for ground temperature measurements over time. My interface is the Ocean Controls Thermocouple Multiplexer Shield (KTA-259T) mounted atop an arduino Metro from Adafruit.
The issue is I need to write the thermocouple temperatures to an Adafruit SD Card Shield. I've reviewed some of the sample codes for SD cards and am currently able to get the card to initialize in my sketch and thats the extent. From what I've read, the code needs to turn off the multiplexer CS pin to write to the SC Card, but I'm not sure what/how to integrate the SD Card write code into my sketch. Once I can get this working I'd also like to encorporate the DateTime stamps as well. The code I'm using is a sample code from the Ocean Controls website.
Thank you for any help you may provide.

// Assumes 20 MHz or less clock. Insert NOPs for faster operation.
// Pinout for Ocean Design's Thermocouple Multiplexer Shield

#include "SD.h"  //talks to SD Card
#include <Wire.h>  //helps Arduino with i2c
#include "RTClib.h"  //talks with real time clock
#include <SPI.h>  // include the SD library:

#define PINEN 7 // TC Mux Enable pin
#define PINA0 4 // TC Mux Address 0 pin
#define PINA1 5 // TC Mux Address 1 pin
#define PINA2 6 // TC Mux Address 2 pin
#define PINSO 12 //TC ADC Slave Out pin (MISO)
#define PINSC 13 //TC ADC Serial Clock (SCK)
#define PINCS 9  //TC ADC Chip Select

#define SHORT -1001
#define OPEN -1000

const int chipSelect = 10;

volatile int tcTemp[9];    // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

int readSPI() {
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
  return v;
}

void tcTempSetup() {
  pinMode(PINEN, OUTPUT);
  pinMode(PINA0, OUTPUT);
  pinMode(PINA1, OUTPUT);
  pinMode(PINA2, OUTPUT);
  pinMode(PINSO, INPUT);
  pinMode(PINCS, OUTPUT);
  pinMode(PINSC, OUTPUT);

  digitalWrite(PINEN, HIGH);   // enable the mux all the time
  digitalWrite(PINSC, LOW);    // put clock in low
  digitalWrite(PINCS, LOW);    // stop conversion, start serial interface

  // Timer0's overflow is used for millis() - setup to interrupt
  // in the middle and call the "Compare A" function below
  OCR0A = 0x80;
  TIMSK0 |= _BV(OCIE0A);
}

void setup() {
  Serial.begin(9600);
  tcTempSetup();{
  }
   Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}

// Interrupt is called every millisecond
SIGNAL(TIMER0_COMPA_vect) {
  static byte ms = 0;
  static byte ch = 0;

  if (ms == 0) {
    // select the thermocouple channel on the mux
    digitalWrite(PINA0, ch & 1);
    digitalWrite(PINA1, ch & 2);
    digitalWrite(PINA2, ch & 4);
    // ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
  } else if (ms == 5) {
    // begin conversion
    digitalWrite(PINCS, HIGH);
    // ... wait 100 mS for conversion to complete
  } else if (ms == 105) {
    // stop conversion, start serial interface
    digitalWrite(PINCS, LOW);
    // 100nS min. delay implied

    int rawTC = readSPI();
    int rawIT = readSPI();

    int tempC = rawTC / 4;
    if (rawTC & 1) {
      if (rawIT & 1) {
        tempC = OPEN;
      }
      if (rawIT & 6) {
        tempC = SHORT;
      }
    }
    tcTemp[ch] = tempC;

    if (++ch == 8) {
      tcTemp[8] = rawIT / 64; // internal temperature reduced to quarter degree C
      ch = 0;
    }
    ms = 255; // ++ will make this 0
  }
  ms++;
}

void loop() {
  for (byte j = 0; j < 9; j++) {
    //Serial.print((word)j);
    //Serial.print('=');

    // access thermocouple readings with interrupts disabled to prevent 'shearing'
    noInterrupts();
    int t = tcTemp[j];
    interrupts();

    if (t == OPEN) {
      Serial.print(" , ");  //Change , to Open to troubleshoot thermocouple
    }  else if (t == SHORT) {
      Serial.print(" , ");  //Change , to Short troubleshoot thermocouple
    } else {
      Serial.print(t / 4);
  }
    Serial.print(' ');
  }
  Serial.println("");
  delay(1000);  //  delay(1000) milleseconds, set this for print time;
}

Hi aatig,
You are welcome on this forum! You are working on an informatic project and what is most needed in an informatic project is information imagine: do the other users here in the forum have a clear picture of what you are trying to do?

You are forcing potential helpers to do additional work that could be done by you.
Provide links to the datasheets of

  • the thermocouple-shield
  • the sD-card-reader
  • and your microcontroller-board.

To speed up finishing your project you should invest some time into writing additional information I'm 100% sure that this WILL speed up finishing your project.

So please go through this checklist and if you find an item you haven't posted yet post it

  • did you write which exact type of microcontroller you are using?
  • description of your programming skills and knowledge
  • description of your knowledge about electronics
  • description of the functionality you want to have written in normal works avoiding programming terms
  • do you have an oscilloscope? Yes / No
  • do you have a digital multimeter (DMM) Yes / No)
  • your age
  • did you post your complete sketch?
  • if relevant did you post a link to a datasheet of each component you are using?
  • if relevant did you post a handdrawn schematic or your wiring?
  • if you got a compiler-error. Did you post the complete compiler-output into a code-section?

If you don't post all this information because you want a "quick answer" to your detail problem It is very likely to turn out that all that happens is having mutliple waiting-times with mutliple asking back for details until the other users do have a clear picture of what you want to do.

best regards Stefan

Below are some additional details of my project and my level of experience:

Adafruit Metro 328 Microcontroller - Metro Pinout, Metro Details
Adafruit SD Card Data Logging Shield Rev.B - SD Card Shield Details, Overview
Ocean Controls Thermocouple Multiplexer Shield KTA-259T - Details

I have very basic understanding of programming. I've done some apple basic, visual basic and C+ in the past, but this was decades ago. My knowledge of electronics is fairly good and is my main hobby. I do have an Oscope, meters, generators etc. to aid in troubleshooting components.

Functionally, i'm looking for this device to record temperature measurements along with timestamps of 6, T - type thermocouples on an SD-Card over the period of a few years. My choice of an SD card is to periodically extract the data into a remote PC and use excel for plotting temperature over time. Note, the data logger and multiplexers are both shields stacked on the arduino metro, so no additional wiring other than the connection of a thermocouple to the multiplexer, see photograph below.

Below is the current serial monitor output and assembly:
Note - 1 thermocouple attached for testing....the permanent installation is in a different part of the US. Also, the serial monitor output was displaying the thermocouple and internal arduino temperatures but now displays "0"s since i've added the SD card code in the void setup().

Please let me know if you need any additional information, thank you.

I had to llok up some more infos
in the FAQ

they write

One of D8, D9 or D10 (by default, D9) is used as the chip select line for the MAX31855's SPI
interface

So this should not interfere with the chip-select on IO-pin 10 from the SD-Cardshield
Anyway Adafruit writes in the overview

Near Digital #10

  • CS - this is the Chip Select pin for the SD card. If you need to cut the trace to pin 10 because it is conflicting, this pad can be soldered to any digital pin and the software re-uploaded

without your full code I can't analyse anything.

Some general rules about posting in the forum.
everytime you modified your code post your complete code new as a code-section. Code-Sections only need a limited space on screen so its really OK to post new code-versions very often.

There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

Post serial output as a code-section too. In this case use the </>-Button of the forum.

It is much easier to click on the upper-right-corner of a code-section to copy all content of a code-section than reading pictures etc.

best regards Stefan

what is the temperature range of the temperatures you are measuring?
What are the environmental conditions of the sensor-heads?

  • underwater?
  • inside earth?
  • ouside = rain?
  • simply dry inside a building?

depending on the conditions using onewire-temperature sensors might be an alternative.

I've posted the code again, below. This has not been amended in my current sketch and is as initially posted.
Yes, I'm using pin 9 as the CS for the Ocean muliplexer which matches the board pinout and pin 10 for the Adafruit data logger. The SD card initializes, so i'm thinking there is no conflict with the CS Pins. Is this a correct statement?

[code]
// Assumes 20 MHz or less clock. Insert NOPs for faster operation.
// Pinout for Ocean Design's Thermocouple Multiplexer Shield

#include "SD.h"  //talks to SD Card
#include <Wire.h>  //helps Arduino with i2c
#include "RTClib.h"  //talks with real time clock
#include <SPI.h>  // include the SD library:

#define PINEN 7 // TC Mux Enable pin
#define PINA0 4 // TC Mux Address 0 pin
#define PINA1 5 // TC Mux Address 1 pin
#define PINA2 6 // TC Mux Address 2 pin
#define PINSO 12 //TC ADC Slave Out pin (MISO)
#define PINSC 13 //TC ADC Serial Clock (SCK)
#define PINCS 9  //TC ADC Chip Select

#define SHORT -1001
#define OPEN -1000

const int chipSelect = 10;

volatile int tcTemp[9];    // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

int readSPI() {
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
  return v;
}

void tcTempSetup() {
  pinMode(PINEN, OUTPUT);
  pinMode(PINA0, OUTPUT);
  pinMode(PINA1, OUTPUT);
  pinMode(PINA2, OUTPUT);
  pinMode(PINSO, INPUT);
  pinMode(PINCS, OUTPUT);
  pinMode(PINSC, OUTPUT);

  digitalWrite(PINEN, HIGH);   // enable the mux all the time
  digitalWrite(PINSC, LOW);    // put clock in low
  digitalWrite(PINCS, LOW);    // stop conversion, start serial interface

  // Timer0's overflow is used for millis() - setup to interrupt
  // in the middle and call the "Compare A" function below
  OCR0A = 0x80;
  TIMSK0 |= _BV(OCIE0A);
}

void setup() {
  Serial.begin(9600);
  tcTempSetup();{
  }
   Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}

// Interrupt is called every millisecond
SIGNAL(TIMER0_COMPA_vect) {
  static byte ms = 0;
  static byte ch = 0;

  if (ms == 0) {
    // select the thermocouple channel on the mux
    digitalWrite(PINA0, ch & 1);
    digitalWrite(PINA1, ch & 2);
    digitalWrite(PINA2, ch & 4);
    // ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
  } else if (ms == 5) {
    // begin conversion
    digitalWrite(PINCS, HIGH);
    // ... wait 100 mS for conversion to complete
  } else if (ms == 105) {
    // stop conversion, start serial interface
    digitalWrite(PINCS, LOW);
    // 100nS min. delay implied

    int rawTC = readSPI();
    int rawIT = readSPI();

    int tempC = rawTC / 4;
    if (rawTC & 1) {
      if (rawIT & 1) {
        tempC = OPEN;
      }
      if (rawIT & 6) {
        tempC = SHORT;
      }
    }
    tcTemp[ch] = tempC;

    if (++ch == 8) {
      tcTemp[8] = rawIT / 64; // internal temperature reduced to quarter degree C
      ch = 0;
    }
    ms = 255; // ++ will make this 0
  }
  ms++;
}

void loop() {
  for (byte j = 0; j < 9; j++) {
    //Serial.print((word)j);
    //Serial.print('=');

    // access thermocouple readings with interrupts disabled to prevent 'shearing'
    noInterrupts();
    int t = tcTemp[j];
    interrupts();

    if (t == OPEN) {
      Serial.print(" , ");  //Change , to Open to troubleshoot thermocouple
    }  else if (t == SHORT) {
      Serial.print(" , ");  //Change , to Short troubleshoot thermocouple
    } else {
      Serial.print(t / 4);
  }
    Serial.print(' ');
  }
  Serial.println("");
  delay(1000);  //  delay(1000) milleseconds, set this for print time;
}
[/code]

No options here, the 6, T Type Thermocouples are measuring ground temperatures beneath a home foundation located in MN and were installed beneath the slab prior to pouring the concrete, so permanent installation. The processor used on the Ocean Mulitplexor is the Max 31855T cold junction compensated thermocouple to digital converter which requires a grounded thermocouple, which are what i have installed on this project.
To be clear, i really dont think there is any hardware issue here. If you look at the code i've pasted, it should be evident that i've not added the correct code for the data logger to send data to the sd card. I've reviewed some of the sample sketches on datalogging, which make some sense, but really not sure how to implement into my code properly.

So this means if you comment out the SD-Card-code

// Assumes 20 MHz or less clock. Insert NOPs for faster operation.
// Pinout for Ocean Design's Thermocouple Multiplexer Shield

#include "SD.h"  //talks to SD Card
#include <Wire.h>  //helps Arduino with i2c
#include "RTClib.h"  //talks with real time clock
#include <SPI.h>  // include the SD library:

#define PINEN 7 // TC Mux Enable pin
#define PINA0 4 // TC Mux Address 0 pin
#define PINA1 5 // TC Mux Address 1 pin
#define PINA2 6 // TC Mux Address 2 pin
#define PINSO 12 //TC ADC Slave Out pin (MISO)
#define PINSC 13 //TC ADC Serial Clock (SCK)
#define PINCS 9  //TC ADC Chip Select

#define SHORT -1001
#define OPEN -1000

const int chipSelect = 10;

volatile int tcTemp[9];    // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

int readSPI() {
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
  return v;
}

void tcTempSetup() {
  pinMode(PINEN, OUTPUT);
  pinMode(PINA0, OUTPUT);
  pinMode(PINA1, OUTPUT);
  pinMode(PINA2, OUTPUT);
  pinMode(PINSO, INPUT);
  pinMode(PINCS, OUTPUT);
  pinMode(PINSC, OUTPUT);

  digitalWrite(PINEN, HIGH);   // enable the mux all the time
  digitalWrite(PINSC, LOW);    // put clock in low
  digitalWrite(PINCS, LOW);    // stop conversion, start serial interface

  // Timer0's overflow is used for millis() - setup to interrupt
  // in the middle and call the "Compare A" function below
  OCR0A = 0x80;
  TIMSK0 |= _BV(OCIE0A);
}

void setup() {
  Serial.begin(9600);
  tcTempSetup();{
  }
/*
   Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}
*/


// Interrupt is called every millisecond
SIGNAL(TIMER0_COMPA_vect) {
  static byte ms = 0;
  static byte ch = 0;

  if (ms == 0) {
    // select the thermocouple channel on the mux
    digitalWrite(PINA0, ch & 1);
    digitalWrite(PINA1, ch & 2);
    digitalWrite(PINA2, ch & 4);
    // ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
  } else if (ms == 5) {
    // begin conversion
    digitalWrite(PINCS, HIGH);
    // ... wait 100 mS for conversion to complete
  } else if (ms == 105) {
    // stop conversion, start serial interface
    digitalWrite(PINCS, LOW);
    // 100nS min. delay implied

    int rawTC = readSPI();
    int rawIT = readSPI();

    int tempC = rawTC / 4;
    if (rawTC & 1) {
      if (rawIT & 1) {
        tempC = OPEN;
      }
      if (rawIT & 6) {
        tempC = SHORT;
      }
    }
    tcTemp[ch] = tempC;

    if (++ch == 8) {
      tcTemp[8] = rawIT / 64; // internal temperature reduced to quarter degree C
      ch = 0;
    }
    ms = 255; // ++ will make this 0
  }
  ms++;
}

void loop() {
  for (byte j = 0; j < 9; j++) {
    //Serial.print((word)j);
    //Serial.print('=');

    // access thermocouple readings with interrupts disabled to prevent 'shearing'
    noInterrupts();
    int t = tcTemp[j];
    interrupts();

    if (t == OPEN) {
      Serial.print(" , ");  //Change , to Open to troubleshoot thermocouple
    }  else if (t == SHORT) {
      Serial.print(" , ");  //Change , to Short troubleshoot thermocouple
    } else {
      Serial.print(t / 4);
  }
    Serial.print(' ');
  }
  Serial.println("");
  delay(1000);  //  delay(1000) milleseconds, set this for print time;
}

the code prints valid temperature-values?

The demo-code provided by ocean controls uses an interrupt to read the temperature-values. I don't know much about the details of the SPI-bus this might be a problem.

There is a library on GitHub that does the reading without interrupt

Do you know how to install ZIP-libraries in the Arduino-IDE?
best regards Stefan

Well it was working perfectly displaying and graphing my temperatures.... now it seems to display all 0's. Will have to go back to the original sketch from ocean and compare.
I dont know too much about interrupts,will take a look at the GitHub library as well.

OK, back to working again, had a few pins not socketed. Confirmed, commented out the SD Card code and temps are being displayed(internal and channel 1 where the thermocouple is attached), on serial monitor as expected and as if the sd card didnt exist.

In the New Code below...I've uncommented the SD card code and added the SD card file write code in the void loop(). The temp data displayed on the Serial Monitor is now all 0's, however the 0's are being recorded on the SD Card in my text file, which is one step closer. So, need to figure out why the temp data from the internal and channel 1 connected sensors are not being transmitted to the serial plotter.

[code]
// Assumes 20 MHz or less clock. Insert NOPs for faster operation.
// Pinout for Ocean Design's Thermocouple Multiplexer Shield

#include "SD.h"  //talks to SD Card
#include <Wire.h>  //helps Arduino with i2c
#include "RTClib.h"  //talks with real time clock
#include <SPI.h>  // include the SD library:

#define PINEN 7 // TC Mux Enable pin
#define PINA0 4 // TC Mux Address 0 pin
#define PINA1 5 // TC Mux Address 1 pin
#define PINA2 6 // TC Mux Address 2 pin
#define PINSO 12 //TC ADC Slave Out pin (MISO)
#define PINSC 13 //TC ADC Serial Clock (SCK)
#define PINCS 9  //TC ADC Chip Select

#define SHORT -1001
#define OPEN -1000

const int chipSelect = 10;

volatile int tcTemp[9];    // in quarter deg. C, tcTemp[8] is the interal reference temp, disable IRQ's to access these

int readSPI() {
  word v = 0;
  for (byte i = 16; i != 0; i--) {
    v <<= 1;
    digitalWrite(PINSC, HIGH);
    // 100nS min. delay implied
    v |= digitalRead(PINSO);
    digitalWrite(PINSC, LOW);   // request next serial bit
    // 100nS min. delay implied
  }
  return v;
}

void tcTempSetup() {
  pinMode(PINEN, OUTPUT);
  pinMode(PINA0, OUTPUT);
  pinMode(PINA1, OUTPUT);
  pinMode(PINA2, OUTPUT);
  pinMode(PINSO, INPUT);
  pinMode(PINCS, OUTPUT);
  pinMode(PINSC, OUTPUT);

  digitalWrite(PINEN, HIGH);   // enable the mux all the time
  digitalWrite(PINSC, LOW);    // put clock in low
  digitalWrite(PINCS, LOW);    // stop conversion, start serial interface

  // Timer0's overflow is used for millis() - setup to interrupt
  // in the middle and call the "Compare A" function below
  OCR0A = 0x80;
  TIMSK0 |= _BV(OCIE0A);
}

void setup() {
  Serial.begin(9600);
  tcTempSetup(); {
  }
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}

// Interrupt is called every millisecond
SIGNAL(TIMER0_COMPA_vect) {
  static byte ms = 0;
  static byte ch = 0;

  if (ms == 0) {
    // select the thermocouple channel on the mux
    digitalWrite(PINA0, ch & 1);
    digitalWrite(PINA1, ch & 2);
    digitalWrite(PINA2, ch & 4);
    // ... wait a while for the capacitor on the ADC input to charge (< .1 mS actually needed)
  } else if (ms == 5) {
    // begin conversion
    digitalWrite(PINCS, HIGH);
    // ... wait 100 mS for conversion to complete
  } else if (ms == 105) {
    // stop conversion, start serial interface
    digitalWrite(PINCS, LOW);
    // 100nS min. delay implied

    int rawTC = readSPI();
    int rawIT = readSPI();

    int tempC = rawTC / 4;
    if (rawTC & 1) {
      if (rawIT & 1) {
        tempC = OPEN;
      }
      if (rawIT & 6) {
        tempC = SHORT;
      }
    }
    tcTemp[ch] = tempC;

    if (++ch == 8) {
      tcTemp[8] = rawIT / 64; // internal temperature reduced to quarter degree C
      ch = 0;
    }
    ms = 255; // ++ will make this 0
  }
  ms++;
}

void loop() {
  for (byte j = 0; j < 9; j++) {
    //Serial.print((word)j);
    //Serial.print('=');

    // access thermocouple readings with interrupts disabled to prevent 'shearing'
    noInterrupts();
    int t = tcTemp[j];
    interrupts();

    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (t == OPEN) {
      Serial.print(" , ");  //Change , to Open to troubleshoot thermocouple
    }  else if (t == SHORT) {
      Serial.print(" , ");  //Change , to Short troubleshoot thermocouple
    } else {
      // if the file is available, write to it:
      if (dataFile) {
        dataFile.println(t / 4);
        dataFile.close();
        // print to the serial port too:
        Serial.print(t / 4);
      }
      //if the file isn't open, pop up an error:
      else {
        Serial.println("error opening datalog.txt");
      }

    }
    Serial.print(' ');
  }
  Serial.println("");
  delay(1000);  //  delay(1000) milleseconds, set this for print time;
}
[/code]

The chip-select pin does what the name says. So you could add a check to the temperature-reading-code. This check does a digitalRead(SD_ChipSelect_pin) to check if the SD-functions did really disable the SD-card.

Another way to analyse would be to use the oscillosope to see what is the difference on the IO-pins with SD-card-code activated or commented out.

best regards Stefan

Thanks StefanL38.....thats would be a good check. I'll take a look at it later this evening. I did find a blog related to this on adafruit that talks about manipulating the mux on/off and coordinate the sensor reading with writing to the SD Card. This blog kind of made sense, but again not sure how to implement/test in my code at the moment...
https://forums.adafruit.com/viewtopic.php?f=31&t=39699

The code provided by Ocean-control controls this small puddle of water called Thermocouple-shield but invoces a hurrican on the SPI-bus blowing the ocean against the coast. ;-))

I think you don't need to read in temperatures every millisecond.
I guess it will be enough to read in the temperatures ten times per second by polling instead of using an interrupt.

So my guess is that this other library on github works the polling way:
If you the user want to retrieve a temperature-measuring your code does it once

Retrieving a temperature-value means set CS-pin9 HIGH to start measuring
Next step set CS-pin9 LOW to enable datatransfer from Thermocouple-multiplexer.
Thermocouple-multiplexer in short the TC-MUX

As long as the CS-pin9 is low the TC-MUX's SPI-bus is active
after retrieving the temperature-measurement
the CS-pin9 has to be set HIGH to deactivate the TC-MUX's SPI-bus

Only if the TC-MUX SPI-bus is disabled communication with the SD-card will work

The reason why the TC-MUX-SPI-bus is disturbed is that the TC-shield uses an interrupt that initiates SPI-communication each milliseconds regardless of what the SD-Card is doing.
There is no cross-checking between the two devices "can I use the SPI-bus now?"
The TC-MUX software switches CS-pin9 LOW/HIGH whenever the TC-MUX-code wants to.
best regards Stefan

Another idea is to put a gate between the Arduino IO-pin 9 and TC-MUXers chip-select-input
and then whenever you want to start a SD-card-command switching the TC-MUXers CS-input electrically HIGH to force disabling the TC-MUXer SPI.

But I think there must be a solution possible in pure software.

best regards Stefan

I believe your opening statement is uncanningly accurate.... the github code is looks the simpler solution by far.
Thank your the details on CS, that makes sense. I'll see what i can do with this github code and report out.....

OK, after a few hours I was able to get the github code to output in the format i need, but...
The Internal Temperature serial.print seems correct value, however the blocks of code labeled "Thermocouple Temperature" in degrees F is outputting 3304F, not sure what this is indicating. I have no thermocouples attached, just the arduino, multiplexer and sd card shields.
I've commented out alot of the output I do not need, note the original code output the same temperature readings so no change due to this.
Any thoughts on the high temp reading? Also how would i add all 8 thermocouple channels?

New Code (github library)

[code]
/***************************************************************************
  Examle for MAX31855_lib library for MAX31855* thermocouple amplifier
  Written by Cory J. Fowler
  BSD license, all text above must be included in any redistribution.
 ***************************************************************************/

#include <SPI.h>
#include <MAX31855.h>

const byte scale = 0;   // 0 is Celsius/Centigrade, ~80µs. 1 is Kelvin, ~108µs. 2 is Fahrenheit ~100µs. 3 is Rankine, ~100µs.
byte error;
double external;
double internal;
unsigned long previousMicros = 0;
MAX31855 TC1(9);
//byte cls[] = {0x1B,0x5B,0x32,0x4A,0x1B,0x5B,0x3B,0x48,0x0A,0x0D};            // Terminal control commands to erase screen and return home: <Esc>[2J<Esc>[;H

void setup() {
  Serial.begin(9600);
  TC1.begin();
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
}

void loop() {
  for (byte i = 0; i < 8; i++) {                                             // Print terminal control codes to clear screen and position cursor at home.
    //Serial.write(cls[i]);
  }

  previousMicros = micros();
  TC1.getTemp(external, internal, scale, error);
  //Serial.print(micros() - previousMicros);
  //Serial.write(0xB5);                                                        // Print µ 'mu'           // Arduino IDE's UTF-8 encoding adds extra character infront of printed mu.
  //Serial.println("s taken to read MAX31855*");
  //Serial.print(" , ");

  //Serial.print("Cold Junction Temperature:");
  //Serial.print(internal);
  //Serial.write(0xB0);                                                        // Print ° 'degree'
  //Serial.print("C");
  //Serial.print(" , ");

  Serial.print(TC1.intTemp(2));                                                //Internal Arduino Temp Sensor, prints around 81F and increases when touched - seems to work okay
  //Serial.write(0xB0);
  Serial.print("F");
  Serial.print(" , ");

  //Serial.println("Thermocouple Temperature:");                               // Supposedly a Thermocouple channel, reads around 1818C and does not change - not sure what this is
  //Serial.print(external);
  //Serial.write(0xB0);
  //Serial.print("C");
  //Serial.print(" , ");

  Serial.print(TC1.extTemp(2));                                               // Supposedly a Thermocouple channel, reads around 3304F  - not sure what this is
  //Serial.write(0xB0);
  Serial.print("F");
  Serial.print(" , ");

  //Need all 8 channels to output to the serial plotter. How to change channels?

  Serial.print("");                                        //(error, BIN);
  if (error & 0x01) {
    Serial.print("TC Open");
    Serial.println();
  } else if (error & 0x02) {
    Serial.print("TC Ground");
    Serial.println();
  } else if (error & 0x04) {
    Serial.print("TC Shorted to Power");
    Serial.println();
  } else {
    Serial.println();
  }
  delay(1000);
}
[/code]

Serial Monitor Output - > Int Temp Sens, Thermocouple Channel?, Thermocouple Channel?

Just had a thought....perhaps the high temp reading is indicative of the error that prints TC Open. In other words an open thermocouple channel would have a high number and the TC Open is a label of the error.

conflicts might occure if the writes on the SD card takes longer than you are aware of.

According to the KTA-259V4 datashied, that shield ties pin 10 (9 and 8???) to CS.
On the other hand the layout of the SD Shield implies that they use pin 10 for CS.

Imho it is essential that you don't connect pin 10 on the KTA-259V4. As you have placed it on top of your stack, you could try to bend the pin 10 outwards, so it can't connect into the socket of the sd shield.

Hi aattig,

For posting code there is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

no additional writing of [ code ] [ / code ] nescessary. Just press Ctrl-V for pasting - done

For posting content of the serial monitor you can use code-sections too.
click into serial monitor
press Ctrl-A for mark all
press Ctr-C for copy to clipboard
change to user-forum
click on the </>-Button
press Ctrl-V for pasting clipboard-content - done

In the GiPo there is a second example called MuxTest.ino

if you click on the raw-Button in the upper-right corner the code is displayed as plain text

In the GiPo the short description below the folders says

There is a function that will set the address and enable bits of the ADG608 multiplexer found on Ocean Controls' MAX31855 shield.
First, the MUX define parameter in MAX31855.h will need to be set to 1 to enable MUX support.
0 corresponds to channel 1, and so on.

setMUX(ChannelNumber-1);

This means the author has designed using multiplexing as an compiler-option.

search for the file MAX31855.h on your harddisc
inside this file there are two lines

// Set to 1 if input is multiplexed (Ocean Controls Shield)
#define MUX   0

change the line to

#define MUX   1

The MuxTest.ino shows how to use the command to set the MUX-channel

TCM.setMUX(channel);   

some additional hints:
if you want to out-comment multiple lines in sequence you can use the block-comment
/* */

void loop() {
  for (byte i = 0; i < 8; i++) {                                             // Print terminal control codes to clear screen and position cursor at home.
    //Serial.write(cls[i]);
  }

  previousMicros = micros();
  TC1.getTemp(external, internal, scale, error);
/*
  Serial.print(micros() - previousMicros);
  Serial.write(0xB5);                                                        // Print µ 'mu'           // Arduino IDE's UTF-8 encoding adds extra character infront of printed mu.
  Serial.println("s taken to read MAX31855*");
  Serial.print(" , ");

  Serial.print("Cold Junction Temperature:");
  Serial.print(internal);
  Serial.write(0xB0);                                                        // Print ° 'degree'
  Serial.print("C");
  Serial.print(" , ");
*/
  Serial.print(TC1.intTemp(2));                                                //Internal Arduino Temp Sensor, prints around 81F and increases when touched - seems to work okay

For easier handling of content that shall be written to the SD-Card I recommend using the SafeString-library

The basic principle of the use is

#include <SafeString.h>

creating a SafeString-variable named "myDataToLog_SS" which can hold strings of a maximal length of 128 bytes

createSafeString(myDataToLog_SS,128);

I'm using the sufffix "_SS" to indicate in the variable name it is of variable type SafeString

Adding content is as easy as this


createSafeString(myDataToLog_SS,128);
createSafeString(TimeStamp_SS,32);  //2021.08.24 ; 07:06:05 ;


// assuming you have integer-variables named year, month, day, hour, minute, sec
TimeStamp_SS = year;
TimeStamp_SS += ".";

if (month < 10) {
TimeStamp_SS += "0"; // leading zero  
}
TimeStamp_SS += month;
TimeStamp_SS += ".";

if (day < 10) {
TimeStamp_SS += "0"; // leading zero  
}
TimeStamp_SS += day;
TimeStamp_SS += ".";

if (day < 10) {
TimeStamp_SS += " ; "; // space semicolon space for creating a CSV-file
}

if (hour < 10) {
TimeStamp_SS += "0"; // leading zero  
}
TimeStamp_SS += hour;
TimeStamp_SS += ":";

if (minute < 10) {
TimeStamp_SS += "0"; // leading zero  
}
TimeStamp_SS += minute;
TimeStamp_SS += ":";


if (second < 10) {
TimeStamp_SS += "0"; // leading zero  
}
TimeStamp_SS += second;

TimeStamp_SS += " ; "; // space semicolon space for creating a CSV-file



myDataToLog_SS = TimeStamp_SS;

myDataToLog_SS += Temp[0];
myDataToLog_SS += " ; "    // space semicolon space for creating a CSV-file

myDataToLog_SS += Temp[1];
myDataToLog_SS += " ; "    // space semicolon space for creating a CSV-file

myDataToLog_SS += Temp[2];
myDataToLog_SS += " ; "    // space semicolon space for creating a CSV-file
//...

// further down the code write to SD-card all the data with a single line of code
// because the SafeString-variable named myDataToLog_SS holds all the data
  dataFile.println(myDataToLog_SS);

best regards Stefan

1 Like

To clarify the KTA259 schematic....there is only one resistor which is soldered to the D9 pin circuit so D10 and D8 pins are open. Bad attempt to show this resistor can be moved to any of the 3 pins.