Two shields share the same MISO and SCK, issues

One shield is a thermocouple shield and uses MISO for Pin 12 and SCK for Pin 13. It uses the SPI library to initialize.

void SPIClass::begin() {

  // Set SS to high so a connected chip will be "deselected" by default
  digitalWrite(SS, HIGH);

  // When the SS pin is set as OUTPUT, it can be used as
  // a general purpose output port (it doesn't influence
  // SPI operations).
  pinMode(SS, OUTPUT);

  // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  // automatically switches to Slave, so the data direction of
  // the SS pin MUST be kept as OUTPUT.
  SPCR |= _BV(MSTR);
  SPCR |= _BV(SPE);

  // Set direction register for SCK and MOSI pin.
  // MISO pin automatically overrides to INPUT.
  // By doing this AFTER enabling SPI, we avoid accidentally
  // clocking in a single bit since the lines go directly
  // from "input" to SPI control.  
  // http://code.google.com/p/arduino/issues/detail?id=888
  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
}

The other shield is the Arduino SD/Ethernet shield and uses the included SD.h library.

The thermocouple will run perfectly fine in its loop until I decided to use the SD card.

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  myFile = SD.open("test.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 8, 2, 3.");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

Is there some way to restart everything? Maybe the clock itself? I’m not understanding what’s going on, I guess. I’ve tried changing different pins to high and low after certain steps but nothing seems to work.

but nothing seems to work.

Certainly not the snippets of code you posted.

I’m sorry, I’ll try to be more descriptive. Having difficulty wrapping my head around slave select and chip select, and how to condense my questions.

The first shield is a MAX31855 Thermocouple Shield.

http://playingwithfusion.com/productview.php?pdid=38&catid=1001

It uses pins 12 (MISO) and 13 (SLK). It uses Pins 3-6 for temperature input. I am only using Pin 3 right now.

The second shield is a Gheo Electronics Arduino Ethernet Shield Rev. 3 without PoE Module

It uses pins 4 (SD chip select), 10 (SS), 11 (MOSI), 12 (MISO) , and 13 (SLK).

Both shields work fine when plugged in without the other.

Here is the code I’m running:

// the sensor communicates using SPI, so include the hardware SPI library:
#include "SPI.h"
// include Playing With Fusion MAX31855 libraries
#include "PlayingWithFusion_MAX31855_1CH.h"
#include "PlayingWithFusion_MAX31855_STRUCT.h"

#include <SD.h>

File myFile;

int8_t CS0_PIN = 6;

PWFusion_MAX31855_TC  thermocouple0(CS0_PIN);


