SD Library Conflict

Greetings,

I am working on a project that uses UNO and Ethernet shield to log data from a 2 channel RTD sensor breakout board based on SPI. I am encountering a problem logging the RTD data to the SD card on the Ethernet shield. I use the SD.h library, but as soon as the sketch executes the line with "SD.begin()" when the SD card is not present in the shield, the reading deviates off to the very negative extreme. In the meantime, when the SD card is present (inserted), the reading deviates off to the very positive end of the RTD sensor measurement capacity. I have check memory capacity of the UNO and it has enough when executing the sketch. Here are my instrument list and codes. Thank you for your help.

Arduino UNO
Arduino Ethernet Shield with SD
Play With Fusion MAX31865 RTD-to-digital converter breakout board

void setup()
{
  Serial.begin(9600);
  
  // Check for amount of free memory
  Serial.print("Free Memory: ");
  freeMem();
  
  // Setup the SPI library
  SPI.begin();                        // begin SPI
  SPI.setDataMode(SPI_MODE3);         // MAX31865 is a Mode 3 device
    
  rtd_ch0.MAX31865_config();
  rtd_ch1.MAX31865_config();
 
  // Disable SPI of RTD #1
  pinMode(SS_RTD1, OUTPUT);
  digitalWrite(SS_RTD1, HIGH);
  
  // Disable SPI of RTD #2
  pinMode(SS_RTD2, OUTPUT);
  digitalWrite(SS_RTD2, HIGH);
  
  // Disable W5100
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  
  // Disable SD
  pinMode(SS_SD,OUTPUT);
  digitalWrite(SS_SD,HIGH);
  
  // Check for SD card
  /*
  Serial.print("Initializing SD card ... ");
  if (!SD.begin(SS_SD))
  {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialized.");
  */
      
  delay(500);
}

