Electronic – arduino – How to avoid SD Card and W1500 SPI mixup on the Ethernet Shield

arduinocethernetsoftware

In an answer Kevin Mark points to a solution/reason for the usage of the Ethernet shield together with the SD Card. The documentation says that SD Card and the Ethernet chip both share the SPI bus and that I have to set different pins on HIGH to tell the Ethernet shield to use the Ethernet OR the SD Card.

How would such a solution look like?

pinMode(4, OUTPUT);
digitalWrite(4, HIGH);

// Now I can use the SD Card?

pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

// Now I can use the Ethernet (W5100)?

// Do I have to (re)set 4 to LOW?
// Any possibility to use both at the same time?
// Can I use the Ethernet/SD Card without the setting of pin 4 or 10?
// Why is this missing on the official code examples? Is it really necessary?

Best Answer

In SPI, the following connections are used:

  • MISO (Master In Slave Out) - a data line for sending data from the slave to the master
  • MOSI (Master Out Slave In) - a data line for sending data from the master to the slave
  • SCK (Serial Clock) - a clock generated by the master for clocking the bits on MISO and MOSI
  • SS (Slave Select) - a data line from the master to a particular slave.

There is one SS for every slave device. MISO, MOSI, and SCK are shared between all the devices on the bus.

In your case, pin 4 is SS for the SD card interface while pin 10 is SS for the ethernet controller.

Your code should look something like this (untested code):

#define SS_SD_CARD   4
#define SS_ETHERNET 10

void setup() {
    // ...
    pinMode(SS_SD_CARD, OUTPUT);
    pinMode(SS_ETHERNET, OUTPUT);
    digitalWrite(SS_SD_CARD, HIGH);  // SD Card not active
    digitalWrite(SS_ETHERNET, HIGH); // Ethernet not active
    // ...
}

void scCardCode() {
    // ...
    digitalWrite(SS_SD_CARD, LOW);  // SD Card ACTIVE
    // code that sends to the sd card slave device over SPI
    // using SPI.transfer() etc.
    digitalWrite(SS_SD_CARD, HIGH); // SD Card not active
    // ...
}

void ethernetCode() {
    // ...
    digitalWrite(SS_ETHERNET, LOW);  // Ethernet ACTIVE
    // code that sends to the ethernet slave device over SPI
    // using SPI.transfer() etc.
    digitalWrite(SS_ETHERNET, HIGH); // Ethernet not active
    // ...
}

You should make sure that 4 and 10 are not low at the same time because that would cause the same data to be sent to both slaves--BAD.

Your library probably handles setting 4 & 10 low and high at the appropriate times. However, there may be methods that leave one of them low until another method sets it high. During that period, you should not use a method for the other device. It's possible for the library to handle cases like this, but since your bug seems to be known, it obviously does not do it well, if at all.