Is the SPI bug in W5100 solved in the new Ethernet shield?

Hi,
I am using Arduino Uno with latest Ethernet shield (rev 3) http://store.arduino.cc/eu/index.php?main_page=product_info&cPath=11&products_id=199 and RFID shield from seeedstudio http://www.seeedstudio.com/depot/nfc-shield-p-916.html?cPath=132_134.
Both shields use SPI and I have read several posts about the buggy implementation of Wiznet W5100 MISO and Arduino Ethernet Shields « John's Ramblings (bug descibed here http://www.wiznet.co.kr/UpLoad_Files/ReferenceFiles/W5100_AN_SPI.pdf).
I am not able to get Ethernet and RFID working together if they are sharing SPI PINs: I use PIN10 (CS/SS) to select Ethernet/Wiznet and PIN5(CS/SS) for RFID/SeeedStudio/NXP doing some rewiring. I reuse PINs 11,12 &13 for MOSI, MISO and SCK between Ethernet and RFID. RFID is working fine until I activate Ethernet and then it stops working. Do you know if the W5100 bug has been corrected in the latest version of Etheret shield (i.e.is SEN PIN of W5100 connected through an inverter to SS digital input of PIN 10)?

I have been able to get this working using completely separate PINS for SPI in RFID (PINS 2,3,5,9) but then I run out of digital PINs for my project.

Thanks for your help!

I use the w5100 with the onboard microSD card with no problems. Both are SPI. I don't think the problem is with the new ethernet shields, but with the w5100 library code.

The ethernet library does have one quirk. When you call Ethernet.begin(), the function returns with the w5100 SPI enabled. This will cause grief with any other SPI device, especially the SD card. I also disable the SD SPI to prevent any chance of bus corruption from it.

void setup()
{
   Serial.begin(9600);

   // Sprinkle some magic pixie dust. (disable SD SPI)
   pinMode(4,OUTPUT);
   digitalWrite(4,HIGH);

   // disable your new SPI until the w5100 is set up
   pinMode(5,OUTPUT);
   digitalWrite(5,HIGH);
      
   // set up w5100
   Ethernet.begin(mac,ip);
   // disable w5100 SPI
   digitalWrite(10,HIGH);

   // rest of your setup code
}

If you still have problems with it, maybe you should post your code.

edit: Jeez! Nobody reads this? I had the mac and ip reversed in the Ethernet.begin call. :blush:
I added disabling your new device SPI while you set up the w5100.

Thanks SurferTim!
I do manage SPI select/deselect of Ethernet, SD card and NFC through digital PINs 10, 4 and 5.
I stack the Ethernet shield on top of Arduino Uno and then I wire the required PINs to the SeeedStudio NFC shield (also to the ICSP PINS of the NFC shield).

If I reuse the three SPI PINs (11,12 & 13) in the NFC shield, the NFC shield stops reading tags as soon as I select the Ethernet chip for the first time (even when I deselect it afterwards - PIN10.HIGH).

However if I use three different digital PINs for NFC shield (3,6 & 9), the NFC shield keeps working and reading tags after the selection of Ethernet chip. In fact I can read tags and then send the data to my server.
That is why I wonder if the bug of W5100 SPI selection is still there.
See my code attached:

#include <PN532.h>
#include <SPI.h>
#include <Ethernet.h>

#define SCK 9  //13
#define MOSI 3 //11
#define SS 5
#define MISO 6 //12


PN532 nfc(SCK, MISO, MOSI, SS);

byte mac[] = {  0x90, 0xA2, 0xDA, 0xDA, 0xDA, 0xDA };
EthernetClient client;


unsigned long time;
unsigned long responseTime;

uint32_t tagId=0;
uint32_t flowState =0;

#define STATE_IDDLE 0
#define STATE_SENDDATA 15
#define STATE_RESPONSE 20


