SPI not working for multiple devices (MEGA2560)

Dear all,

I've got a MEGA2560 with a Sensor Shield V2.0 board. I will be using this as a remote data collector. The data will be locally stored on a SD-card and will also be transmitted to home base via an nRF24L01.

I've got two boards both using the SPI protocol: A SD-card (http://arduino-info.wikispaces.com/SD-Cards) which is connected to the SD-card connector on the Sensor Shield board.
And I also got a nRF24L01 TX board connected to the same MISO, MOSI and SCK pins but also on pin 8 and 7. 7= CE and 8= CSN

Both, SD-card and nRF24L01, boards work individually but refuse to work together.

When I call the specific function I open the function with digitalWrite(CSSD, LOW); and close the function with digitalWrite(CSSD, HIGH);

Eg:

void Radio() {
  digitalWrite(CSTX, LOW);
  radio.write(&LDRValue, 2); // Second parameter specifies amount of bytes, long = 2 bytes, float = 4 bytes
  radio.write(&TempOffice, 4);
  digitalWrite(CSTX, HIGH);

You would expect by doing this that the SPI will then be ready to open up another function and read the data from that. However, that's not the case.
I also got an RTC (DS3231) and an LCD (4 x 2) connected via I2C to the MEGA and when I try to run as is then the clock stops working and also the Serial Monitor.

I am aware that the SPI uses common MOSI, MISO and CLK lines but uses different CS pins for each application.

Can somebody tell me where I went wrong? I've kind of given up by spending more then 8 hours on this.

Here is my code:

/* TEMPERATURE DATA LOGGER, 19-02-2018@Luc De Pauw */
/*---( LIBRARIES )---*/ 
#include <OneWire.h>           /*DS18B20*/ 
#include <DallasTemperature.h> /*DS18B20*/
#include <Wire.h>              /*RTC DS3231*/
#include "Sodaq_DS3231.h"      /*RTC DS3231*/
#include <LiquidCrystal_I2C.h> /*LCD*/    
#include <SD.h>                /*SD-card*/  
#include "Timer.h"             /*Timer*/
#include <SPI.h>               /*nRF24L01*/
#include <RF24.h>              /*nRF24L01*/  
/*---( DECLARE OBJECTS )---*/
/*LCD*/           //                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol       //Set the pins on the I2C chip used for LCD connections:
/*LCD*/           LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  //Set the LCD I2C address to 0x20 or 0x27, determined by A0, A1 and A2
/*DS18B20*/       OneWire oneWire(2); //Data wire is plugged into pin 2 on the Arduino
/*DS18B20*/       DallasTemperature tempSensors(&oneWire); //Pass our oneWire reference to Dallas Temperature.
/*DS18B20*/       DeviceAddress TempSensor0 = { 0x28, 0x2D, 0x68, 0x4D, 0x05, 0x00, 0x00, 0x85 }; //Insert unique 128 bit address of sensor
/*SD-card*/       const int CSSD = 53; // Chip Selct SD card,Also for nRF24L01 as it uses the shared SPI-bus
/*nRF24L01*/      RF24 radio(7, 8); // CE, CSN= Chip Select Not
                  const int CSTX = 8;
/*nRF24L01*/      byte addresses[][6] = {"0"}; //Identify the transmitting and receiving bit
/*---( DECLARE VARIABLES )----*/
/*DS18B20*/       float TempOffice;
/*DS18B20*/       float MaxTemp1;
/*DS18B20*/       float MinTemp1 = 50;
/*LDR*/           long LDRValue;
/*RTC DS3231*/    char TimeBuffer[19] = "";
/*Timer*/         Timer timer;
 
void setup(){
/*Serial Monitor*/Serial.begin(9600); //Start serial port
                  SPI.begin();
/*LCD*/           lcd.begin(20,4); //Initialize the lcd for 20 chars 4 lines
/*RTC DS3231*/    rtc.begin(); //Start the RTC library code 
/*DS18B20*/       tempSensors.begin();  //Start the OneWire library
/*DS18B20*/       tempSensors.setResolution(TempSensor0, 11); //Set the resolution to 11 bit (Can be 9 to 12 bits .. lower is faster but less accurate)
/*SD-card*/       Serial.print("Initializing SD card...");
/*SD-card*/       pinMode(CSSD, OUTPUT);  //Make sure that the default chip select pin is set to output, even if you don't use it:
/*SD-card*/       if (!SD.begin(CSSD)) {   //See if the card is present and can be initialized:
/*SD-card*/       Serial.println("Card failed, or not present");}
/*SD-card*/       Serial.println("Card initialized.");
/*Timer*/         timer.every(5000, SerMon); //Write every 5 seconds to the SerialMonitor
/*Timer*/         timer.every(30000, WriteToSD);  //Write every 30 seconds to the SD-card
                  pinMode(CSTX, OUTPUT);
/*nRF24L01*/      radio.begin();  // Initiate the radio object
/*nRF24L01*/      radio.setChannel(124);  // 0 to 124, frequencies between 2.4 and 2.5 Ghz in chunks of 100 MHz. Use a channel unlikely to be used by Wifi, Microwave ovens etc 
/*nRF24L01*/      radio.setPALevel(RF24_PA_MIN);  // Set the transmit power to lowest available to prevent power supply related issues, can also be set to MAX  
/*nRF24L01*/      radio.setDataRate(RF24_2MBPS);  // Set the speed of the transmission to the quickest available, can be set to 250KB or 1MBPS to increase range  
/*nRF24L01*/      radio.openWritingPipe(addresses[0]);  // Open a writing and reading pipe on each radio, with opposite addresses
/*nRF24L01*/      radio.openReadingPipe(1, addresses[0]);
}

void loop(){
 timer.update();
 Clock();
 ReadTemp();
 MaxTemp();
 MinTemp();
 LDR();
 LCDPrint();
 Radio();
 //SerMon(); // No need to call as this is done by the timer
 //WriteToSD(); // No need to call as this is done by the timer
}
void Clock(){
  DateTime now = rtc.now(); //Read the current date-time from the RTC
  sprintf(TimeBuffer, "%04d-%02d-%02d %02d:%02d:%02d", now.year(), now.month(), now.date(), now.hour(), now.minute(), now.second());  
}
/
void ReadTemp(){   
  tempSensors.requestTemperatures(); // Send the command to get temperatures
  TempOffice = tempSensors.getTempC(TempSensor0);
}

void MaxTemp(){
  if (TempOffice > MaxTemp1) {
    MaxTemp1 = TempOffice; }
}

void MinTemp(){
  if (TempOffice < MinTemp1) {
    MinTemp1 = TempOffice; }
}

void LDR() {
    LDRValue = analogRead(A0);
    }

void LCDPrint(){  
  lcd.setCursor(0,0); //Start at character 0 on line 0
  lcd.print("CurrentTemp= "); lcd.print(TempOffice,1); lcd.print(" C");
  lcd.setCursor(0,1);
  lcd.print("MaxTemp= "); lcd.setCursor(13,1); lcd.print(MaxTemp1,1); lcd.print(" C");
  lcd.setCursor(0,2);
  lcd.print("MinTemp= "); lcd.setCursor(13,2); lcd.print(MinTemp1,1); lcd.print(" C");
  lcd.setCursor(0,3);
  lcd.print(TimeBuffer); 
}

void Radio() {
  digitalWrite(CSTX, LOW);
  radio.write(&LDRValue, 2); // Second parameter specifies amount of bytes, long = 2 bytes, float = 4 bytes
  radio.write(&TempOffice, 4);
  digitalWrite(CSTX, HIGH);
}

void SerMon(){                      //Every 5 seconds writes data to serial monitor, activated by timer
  Serial.print("Writing data to Serial: ");
  Serial.print("TempOffice= "); Serial.print(TempOffice,1); Serial.print("°C |");
  Serial.print(" MAX= "); Serial.print(MaxTemp1, 1); Serial.print("°C |");
  Serial.print(" MIN= "); Serial.print(MinTemp1, 1); Serial.print("°C |");
  Serial.print(" LDR= "); Serial.println(LDRValue, 1);
}

void WriteToSD(){                   //Every 30 seconds writes data to SD-card and to serial monitor, activated by timer
   digitalWrite(CSSD, LOW);
  // digitalWrite(chipSelect, LOW); // Chip Select pin must be low before the Slave is recognised
   
   File dataFile = SD.open("datalog.txt", FILE_WRITE); //Open the file. Only one file can be open at a time, so you have to close this one before opening another
  if (dataFile) {  //If the file is available, write to it:
    dataFile.print(TimeBuffer); dataFile.print(", "); dataFile.print(TempOffice, 1); dataFile.print(", "); dataFile.print(MaxTemp1, 1);
    dataFile.print(", "); dataFile.print(MinTemp1, 1); dataFile.print(", "); dataFile.println(LDRValue, 0);
    dataFile.close();}  
  else {   //If the file isn't open, pop up an error
   Serial.println("Error opening datalog.txt");}
//Also print confirmation and data to Serial Monitor    
 Serial.print("To SD-card: "); Serial.print("TempOffice= "); Serial.print(TempOffice,1); Serial.print("°C |");
 Serial.print(" MAX= "); Serial.print(MaxTemp1, 1); Serial.print("°C |");
 Serial.print(" MIN= "); Serial.print(MinTemp1, 1); Serial.print("°C |");
 Serial.print(" LDR= "); Serial.println(LDRValue, 1);
digitalWrite(CSSD, HIGH);
}

Have you checked if SPI bus speed is the same in both library?

Hi J-M-L,

Thanks for that! I didn't even know about the possibility of different bus speed!
I will check it out tomorrow.
Cheers,

Luc

I had an exactly similar problem.

The SD Card reader was sourced from E-Bay and the Chinese version ( which I think is very popular otherwise ) was holding on to the SPI bus even after it was done with it. This is a hardware issue. So unless the card is subject to a corrective surgery. Unfortunately this was discussed in this forum and I am unable to locate the thread right now.

No possibility of surgery on the SMD pcb ? Simply buy the Micro SD Breakout board from Adafruit and it works first shot !!

Thanks Ardubit,

I took your advice on board and have ordered three new SD-card boards on Banggood.
I now have to wait patiently until the order arrives.
Cheers,

Luc

Hi J-M-L,

I had a look through both libraries and was hoping to find a single line of code about the SPI speed setting.
However, there were about a 100 lines containing references to speed settings.
I'm not good enough to break it all down so I gave up...
Thanks for the advice anyway. Karma updated.
Cheers,

Luc