[SOLVED] SD Serial conflicting with multiplexer serial?

Hi,
I'm working on a temperature data logger and I'm having trouble getting the serial communication to work on both boards. I'm using an Uno.

The thermocouple multiplexer board is from Ocean Controls: Electronics & Automation Engineering T/A Ocean Controls > Arduino Shields > Arduino K, J or T Type Thermocouples Multiplexer Shield, and I'm using most of their code (bit banging example).

The SD card is from Newegg http://www.newegg.com/Product/Product.aspx?Item=9SIA2V51428280.

Both boards must be connected to pin 13 for SCK, but the rest of the pins are separate (I moved pin 12 on the multiplexer to pin 8, but couldn't get any sketch to work if I moved SCK to another pin). If I run the code below the multiplexer returns all bits 0, but the SD card writes OK. If I comment out the SD.begin() command, the multiplexer will read correctly but of course I've disabled the SD.

There's too much data to read first, then write after. I have to loop between reading my 8 temperatures and writing them to SD.

From what I've read the serial interface can serve multiple devices as long as I correctly control the CS pin for each device. I've also read that the SD.h library doesn't properly put the SD to "sleep", so I'm guessing it's still interfering with the multiplexer even though I digitalWrite(SDPINCS,LOW); on line 101. Maybe this isn't the right way to do it, maybe it's not possible with SD.h? Maybe I can use softwareserial to move SCK, or use SDFat to properly shut down the SD while I read my temps? (I'm going to try these next, but any ideas or suggestions in the meantime are appreciated.

Thanks,
-D

Haake_Refurb_Control.ino (7.76 KB)

digitalWrite(SDPINCS,LOW);

Most chip selects are active Low; you bring them High to kick them off the SPI bus.

Thanks CrossRoads. I tried flip-flopping the high/low for SDPINCS with no luck.
(I also tested flip-flopping TCPINEN, but that one is right.)

Anyone have any experiencing "kicking SD modules off the bus" with SD.h?

Learning how to work the forum... Here's my code:

#include <string.h>
#include <ctype.h>
#include <SD.h>

//------Thermocouple multiplexer definitions-----
#define SHOWMEYOURBITS // display MUX raw bits on Serial
#define TCPINA0 4 //Mux Address 0 pin
#define TCPINA1 5 //Mux Address 1 pin
#define TCPINA2 6 //Mux Address 2 pin
#define TCPINEN 7 //Mux Enable pin
#define TCPINSO 8 //TCAmp Slave Out pin (MISO) [Pin 12 on shield]
#define TCPINCS 9  //TCAmp Chip Select
#define TCPINSC 13 //TCAmp Serial Clock (SCK)
int temperatures[8], internalTemperatures[8], sensorFail[8]; //Temperature, internal temperature, and sensor failure flags
char failMode[8]; //Failure codes
unsigned int Mask; //Temperature value storage during read

//-----SD Variable Definitions-----
#define SDPINCS 10 //SD Chip Select
unsigned int fileNumber = 0; //SD card file search index
File dataFile; //data output file
File configFile; //configuration input file
/*
  Add instructions for configFile configuration
*/

//-----General use variables-----
#define LEDPIN 2 //General LED pin to indicate SD writing (or whatever)
char i; //general use integer
String buf; //general use string

void setup()
{
//-----Open serial communications-----
  Serial.begin(9600);

//-----INITIALIZE MULTIPLEXER-----
  pinMode(TCPINEN, OUTPUT);     
  pinMode(TCPINA0, OUTPUT);    
  pinMode(TCPINA1, OUTPUT);    
  pinMode(TCPINA2, OUTPUT);    
  pinMode(TCPINSO, INPUT);    
  pinMode(TCPINCS, OUTPUT);    
  pinMode(TCPINSC, OUTPUT);   

  digitalWrite(TCPINEN, LOW); 

//-----INITIALIZE SD CARD-----
  Serial.print("Initializing SD Card...\r\n");
  pinMode(SDPINCS,OUTPUT);

  if (!SD.begin(SDPINCS)) {
    Serial.println("SD initialization failed!");
    return;
  }
  Serial.println("SD initialization done.");

//-----OPEN CONFIG.TXT FILE-----
  if (SD.exists("config.txt")){
    configFile = SD.open("config.txt", FILE_READ);
    Serial.println("Reading config.txt:");
      if (configFile){
      while (configFile.available()){
        Serial.write(configFile.read()); //list contents of config.txt. Replace later to read configuration settings.*****
      }
      Serial.write("\n");
    }
    configFile.close();
  }
  else {
    Serial.println("Error reading config.txt");
//    return;
  }  

//-----OPEN NEXT AVAILABLE CSV Fx.CSV, WHERE x IS THE NEXT AVAILABLE FILE NUMBER-----
  char charFileName[0];
  
  do{
    buf=String(String("f" + String(fileNumber,DEC)) + ".csv");
    buf.toCharArray(charFileName, buf.length()+1);
    fileNumber++;
  }while (SD.exists(charFileName));
  
  Serial.println(String("Creating new data file " + buf));
  dataFile = SD.open(charFileName,FILE_WRITE);
  dataFile.println("Temp0,Temp1,Temp2,Temp3,Temp4,Temp5,Temp6,Temp7");  


}

void loop()
{
if (millis()<10000){//Temporary limit for debugging

  digitalWrite(SDPINCS,HIGH);//disable SD serial 
  digitalWrite(TCPINEN, HIGH); // enable TC serial
  getTemp();
  digitalWrite(TCPINEN,LOW);//disable TC serial
  digitalWrite(SDPINCS,LOW);//enable SD serial
  
  Serial.print("\n");

  for (i=0;i<8;i++){
    Serial.print(millis()); //used as an example to debug instead of temperatures, below.
    Serial.print(","); //used as an example to debug instead of temperatures, below.
    dataFile.print(millis()); //used as an example to debug instead of temperatures, below.
    dataFile.print(","); //used as an example to debug instead of temperatures, below.
   
//    Serial.print(((float)temperatures[i]*0.25),2);
//    Serial.print(",");
//    dataFile.print(((float)temperatures[i]*0.25),2);
//    dataFile.print(",");
  }
  Serial.print("\n");
  dataFile.print("\n");

  delay(1000);


} else
if (dataFile){
  dataFile.close();
  Serial.println("Data file closed.");

}

}//end of loop

void getTemp()
//Obtains current temperature, error, and error codes for all eight channels.
{
  int ch; //current channel

  for (ch=0;ch<8;ch++){
    temperatures[ch] = 0;
    failMode[ch] = 0;
    sensorFail[ch] = 0;
    internalTemperatures[ch]=0;
    
    //initialize
    digitalWrite(TCPINSC,LOW);//disable bit read (initialization)
    digitalWrite(TCPINCS,LOW);//disable TC conversion (initialization)
    delay (5);

    //convert temperature on mutliplexer
    selectChannel(ch);
    digitalWrite(TCPINCS,HIGH);//begin TC conversion
    delay(100);
    digitalWrite(TCPINCS,LOW);//end TC conversion
    delay(1);
    
    //read bits
      for (i=31;i>=0;i--){
        digitalWrite(TCPINSC, HIGH); //get next bit
        delay(1);


        #ifdef SHOWMEYOURBITS  
          if (digitalRead(TCPINSO)==1){ //current bit is received as 1
            Serial.print("1");
          } else{//current bit was received as 0
            Serial.print("0");
          }
          if (i==0){
            Serial.print("\n");
          }
        #endif

        if ((i<=31) && (i>=18)){ //thermocouple temperature data is being read
          Mask = 1<<(i-18); //convert current bit number (i) to integer value and store in Mask
          if (digitalRead(TCPINSO)==1){ //current bit is received as 1
            if (i==31){ //sign bit is being read
              temperatures[ch] += (0b11<<14);
            }
            temperatures[ch] += Mask; //add Mask value to the temperature
          }//current bit was received as 0, so do nothing
        }
        
        //bit 17 is reserved, do nothing with bit 17.

        if (i==16){ //read sensor fail bit
          sensorFail[ch] = digitalRead(TCPINSO);
        }
                
        if ((i<=15) && (i<=4)){ //internal temperature data is being read
          Mask = 1<<(i-4); //convert current bit number (i) to integer value and store in Mask
          if (digitalRead(TCPINSO) == 1) { //current bit received as 1
            if (i==15){ //internal temp is negative
              internalTemperatures[ch] += (0b1111<<12);
            }
            internalTemperatures[ch] += Mask; //add Mask value to the internal temperature
          } //current bit was received as 0, so do nothing
        }
        
        //bit 3 is reserved, do nothing with bit 3.

        if (i==2){
          failMode[ch]+=digitalRead(TCPINSO)<<2; //bit 2 is set if shorted to VCC
        }
        
        if (i==1){
          failMode[ch]+=digitalRead(TCPINSO)<<1; //bit 1 is set if shorted to ground
        }
        
        if (i==0){
          failMode[ch]+=digitalRead(TCPINSO)<<0; //bit 0 is set if tc is open circuit
        }
        
        digitalWrite(TCPINSC, LOW);//stop reading current bit
        delay(1);
      }
  }
  
}

void selectChannel(int j)
//Sets thermocouple multiplexer outputs to select thermocouple input channel ch (1-8)
{
  if (j<0 or j>7){
    Serial.println("Invalid thermocouple channel selection");
    j=0;
  }
  switch (j)
    {
      case 0:
        digitalWrite(TCPINA0, LOW); 
        digitalWrite(TCPINA1, LOW); 
        digitalWrite(TCPINA2, LOW);
      break;
      case 1:
        digitalWrite(TCPINA0, HIGH); 
        digitalWrite(TCPINA1, LOW); 
        digitalWrite(TCPINA2, LOW);
      break;
      case 2:
        digitalWrite(TCPINA0, LOW); 
        digitalWrite(TCPINA1, HIGH); 
        digitalWrite(TCPINA2, LOW);
      break;
      case 3:
        digitalWrite(TCPINA0, HIGH); 
        digitalWrite(TCPINA1, HIGH); 
        digitalWrite(TCPINA2, LOW);
      break;
      case 4:
        digitalWrite(TCPINA0, LOW); 
        digitalWrite(TCPINA1, LOW); 
        digitalWrite(TCPINA2, HIGH);
      break;
      case 5:
        digitalWrite(TCPINA0, HIGH); 
        digitalWrite(TCPINA1, LOW); 
        digitalWrite(TCPINA2, HIGH);
      break;
      case 6:
        digitalWrite(TCPINA0, LOW); 
        digitalWrite(TCPINA1, HIGH); 
        digitalWrite(TCPINA2, HIGH);
      break;
      case 7:
        digitalWrite(TCPINA0, HIGH); 
        digitalWrite(TCPINA1, HIGH); 
        digitalWrite(TCPINA2, HIGH);
      break;
    }
}//end of selectChannel

There's a conflict on pin 13, SCK.

There are two ways to solve this problem. I first re-routed the multiplexer pin from 13 to 8, which was an ugly mess but worked.

I later found this post on adafruit's forum: http://www.adafruit.com/forums/viewtopic.php?f=31&t=39699. Turns out if you SD.begin(SDPINCS, 11, 12, 13) instead of SD.begin(SDPINCS) the SD library will disable hardware SCK and allow you to bit-bang the data out of the MUX.