void setup()
{

 Serial.begin(9600);

  SPI.begin();                        // begin SPI
  SPI.setDataMode(SPI_MODE1);         // MAX31855 is a Mode 1 device
                                      //    --> clock starts low, read on rising edge

  pinMode(CS0_PIN, OUTPUT);
  pinMode(10, OUTPUT);
 

void loop()
{
  delay(2500);                       

  static struct var_max31855 TC_CH0;           
  double tmp;

  // update TC0
  struct var_max31855 *tc_ptr;
  tc_ptr = &TC_CH0;
  thermocouple0.MAX31855_update(tc_ptr);        // Update MAX31855 readings 

  // TC0
  Serial.println("Thermocouple 0:");            // Print TC0 header
  tmp = (double)TC_CH0.value * 0.25;           // convert fixed pt # to double
  Serial.print("TC Temp = ");                   // print TC temp heading
  Serial.println(tmp);


  //begin writing to SD Card

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing");
	// close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  

}

The first pass will get the temperature correctly and initialize/write to the SD card. The next pass will show a bad temperature and the card will not initialize. As soon as I initialize the SD card, the thermocouple shield doesn’t work properly from then on.

This code is likely a mess currently. I have moved the SPI.begin() in to the loop. I had moved the SD.begin(4) out of the loop. I have changed PIN 4 and PIN 10 to be HIGH and LOW at different parts. I have tried using SPI.end(). The problem is I’m not sure what I’m doing when it comes to using one shield and not using the other. All I want to do is:

  1. Connect to thermocouple shield.
  2. Pass data.
  3. Disconnect from thermocouple shield.
  4. Connect to SD/Ethernet shield.
  5. Pass data.
  6. Disconnect from SD shield.
  7. Loop

Disable all SPI slave selects before trying to initialize any of them. What pin is the thermocouple SPI slave select using?

edit: If using D6 as the slave select, here are the first lines of your setup function.

void setup() {
  // disable SD 
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  // disable thermocouple 
  pinMode(6,OUTPUT);
  digitalWrite(6,HIGH);

  // disable w5100
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  // rest of your setup

I think it has to do with the SPI mode. SD uses mode 0 while your MAX thermocouple shield uses mode 1.

Try setting SPI to mode 0 before each call to SD and to mode 1 before each MAX call. It's kind of a pain; it would better if the libraries took care of this themselves. If I were you I'd edit them rather than clutter my sketch with repeated calls to SPI.setDataMode.

I had a similar issue with my project; each of the three SPI slaves wanted a different clock speed and only one of the libraries (SdFat) was actually setting it each time it used the bus. The other two libraries only set it at initialization, which is a design flaw in those two libraries.

That's another thing, check to see if SD and MAX are using compatible SPI clock speeds.

Also, move SD.begin from loop() into setup(). You should only be doing that once in your sketch.

You can change any SPI setting on the fly. Change to mode 1, use the thermocouple, then change back to mode 0.

Thank you both for your help. I will try these changes when I get home (4 hours) and report back with what I find.

UPDATE: It works!! ...well, mostly.

In setup(), I set all pins to OUTPUT and HIGH. I initialize the SD, then the SPI library. Then, in my loop():

void loop{

SPI.setDataMode(SPI_MODE1);

collectTemps(); //psuedo for the forum

SPI.setDataMode(SPI_MODE0);

useSDCard(); //psuedo for the forum

}

The issue is when I come back to SPI_MODE1, the very first value thermocouple value I read is incorrect. Every subsequent request is correct, as if the problem fixes itself when the value moves through the SPI library.

I will look into this later for a clean fix, but for the time being I'm happy with it working. To solve the problem using all temperature inputs, I read in an input into a throwaway variable.

 struct var_max31855 *tc_ptr;

  // junk value
  tc_ptr = &TC_CH0;
  thermocouple0.MAX31855_update(tc_ptr);        // Junk value to fix SPI issue 
  
  // update TC0
  tc_ptr = &TC_CH0;
  thermocouple0.MAX31855_update(tc_ptr);        // Update MAX31855 readings 
  
  // update TC1
  tc_ptr = &TC_CH1;
  thermocouple1.MAX31855_update(tc_ptr);        // Update MAX31855 readings 
  
  // update TC2
  tc_ptr = &TC_CH2;
  thermocouple2.MAX31855_update(tc_ptr);        // Update MAX31855 readings 
  
  // update TC3
  tc_ptr = &TC_CH3;
  thermocouple3.MAX31855_update(tc_ptr);        // Update MAX31855 readings

Thanks again for the help; hopefully this will help someone down the road with multiple shields and SPI issues.

It is probably the SD library that causes the first thermocouple read in your loop (after a SD read/write) to be in error. The SD card does not release the MISO line until a last clock cycle is sent after the SS line goes HIGH to release that line.

Here is the post from fat16lib with the fix that I implemented in my SD library that corrected the problem for me.

Nice! I'd forgotten about that.

It's probably just as easy to use SdFat instead of repairing SD. I believe SdFat sets the mode and clock speed with each access. So you just have to fix the thermocouple library.

I switched to SDFat. Saved me 1300 bytes, no more setting a garbage thermocouple, and I don’t have to set the SPI_MODE before I use the SD Card. Thanks again.

UPDATE: I’m trying to port this setup to the MEGA 2560 (with a GSM Shield as well, but no luck so far). Can get the shields working separately but when together it all falls apart. If I can conclude it’s another SPI issue I’ll post what I’ve tried here, otherwise, I’ll start a new thread.