Arduino (Nano), ENC28J60 and SD Card Reader

Hi all,

I've been trying to connect an ENC28J60 ánd an SD cardreader module to an Arduino Nano on the SPI bus. Both modules work fine but only when the other module is not connected.

Then I found this: SOLVED. Nrf24 (Mirf lib) + Micro SD-card works OK together

I'm pretty sure I have the same problem. The SD card module is probably not playing nice on the SPI bus. The thread is marked as "SOLVED" but not really.

What I've tried:
-- desoldering an SMD pin en bridging it, that ended in one big blob of solder on all the pins and a ruined SD card reader :frowning: I'm not going to try that again.
-- Using "SPI.transfer(0);" after initializing the SD card as suggested in: SOLVED. Nrf24 (Mirf lib) + Micro SD-card works OK together - #7 by chucktodd

Someone suggested using an "Adafruit 254 micro Sd breakout board" that should work out of the box

What is going on and how can I use both an enc28J60 ánd an SD card reader? What card reader should I get? What libraried do I use? Sorry but this is kinda frustrating.

Any help would be most welcome!

This is my curtrent setup and below is my current code:


// ETHERNET ==============================================================
#include <EtherCard.h>
#define TCP_FLAGS_FIN_V   1
#define TCP_FLAGS_ACK_V   0x10

static byte myip[] = { 192,168,1,177 };
static byte gwip[] = { 192,168,1,1 };
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x39 };

byte Ethernet::buffer[200];                                               // tcp ip send and receive buffer

const char indexPage[] PROGMEM =                                              // Hello world webpage
  "HTTP/1.0 200 OK\r\n"
  "Content-Type: text/html\r\n"
  "\r\n"
  "<html>"
    "<body>"
      "<h3>Hello from webserver</h3>"
    "</body>"
;

// SD CARD ===============================================================

#include <SPI.h>
#include <SD.h>

Sd2Card card;                                                             // set up variables using the SD utility library functions
SdVolume volume;
SdFile root;

const int chipSelect = 9;                                                // change this to match your SD shield or module;


// SETUP =================================================================

void setup(){

  Serial.begin(115200);
  while (!Serial);
  Serial << "Hello" << endl;

  // SD CARD =============
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {                            // Initialize and check SD card
    Serial << "SD initialisation failed" << endl;
  }else{
    Serial << "Wiring is correct and a card is present." << endl;
  }

  SPI.transfer(0);                                                         // just activate the SPI SCK for 8 pulses, none of the devices on the bus
                                                                           // have their CS pin low, so there should be no reaction, but sometimes the SD card does not release
                                                                           // the MISO pin until it sees a few clocks, so by sending a null without any CS driven low it tends to 
                                                                           // 'clear' the SPI bus

  if (!volume.init(card)) {                                                // Try to open the 'volume'/'partition' - it should be FAT16 or FAT32
    Serial << "Could not find FAT16/FAT32 partition" << endl;
  }
 
  // ETHERNET ============
  ether.begin(sizeof Ethernet::buffer, mymac , SS);                        // Change 'SS' to Slave Select pin if not using default
  ether.staticSetup(myip, gwip);
  Serial << "end of setup" << endl;
  
} // end setup


// LOOP ==================================================================

void loop(){
    word pos = ether.packetLoop(ether.packetReceive());
    
    if (pos){                                                                                    // check if valid tcp data is received
      
      char* data = (char *) Ethernet::buffer + pos;
      Serial << data << endl;
      if (strncmp("GET / ", data, 6) == 0){
          ether.httpServerReplyAck();                                                             // send ack to the request
          memcpy_P(ether.tcpOffset(), indexPage, sizeof indexPage);                                       // send first packet and not send the terminate flag
          ether.httpServerReply_with_flags(sizeof indexPage - 1,TCP_FLAGS_ACK_V|TCP_FLAGS_FIN_V); 
      }
  }
  
} // end loop```
1 Like

Helpers not having exactly those boards, how would we know the logic is behind the pins in the picture?

You have some debugging serial.prints in setup. What do they tell?
I see no SD card access in loop...
Look out for I/O pins used twice. If both cards use SPI they need different chip select. I se only one, pin 9.

Well, the logic behind those pictures, both boards are:

  • connected to +5v and GND
  • connected on the SPI bus MISO/MOSI/SCK
  • they have their own Chip Select line (orange = ethernet / grey = SD)

The ethercard library uses pin 10 by default, not necessary to specify that:
"ether.begin(sizeof Ethernet::buffer, mymac , SS);" SS is 10 by default

I'll post some additional info later today ok.

I've been trying to figure out how far the code runs. The result is in the updated sketch below. At the end of the setup ether.begin(sizeof Ethernet::buffer, mymac , 10); never completes.