void loop()
{
  static struct var_max31865 RTD_CH0;
  static struct var_max31865 RTD_CH1;
  
  // Handle values: 1: Pt-100, 2: Pt-1000 
  // RTD_CH0.RTD_type = 1;                        
  RTD_CH0.RTD_type = 2;                        
  // RTD_CH1.RTD_type = 1;                        
  RTD_CH1.RTD_type = 2;
    
  struct var_max31865 * rtd_ptr0;
  struct var_max31865 * rtd_ptr1;
  
  rtd_ptr0 = &RTD_CH0;
  rtd_ptr1 = &RTD_CH1;
  
  // Update MAX31855 readings
  rtd_ch0.MAX31865_full_read(rtd_ptr0);          
  rtd_ch1.MAX31865_full_read(rtd_ptr1);
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  // digitalWrite(SS_SD,LOW);
  // File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // digitalWrite(SS_SD,HIGH);
  
  // RTD #1 
  if(0 == RTD_CH0.status)                       // No fault, print info to serial port
  {
    if(1 == RTD_CH0.RTD_type)                   // Handle values for PT-100
    {
      // calculate RTD resistance
      R1 = (float)RTD_CH0.rtd_res_raw * 400 / 32768;
      
      Serial.print(R1);                         
      Serial.print("   ");
    }
    else if(2 == RTD_CH0.RTD_type)                // Handle values for PT-1000
    {
      // calculate RTD resistance
      R1 = (float)RTD_CH0.rtd_res_raw * 4000 / 32768;
      Serial.print(R1);                         
      Serial.print("   ");
    }
    // calculate RTD temperature (simple calc, +/- 2 deg C from -100C to 100C)
    // more accurate curve can be used outside that range
    // tmp1 = ((double)RTD_CH0.rtd_res_raw / 32) - 256;
    tmp1 = (-A + sqrt(pow(A,2) - 4*B*(1 - R1/R0))) / (2*B);
    Serial.print(tmp1);                         
    Serial.print("   ");
  }  // End of no-fault handling RTD #1
  else 
  {
    Serial.print("RTD Fault, register: ");
    Serial.print(RTD_CH0.status);
    if(0x80 & RTD_CH0.status)
    {
      Serial.print("RTD High Threshold Met");            // RTD high threshold fault
    }
    else if(0x40 & RTD_CH0.status)
    {
      Serial.print("RTD Low Threshold Met");             // RTD low threshold fault
    }
    else if(0x20 & RTD_CH0.status)
    {
      Serial.print("REFin- > 0.85 x Vbias");             // REFin- > 0.85 x Vbias
    }
    else if(0x10 & RTD_CH0.status)
    {
      Serial.print("FORCE- open");                       // REFin- < 0.85 x Vbias, FORCE- open
    }
    else if(0x08 & RTD_CH0.status)
    {
      Serial.print("FORCE- open");                       // RTDin- < 0.85 x Vbias, FORCE- open
    }
    else if(0x04 & RTD_CH0.status)
    {
      Serial.print("Over/Under voltage fault");          // overvoltage/undervoltage fault
    }
    else
    {
      Serial.print("Unknown fault, check connection");   // print RTD temperature heading
    }
  }  // end of fault handling RTD #1
  
  /*
  ----------------------------------------------------------------------------------------------------------------------------
  */
  
  // RTD #2
  if(0 == RTD_CH1.status)                       // No fault, print info to serial port
  {
    if(1 == RTD_CH1.RTD_type)                   // Handle values for PT-100
    {
      // calculate RTD resistance
      R2 = (float)RTD_CH1.rtd_res_raw * 400 / 32768;
      Serial.print(R2);                         // print RTD resistance
      Serial.print("   ");
    }
    else if(2 == RTD_CH1.RTD_type)              // handle values for PT-1000
    {
      // calculate RTD resistance
      R2 = (float)RTD_CH1.rtd_res_raw * 4000 / 32768;
      Serial.print(R2);                         // print RTD resistance
      Serial.print("   ");
    }
    // calculate RTD temperature (simple calc, +/- 2 deg C from -100C to 100C)
    // more accurate curve can be used outside that range
    // tmp2 = ((double)RTD_CH1.rtd_res_raw / 32) - 256;
    tmp2 = (-A + sqrt(pow(A,2) - 4*B*(1 - R2/R0))) / (2*B);
    Serial.print(tmp2);                         // print RTD resistance
    Serial.print("   ");
  }  // end of no-fault handling RTD #2
  else 
  {
    Serial.print("RTD Fault, Register: ");
    Serial.print(RTD_CH1.status);
    if(0x80 & RTD_CH1.status)
    {
      Serial.print("RTD High Threshold Met");            // RTD high threshold fault
    }
    else if(0x40 & RTD_CH1.status)
    {
      Serial.print("RTD Low Threshold Met");             // RTD low threshold fault
    }
    else if(0x20 & RTD_CH1.status)
    {
      Serial.print("REFin- > 0.85 x Vbias");             // REFin- > 0.85 x Vbias
    }
    else if(0x10 & RTD_CH1.status)
    {
      Serial.print("FORCE- open");                       // REFin- < 0.85 x Vbias, FORCE- open
    }
    else if(0x08 & RTD_CH1.status)
    {
      Serial.print("FORCE- open");                       // RTDin- < 0.85 x Vbias, FORCE- open
    }
    else if(0x04 & RTD_CH1.status)
    {
      Serial.print("Over/Under voltage fault");          // overvoltage/undervoltage fault
    }
    else
    {
      Serial.print("Unknown fault, check connection");   // print RTD temperature heading
    }
  }  // end of fault handling RTD #2

  /*
  ----------------------------------------------------------------------------------------------------------------------------
  */
  
  // Reading analog humidity modules
  rhRead1 = analogRead(rhSen1);
  float rh1 = ( rhRead1 / 1024.0 ) * voltage * 100.0;
  Serial.print(rh1);
  Serial.print("   ");
    
  rhRead2 = analogRead(rhSen2);
  float rh2 = ( rhRead2 / 1024.0 ) * voltage * 100.0;
  Serial.println(rh2);
    
  delay(1000);
}
 SPI.setDataMode(SPI_MODE3);

The SD.h uses mode 0 so you need to reset the mode before accessing your sensors.

Unfortunately the ancient version of SdFat used in the SD.h library won't select the proper SPI mode so you will also need to change mode before accessing the SD.

Newer versions of SdFat set the SPI mode and speed before every access to the SPI bus. Also many SdFat bugs have been fixed over the years since the Arduino Company released their SD.h wrapper for the old version of SdFat.

Thanks fat16lib!

I have to switch between Mode3 and Mode0 to have both SPI devices working properly, but when the microSD card is inserted, the reading is off again. Then, I read about changing the clock rate and after some trial and error, it is working now, but I have no idea the exact meaning of the following line. It does not work for DIV2, DIV4, DIV8, and DIV16, but it started working with DIV32 and beyond. I hope I did not damage the UNO in doing the trial and error procedure.

SPI.setClockDivider(SPI_CLOCK_DIV32);