SD card vs. Ethernet on Arduino Ethernet Shield v2

On the Arduino Ethernet Shield v2 the SD card and Ethernet are connected via SPI. I want to use both, the SD card and Ethernet over the life time of the overall application. How do I have to do the setup then? Can I use SD.begin(); and Ethernet.begin(mac, ip); once at startup and dynamically switch between them with the SPI chip selects (Pin 4 for SD card, Pin 10 for ETH)? Ethernet will be needed most of the time. So I'd chip select Pin 4 (low -> active: digitalWrite(sdChipSelectPin, LOW); digitalWrite(ethernetChipSelectPin, HIGH);) only for the time of reading from/writing to the SD card and chip select Pin 10 (vice versa to enable Ethernet) else, right?

EDIT: On top of the Ethernet lib I'm using aWOT for providing RESTful API endpoints. To send data I'm using the mWebSockets lib. Of course everything should work despite of writing data to the SD card as part of a RESTful API endpoint logic :wink:

the libraries control the CS pin. only thing to do is in setup() set the CS pins of the second HIGH before begin() the first

Ok.

What do you mean exactly :grin: ?

Do you mean this:

#define CHIP_SELECT_ACTIVE LOW
#define CHIP_SELECT_PASSIVE HIGH

const int sdCardChipSelectPin = 4;
const int ethernetChipSelectPin = 10;

digitalWrite(ethernetChipSelectPin, CHIP_SELECT_PASSIVE);
SD.begin();

Does not work.

However this code seems to work w.r.t. SD card functionality (Ethernet?):

  pinMode(sdCardChipSelectPin, OUTPUT);
  pinMode(ethernetChipSelectPin, OUTPUT);
  digitalWrite(sdCardChipSelectPin, CHIP_SELECT_PASSIVE);
  digitalWrite(ethernetChipSelectPin, CHIP_SELECT_PASSIVE);

  digitalWrite(sdCardChipSelectPin, CHIP_SELECT_ACTIVE);
  while (!SD.begin(sdCardChipSelectPin)) {
    delay(1000);
  }

so pinmode would be good an HIGH is a nice constant

Right, this works to make the SD card working.

  #define CHIP_SELECT_PASSIVE HIGH

  const int sdCardChipSelectPin = 4;
  const int ethernetChipSelectPin = 10;

  pinMode(sdCardChipSelectPin, OUTPUT);
  pinMode(ethernetChipSelectPin, OUTPUT);
  digitalWrite(ethernetChipSelectPin, CHIP_SELECT_PASSIVE);

  while (!SD.begin(sdCardChipSelectPin)) {
    Serial.println("SD Library konnte nicht initialisiert werden.");
    delay(1000);
  }

However it does not work when both is used, the SD card and Ethernet. In a PUT RESTful API server I'm writing data to the SD card. That works. However after the endpoint has been triggered the RESTful API is not responding anymore. This means the SS/chip select pins are not managed by the libs automatically! However nowhere is defined how one has to use the SD card lib in combination with the Ethernet lib.

SD.begin sets the SD CS pins mode and state. you don't have to

No, it's not working w.o. passing the pin! It's also not working with

   ...

  digitalWrite(sdCardChipSelectPin, CHIP_SELECT_ACTIVE);
  while (!SD.begin()) {
    Serial.println("SD Library konnte nicht initialisiert werden.");
    delay(1000);
  }

Florian,
some days ago I've written a demo sketch with Ethernet + SD

  • a periodically log of some data to the SD Card
  • a small webserver
  • download the log from the SD via the webserver
  • fetch date/time via SNTP / UDP (for logging)

You can find that sketch here: https://werner.rothschopf.net/microcontroller/202108_arduino_webserver_ntp_sd_en.htm

You will need Juraj's Streamlib.h to make it work.

By the way, in the international section you will find also a German forum.

Thanks @noiasca for letting me know.

you need pinmode and writedigital for ethernet CS before SD.begin

Hey, nice project. I've looked into your sources and found out that you do not manually set the chip select signals for the SD card (Pin 4) or Ethernet (Pin 10) despite during SD card initialization if (!SD.begin(ssSD)) { (webserver_receive_post_streamlib_sd.ino). Is that right?

Probably my server logic is not that robust than yours which should be

void checkForClient()
{
  EthernetClient client = server.available();
  if (client) {
    ...
    while (client.connected()) {
      while (client.available()) {
        // you: own-grown parsing
        // me: RESTful API server managed by aWOT instead
        char c = client.read();
        ...
      }
    }
  }
}

and is called in loop()

void loop()
{
  checkForClient();          // listen for incoming clients - the "webserver"
  ...
}

yes.
I played around with "manual" setting of CS pins, but in the end I hope I have deleted all of them again.
Both libraries are working hand in hand.

Just in case if you don't need the SD card but use the ethernet, I would recommend to add the pinmode and digitalWrite = HIGH for the ssSD, otherwise an (unused) inserted SD-Card, might block the Ethernet shield.

I don't see yours. But if you feel that my server is working consistently - why not just reuse it as example? If you don't need the NTP it should be very easy to delete the tab and the minor dependencies in the other tabs.

PS: All the struggles I had in the beginning with the SD card + Ethernet were due to low remaining SRAM. Do you have more than 520 bytes remaining?

@noiasca The only difference in our code is that I'm writing the SD card as part of the handling of a RESTful API endpoint request. A short workaround is to delay writing to the SD card to after the endpoint has been triggered.

I didn't digg into your used libraries and how many resources they occupy. But do you still have a lot of SRAM availlabe - more than 520 bytes?

Is your Arduino the API endpoint (server) or does it (client) request data from another server?

Flash is okSketch uses 122348 bytes (23%) of program storage space. How can I check the SRAM quota?

The Arduino is a server.

my ide reports

Sketch uses 29446 bytes (91%) of program storage space. Maximum is 32256 bytes.
Global variables use 1354 bytes (66%) of dynamic memory, leaving 694 bytes for local variables. Maximum is 2048 bytes.

The "leaving" portion is the remaining SRAM.
And you are obviously not on an UNO. Which controller are you using?

What kind of data do you get, can you give me a full example?
Including what data should be extracted to your sd card?

I'm using an Arduino Due.

I'm not able to paste this here... sorry.

I've cross-checked. My server is running perfectly fine. No need to replace my aWOT based server. Without SD-card interaction the server is running perfectly fine.