Also in this sketch, both the SD Card and the ENC28J60 work just fine if only one of them is connected.

I've also been searching on this topic and there seem to be a lot of people running into this problem. I didn't come across a solution though.

At this point I have decided not to invest more time into this setup (Arduino, ethernet module and SD card reader). I'm getting a Teensy 4.1 with an ethernet kit and start from there.

Solutions are still welcome. I'm still curious about the problem and there might be others who find this thread in search of a solution.

Thanks.


// ETHERNET ==============================================================
#include <EtherCard.h>
#define TCP_FLAGS_FIN_V   1
#define TCP_FLAGS_ACK_V   0x10

static byte ipAddress[] = { 192,168,1,177 };
static byte gateway[] = { 192,168,1,1 };
static byte netMask[] = { 255,255,255,0 };
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x39 };

byte Ethernet::buffer[200];                                               // tcp ip send and receive buffer

const char indexPage[] PROGMEM =                                              // Hello world webpage
  "HTTP/1.0 200 OK\r\n"
  "Content-Type: text/html\r\n"
  "\r\n"
  "<html>"
    "<body>"
      "<h3>Hello from webserver</h3>"
    "</body>"
;

// SD CARD ===============================================================

#include <SPI.h>
#include <SD.h>

Sd2Card card;                                                             // set up variables using the SD utility library functions
SdVolume volume;
SdFile root;

const int CS_SD = 9;                                                      // change this to match your SD shield or module;


// SETUP =================================================================

void setup(){

  Serial.begin(115200);
  while (!Serial);                                                         // Wait for serial monitor to be opened

  // SD CARD =============
  if (!card.init(SPI_HALF_SPEED, CS_SD)) {                                 // Initialize and check SD card
    Serial << "SD initialisation failed" << endl;
  }else{
    Serial << "Card found, files on card:" << endl;
    volume.init(card);
    root.openRoot(volume);
    root.ls(LS_R | LS_DATE | LS_SIZE);
  }

  SPI.transfer(0);                                                         // just activate the SPI SCK for 8 pulses, none of the devices on the bus
                                                                           // have their CS pin low, so there should be no reaction, but sometimes the SD card does not release
                                                                           // the MISO pin until it sees a few clocks, so by sending a null without any CS driven low it tends to 
                                                                           // 'clear' the SPI bus
 Serial << "Last serial print that gets printed out" << endl;

 // THE CODE BELOW DOS NOT COMPLETE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  // ETHERNET ============
  ether.begin(sizeof Ethernet::buffer, mymac , 10);                        // Change 'SS' to Slave Select pin if not using default
  
  Serial << "This is not printed over serial" << endl;
  
  ether.staticSetup(ipAddress, gateway, NULL, netMask);
  
  Serial << "end of setup" << endl;
  
} // end setup


// LOOP ==================================================================

void loop(){
    word pos = ether.packetLoop(ether.packetReceive());
    
    if (pos){                                                                                    // check if valid tcp data is received
      
      char* data = (char *) Ethernet::buffer + pos;
      Serial << data << endl;
      if (strncmp("GET / ", data, 6) == 0){
          ether.httpServerReplyAck();                                                             // send ack to the request
          memcpy_P(ether.tcpOffset(), indexPage, sizeof indexPage);                                       // send first packet and not send the terminate flag
          ether.httpServerReply_with_flags(sizeof indexPage - 1,TCP_FLAGS_ACK_V|TCP_FLAGS_FIN_V); 
      }
  }
  
} // end loop```

As your link describes, the problem is that the typical microSD module does not release the MISO line when it is not selected by CS. So it interferes with the other SPI device when it tries to send data to the processor. In electronics terms, the MISO line is sent through the voltage shifter, and is therefore always either high or low when it really should be HZ (not connected). The Adafruit modules do this correctly, which means they connect the SD card's output pin directly to the MISO header on the module, and bypass the level shifter. Then the SD card itself will tri-state MISO when its CS line is not asserted. The fix I use is shown below. You solder one wire, and cut one trace. With any luck, your module layout will be the same.

Thanks for the info and picture, I had not seen this option before. I'll try this today and hope it's not gonna end up like the mess I made on my previous attempt.

Awesome, it worked!

The soldering was more doable then my previous soldering mod. Soldering did require a carefully
planned soldering setup and a magnifier though.

To conclude:

-- These el cheapo SD card boards have wrong wiring/routing.
-- The typical microSD module does not release the MISO line (ShermanP, in the post above).
-- To fix it some re-soldering is required (see image below)
-- The Adafruit modules do this correctly (ShermanP, in the post above)
Adafruit Micro-SD breakout board:
"Introduction | Micro SD Card Breakout Board Tutorial | Adafruit Learning System"

The fixes:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.