void setup()
{
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  time = millis();
  Serial.begin(19200);
  Serial.println("Starting setup method...");
  //Initialise NFC reader
  nfc.begin();
  nfc.RFConfiguration(0x14); // default is 0xFF (try forever; ultimately it does time out but after a long while
                             // modifies NFC library to set up a timeout while searching for RFID tags
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    // stop
    for(;;);
  }
  // ok, print received data!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  Serial.print("Supports "); Serial.println(versiondata & 0xFF, HEX);
  // configure board to read RFID tags and cards
  nfc.SAMConfig();
 
  //Initialise Ethernet connection
  Serial.println("StartEthernet");
  digitalWrite(5, HIGH); //SPI deselect RFID reader
  digitalWrite(10, LOW); //SPI select Ethernet
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // stop
    for(;;);
  }
  
  // give the Ethernet shield a second to initialize:
  delay(1000);
  digitalWrite(10, HIGH); //SPI deselect Ethernet

  Serial.println("NFC and Ethernet initialised OK");   
  flowState=STATE_IDDLE;
  delay(2000);
}



void loop()
{ 

  if ((millis()-time > 1000)&&(flowState==STATE_IDDLE)) {
      Serial.println("Checking NFC...");
    // look for Mifare type cards every second
    time=millis();
    digitalWrite(10, HIGH);//SPI deselect Ethernet
    digitalWrite(5, LOW);//SPI select RFID reader
    tagId = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
    digitalWrite(5, HIGH);//SPI deselect RFID reader
    digitalWrite(10, LOW);//SPI select Ethernet
    if (tagId != 0) 
    { 
      Serial.print("Read card #"); Serial.println(tagId);
      time=millis();
      flowState=STATE_SENDDATA;
      return;
     }
  }   


  if (flowState==STATE_SENDDATA) {
      Serial.println("Connecting to server ...");
      // if you get a connection, report back via serial:
      if (client.connect("myserver", 80)) { //fill in your server ip address/URL and port
          Serial.println("Connected. Making GET http request");
          // Make a HTTP request:
          client.print("GET /TestServlet?TagId=");
          client.println(tagId);
          client.println(" HTTP/1.1");
          client.println();
          responseTime=millis();
          flowState=STATE_RESPONSE;
      }  else {
          Serial.println("Connection to server failed");
          flowState=STATE_IDDLE;
      } 

  }


  
  if (flowState== STATE_RESPONSE) {

    if (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
    if ((millis() - responseTime)>2000) {
        Serial.println();
        Serial.println("Closing connection to server");
        client.stop();
        flowState=STATE_IDDLE;
    }
  }
  
}

The ICSP pins are the SPI data lines for the Uno and Mega interface to the ethernet shield.

If I reuse the three SPI PINs (11,12 & 13) in the NFC shield, the NFC shield stops reading tags as soon as I select the Ethernet chip for the first time (even when I deselect it afterwards - PIN10.HIGH).

However if I use three different digital PINs for NFC shield (3,6 & 9), the NFC shield keeps working and reading tags after the selection of Ethernet chip. In fact I can read tags and then send the data to my server.
That is why I wonder if the bug of W5100 SPI selection is still there.

I am not certain about the NFC shield code. You need not manage the SPI SS pins for the w5100 nor the SD card. Those are managed by the low level read/write routines in the libraries. That is why you must disable the w5100 SS pin (digital 10). Once you do that, all SPI SS pins are HIGH, and you can select the proper SS pin to communicate with that device.

If the NFC shield does not manage its SS pin (digital 5), then that could be a problem, but not due to the SPI bus. That would be a code error in the NFC library. And that would also explain why it would work with different pins for the SPI data lines and not with the standard SPI bus.

I am just a beginner but it sounds strange: even if the NFC shield does not handle SS properly, I am setting it LOW just before calling NFC functions so that should not be an issue (and when I use different MOSI/MISO/SCK pins everything works fine).

I am sure that there must be a technical reason beyond my understanding and an easy way to solve it. For all those that want a quick fix, I attach the comments explaining how I got it working.
It does not require any HW or SW update but the wiring is a bit cumbersome (probably some of the wires are not needed but this wiring works :slight_smile:

#define SCK 9   
#define MOSI 3 
#define SS 5
#define MISO 6  
// SPI digital PINs are HW hardcoded in both Ethernet and NFC shields (SS - 10, MOSI - 11,  MISO - 12, SCK - 13
// Do not know why, but using a different SS PIN for NFC shield (PIN 5) and reusing the other three PINs(11,12,13) does not work. As soon as Ethernet shield is used
// (PIN 10 set to LOW) the NFC shield stops reading tags. 
// Using completely independent PINS for NFC shield (5, 3, 6, 9) works fine and no interference is detected between the two shields.
//
// Connect the Ethernet shield on top of Arduino Uno to get ICSP PINs 
// Both shields use the ICSP PINs for SPI protocol (rather than the actual digital PINs). Since the NFC shield ICSP PINS are unconnected, they need to be wired to the  
// appropriate digital PINs in the NFC shield.
//
// This is the required wiring:
//   * wire RESET, 3,3V, 5V, GND, GND, Vin female PINS from the Ethernet shield to equivalent male PINs in NFC shield
//   * wire digital female PINs in the Ethernet shield to male digital PINs in NFC shield:
//            5  (Ethernet)  -> 10 (NFC)  SS
//            3  (Ethernet)  -> 11 (NFC)  MOSI
//            6  (Ethernet)  -> 12 (NFC)  MISO
//            9  (Ethernet)  -> 13 (NFC)  SCK
//
//   * wire female ICSP PINs of NFC shield with the appropriate female PINs of NFC shield:
//            MISO (ICSP)  -> 12 
//            SCK  (ICSP)  -> 13
//            MOSI (ICSP)  -> 11
//            Vcc  (ICSP)  -> 5V (This is the 5 Volts power PIN; do not connect it by mistake to digital PIN 5) 

PN532 nfc(SCK, MISO, MOSI, SS);

Are you setting it HIGH when you are finished? Most successful routines use something like this:

// enable the NFS SPI
digitalWrite(5,LOW)
// do all transfer functions here
SPI.transfer(byte);
// disable NFS SPI
digitalWrite(5,HIGH);

Yes I do deselect it by setting it to HIGH

Post your code.

Code is included in my second post above/below

Fair enough. What is the last message on the serial monitor during the fail?

No problem.
When I use separate PINs (5, 3, 6, 9) I get the following two text messages in every loop:

Checking NFC...
Found 0 tags

The first line is generated by my code and the second one by the NFC library.

When I put one RFID tag on the reader, I get the message "Found 1 Tag" and then my code continues with the Ethernet/http connection to my server without any issue. Finally my application goes back to the NFC reading loop after closing the connection.

When I reuse SPI PINs (5,11,12,13) I only see one text line in every loop (no text line from the NFC library); no tag is detected by the NFC reader:

Checking NFC...

I downloaded NFC library from the wiki of SeeedStudio: NFC Shield | Seeed Studio Wiki
http://www.seeedstudio.com/wiki/images/2/25/PN532_SPI_V1.zip

Things have changed with v1.0. I would like to help you get the bug out of this if we can. The code looks ok, but that can be deceiving. Add a couple serial outputs to the code.

    digitalWrite(5, LOW);//SPI select RFID reader
    Serial.println("Start NFC read");
    tagId = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
    Serial.println("End NFC read");
    digitalWrite(5, HIGH);//SPI deselect RFID reader

Now what is the last message?

Many thanks SurferTim!
Good try :wink: before entering into debugging the actual NFC library. Unfortunately the outcome of your code indicates that the issue appears within the NFC library code.
I think that we can stop the debugging for a while and see if somebody else has experienced similar issues with other SPI shields when used together with the Ethernet shield. That can give a hint about where the culprit is.

With disjoint SPI PINs:

Checking NFC...
Start NFC read
Found 0 tags
End NFC read

With shared SPI PINs:

Checking NFC...
Start NFC read
End NFC read

I had some time to dig into this issue and found the cause of the problem. Nothing to do with Ethernet shield but with Seeedstudio NFC library (PN532.h).
This library is using a SW implementation of SPI protocol, not the HW implementation of the official Arduino SPI.h library used by Ethernet shield.
Unfortunately the SW implementation is not compatible with the HW implementation and when you use them together and try to share the SPI pins (MISO/MOSI/SCK) it does not work.
I created an updated PN532 library that uses HW SPI and uploadaded it to GitHub - jmgjmg/PN532: Arduino Library for Seeedstudio NFC Shield based on NXP PN532 chip. Now you can use Ethernet and NFC shields sharing the three SPI PINs. See detailed instructions in readme file.

Unfortunately, this library does not work when you stack three SPI shields together. There is too much noise in the SPI lines and the data transmission becomes unreliable.