Pages: [1]   Go Down
Author Topic: Arduino Ethernet/Etherten + NFC Shield - chip select/SPI issues? [SOLVED]  (Read 1760 times)
0 Members and 1 Guest are viewing this topic.
Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm new to Arduino programming and despite lots of great online resources I'm a bit stuck on this, my first project. Hopefully you may be able to help.

I'm trying to stack the NFC shield v2.0 (http://www.seeedstudio.com/depot/nfc-shield-v20-p-1370.html?cPath=132_134) with an Arduino EtherTen (http://www.freetronics.com/products/etherten#.UhORk_myyO4).

The project is to read a MiFare card and send the card ID to a web server for logging.

I had very little success trying to do this with an official Arduino Ethernet board and from what I've read so far it's because the Ethernet and NFC both use pin 10 and also need to share the SPI bus which the Ethernet chip doesn't do properly.

I thus ordered the EtherTen as Freetronics claim to have "Fixed SPI behavior on Ethernet chipset."

The NFC shield and libraries from Seeedstudio have the option to use pin 9 for the NFC and so I've set this in the code and also re-soldered the SS pad to pin 9 instead of pin 10.

This has got me further than ever before in that both Ethernet and the NFC shield seem to initialize correctly but I still can't get the two to work at the same time.

Here's my test code so far:

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

/*Chip select pin can be connected to D10 or D9 which is hareware optional*/
/*if you the version of NFC Shield from SeeedStudio is v2.0.*/
#define PN532_CS 9
PN532 nfc(PN532_CS);

/* Network Settings */
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x3B, 0xB9 }; // MAC address
IPAddress ip(192,168,0,10);       // Static IP if DHCP fails
IPAddress server(74,125,232,128);  // IP for Google
EthernetClient client;

/* Startup routine */
void setup(void) {

  /* Start serial output */  
  Serial.begin(57600);
  Serial.println("Arduino Powered On");
  
  /* Initialise Network */
  Serial.println("Sending DHCP request");
  if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      Serial.println("Setting static IP address instead");
      Ethernet.begin(mac, ip);
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());
    }
    else {
      Serial.println("Obtained DHCP lease");
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());    
    }
  
  /* Initialise NFC reader */
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  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);
  nfc.SAMConfig();
  
  /* Configure web client */
  if (client.connect(server, 80)) {
    Serial.println("Connected to web server");
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("Connection failed");
  }

}

/* Main program loop */
void loop(void) {

  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println("Disconnecting");
    client.stop();
    while (1); // halt
  }
  
  /* look for MiFare type cards */
  uint32_t id;
  id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
  if (id != 0) {
    Serial.print("Read card #");
    Serial.println(id);
  }
  
}

This outputs:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 192.168.0.10
Found chip PN532
Firmware ver. 1.6
Supports 7
Connection failed
Disconnecting

So it seems the ethernet works fine until the NFC reader is started. Indeed, if I comment out the section under /* Initialise NFC reader */ the serial monitor then shows the Google search.

I also tried using pin 10 (changing the solder pads again) but that simply returns:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 192.168.0.10
Didn't find PN53x board

Can anyone help point me in the right direction? I'm at a loss at what to try next.
« Last Edit: August 23, 2013, 11:26:06 am by empoit » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5851
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I had very little success trying to do this with an official Arduino Ethernet board and from what I've read so far it's because the Ethernet and NFC both use pin 10 and also need to share the SPI bus which the Ethernet chip doesn't do properly.
That is not correct. It shares the SPI bus with the SD and most other devices. You must have separate slave select pins for the sharing to be effective. That means the w5100 slave select is on D10, and your NFC will need to use another slave select pin.
Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks SurferTim. Sounds like moving the NFC SS to pin 9 was a step in the right direction but unfortunately that still is not working as shown above. Am I missing something here?
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5851
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I try the SPI devices one at a time. Try the ethernet shield code first.
Code:
void setup() {
  Serial.begin(9600);

  // disable NFC SPI for a test
  pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);

  // disable SD if one in the slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

// now your ethernet stuff and the rest
}

I use these. You did not mention if it is a client or server, so here are both my example sketches.
http://playground.arduino.cc/Code/WebClient
http://playground.arduino.cc/Code/WebServerST
Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks again for your help. I was planning to do this as a web client. The example sketch you linked works perfectly.

The web client code in my sketch also works if I comment out the NFC code under "Initialise NFC reader" and the NFC reader code works if I comment out the "Configure web client" part of my sketch. The only problem is they won't work together.

There's no SD card in the slot but I tried adding the code to disable NFC SPI at the beginning of the setup() routine. This gave the serial output as before:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 148.88.167.38
Found chip PN532
Firmware ver. 1.6
Supports 7
Connection failed
Disconnecting

I then tried disabling the NFC SPI after the "Initialise NFC reader" section but before the "Configure web client" section but I just get the above output again.

It seems that once the NFC code has been called the web client will no longer work.

As a test I added the following after the "Initialise NFC reader" section:

Code:
Serial.print("Arduino IP is ");
Serial.println(Ethernet.localIP());

This time it returns:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 192.168.0.10
Found chip PN532
Firmware ver. 1.6
Supports 7
Arduino IP is 192.192.192.192
Connection failed
Disconnecting

So it seems just calling the NFC code is trashing the ethernet configuration.


Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK I think I've got it. Looking at this previous thread which is pretty much the same issue: http://forum.arduino.cc/index.php?topic=102331.0

Looks like jmgjmg has come up with a solution:

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 https://github.com/jmgjmg/PN532. 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.

I used the example code provided but changed the NFC_SS to pin 9 to match the change I've already made on the Seeedstudio NFC v2.0 shield. It works!

I didn't need to do any of the rewiring suggested. I've simply fitted the NFC v2.0 shield on top of the Freetronics EtherTen connecting all header pins including the SPI pins.

What I'm not sure on is whether this would work with the official Arduino Ethernet board - I have one so will try that and report back tomorrow.

I see you were active in that thread too SurferTim - many thanks for your help and to jmgjmg should he see this thread.

« Last Edit: August 20, 2013, 01:33:49 pm by empoit » Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scratch that - it doesn't work. Although both ethernet and NFC appear to be working the Mifare card ID that is 'read' from the card is incorrect.

For test Mifare card number 1 I get:

Code:
Found 1 tags
Sens Response: 0x300
Sel Response: 0x0
 0x0 0x4 0x0 0x1 0x3 0x4 0x0
End NFC read
Read card #16974848
Converted String: 0016974848

But test card number 2 just gives:
Code:
Found 1 tags
Sens Response: 0x0
Sel Response: 0x0
End NFC read

Interestingly the actual IDs of these cards when read using the demo NFC sketch (with no Ethernet component) are:

Test card number 1:

Code:
Found 1 tags
Sens Response: 0x344
Sel Response: 0x20
 0x4 0x86 0x20 0x29 0x93 0x26 0x80
Read card #697509504

Test card number 2:
Code:
Found 1 tags
Sens Response: 0x4
Sel Response: 0x8
 0xF2 0xF7 0xB5 0x60
Read card #4076320096

So something isn't right. It would seem the problem lies in the Seeedstudio NFC library (PN532.h) but I don't understand enough to debug that.

Is there anything else I could try here?



Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5851
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That NFC shield uses the ICSP connector for the SPI data lines. D10 is normally the NFC slave select, same as the w5100. That would cause problems.
http://www.seeedstudio.com/wiki/NFC_Shield_V2.0

If you decide to use this with an ethernet shield rather than an Arduino with built-in ethernet, the NFC shield must be "sandwiched" between the Arduino and the ethernet shield.

I see from your code you did not disable the other SPI devices before starting the ethernet shield. That could not only cause problems for the w5100, but the startup communication for the w5100 could also be received by the NFC shield. That could cause it to malfunction when you try to start it.
Code:
Serial.begin(57600);
  Serial.println("Arduino Powered On");
  
  // disable the NFC SPI here
  pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);

  /* Initialise Network */
  Serial.println("Sending DHCP request");
  // rest of your stuff.

edit: The NFC shield SPI bus is not the same settings as the w5100. Here is jmgjmg's code to show that. The NFC is LSBFIRST and the w5100 is MSBFIRST. You must switch SPI settings before using the NFC shield and change them back when using the w5100. This shows how.
https://github.com/jmgjmg/PN532/blob/master/PN532.cpp
« Last Edit: August 20, 2013, 02:29:10 pm by SurferTim » Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks SurferTim, it's still not working but I'm starting to understand a bit better.

I know the D10 is normally the NFC slave select which is why I moved that to D9. There's an option to do so by simple re-soldering of the pads on the Seeedstudio NFC v2.0 shield and by setting it to pin 9 in the example code.

I hadn't heard of SPI before I started this project and I realised I didn't really understand that part of your post so I found a couple of YouTube clips which helped there. Others in a similar position might try searching YouTube for "SPI explained".

Hopefully with a better understanding I've rewritten my sketch as follows:

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

/*Chip select pin can be connected to D10 or D9 which is hareware optional*/
/*if you the version of NFC Shield from SeeedStudio is v2.0.*/
#define PN532_CS 9
#define ETHNET_CS 10
#define SDCARD_CS 4
PN532 nfc(PN532_CS);

/* Network Settings */
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x3B, 0xB9 }; // MAC address
IPAddress ip(192,168,0,10);       // Static IP if DHCP fails
IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
EthernetClient client;

/* Chip select routine */
void spiSelect(int CS) {
  // disable all SPI
  pinMode(PN532_CS,OUTPUT);
  pinMode(ETHNET_CS,OUTPUT);
  pinMode(SDCARD_CS,OUTPUT); 
  digitalWrite(PN532_CS,HIGH);
  digitalWrite(ETHNET_CS,HIGH);
  digitalWrite(SDCARD_CS,HIGH);
  // enable the chip we want
  digitalWrite(CS,LOW); 
}

/* Startup routine */
void setup(void) {

  /* Start serial output */   
  Serial.begin(57600);
  Serial.println("Arduino Powered On");

  // disable the NFC and SD card SPI here so just network is active
  spiSelect(ETHNET_CS);
 
  /* Initialise Network */
  Serial.println("Sending DHCP request");
  if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      Serial.println("Setting static IP address instead");
      Ethernet.begin(mac, ip);
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());
    }
    else {
      Serial.println("Obtained DHCP lease");
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());     
    }
 
  /* Configure web client */
  if (client.connect(server, 80)) {
    Serial.println("Connected to web server");
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("Connection failed");
  }
 
  // disable the ethernet and SD card SPI here so just NFC is active
  spiSelect(PN532_CS);
 
  /* Initialise NFC reader */
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  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);
  nfc.SAMConfig();
 
}

/* Main program loop */
void loop(void) {

  // disable the ethernet and SD card SPI here so just NFC is active
  spiSelect(PN532_CS);
   
  /* look for MiFare type cards */
  uint32_t id;
  id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
  if (id != 0) {
    Serial.print("Read card #");
    Serial.println(id);   
  }
 
  // disable the NFC and SD card SPI here so just network is active
  spiSelect(ETHNET_CS);
   
  // check ethernet is still working
  Serial.print("Arduino IP is ");
  Serial.println(Ethernet.localIP());
 
}

This now seems to read the cards correctly but it still breaks the ethernet connection once the NFC code has been run. Output is as follows:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 192.168.0.10
Connected to web server
Found chip PN532
Firmware ver. 1.6
Supports 7
Arduino IP is 192.192.192.192
Found 1 tags
Sens Response: 0x344
Sel Response: 0x20
 0x4 0x86 0x20 0x29 0x93 0x26 0x80
Read card #697509504
Arduino IP is 192.192.192.192
Arduino IP is 192.192.192.192
[etc]

I've tried running jmgjmg's libraries and example but that doesn't work either - presumably because I didn't do the necessary rewiring in his readme file. I've read through the instructions but I'm struggling to follow the wiring notation.

It sounds like the NFC being LSBFIRST and the w5100 MSBFIRST would be pretty fundamental to getting this to work and it must be possible to tweak my code to do so but it's still a bit beyond my understanding at this stage.

Presumably the PN532 library (as provided by Seeedstudio: http://www.seeedstudio.com/wiki/NFC_Shield_V2.0) switches SPI to LSBFIRST and I need to switch it back to MSBFIRST when changing back to ethernet?

Again, thanks for all the help and any new ideas also welcome.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5851
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That should be easy to do. I've used the SPI commands to change modes before with devices that use different modes. This is what I would try.
Code:
SPI.setBitOrder(LSBFIRST);
// do your NFC stuff
SPI.setBitOrder(MSBFIRST);
// now you are ready to use the w5100

I try to leave the SPI bus set to default after each SPI access. That is MODE0 and MSBFIRST.
Logged

Lancaster, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It works! Fantastic - I can't believe one line of code was all that was needed.

Thanks for all your help SurferTim. I'd never have figured this out.

I'm still working on my sketch to complete the project but I'll post the test code now in case others find it useful.

Working example:

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

/*Chip select pin can be connected to D10 or D9 which is hareware optional*/
/*if you the version of NFC Shield from SeeedStudio is v2.0.*/
#define PN532_CS 9
#define ETHNET_CS 10
PN532 nfc(PN532_CS);

/* Network Settings */
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x3B, 0xB9 }; // MAC address
IPAddress ip(192,168,0,10);       // Static IP if DHCP fails
IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
EthernetClient client;

/* Chip select routine */
void spiSelect(int CS) {
  // disable all SPI
  pinMode(PN532_CS,OUTPUT);
  pinMode(ETHNET_CS,OUTPUT);
  digitalWrite(PN532_CS,HIGH);
  digitalWrite(ETHNET_CS,HIGH);
  // enable the chip we want
  digitalWrite(CS,LOW); 
}


/* Startup routine */
void setup(void) {

  /* Start serial output */   
  Serial.begin(57600);
  Serial.println("Arduino Powered On");

  // disable the NFC SPI here so just network is active
  spiSelect(ETHNET_CS);
 // ethernet uses the default MSB first so making sure that is set
  SPI.setBitOrder(MSBFIRST);
 
  /* Initialise Network */
  Serial.println("Sending DHCP request");
  if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      Serial.println("Setting static IP address instead");
      Ethernet.begin(mac, ip);
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());
    }
    else {
      Serial.println("Obtained DHCP lease");
      Serial.print("Arduino IP is ");
      Serial.println(Ethernet.localIP());     
    }
 
  /* Configure web client */
  if (client.connect(server, 80)) {
    Serial.println("Connected to web server");
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("Connection failed");
  }
 
  // disable the ethernet SPI here so just NFC is active
  spiSelect(PN532_CS);
 // NFC uses LSB first so we have to explicitly set that
  SPI.setBitOrder(LSBFIRST);
 
  /* Initialise NFC reader */
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  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);
  nfc.SAMConfig();
 
}

/* Main program loop */
void loop(void) {

  // disable the ethernet SPI here so just NFC is active
  spiSelect(PN532_CS);
 // NFC uses LSB first so we have to explicitly set that
  SPI.setBitOrder(LSBFIRST);
   
  /* look for MiFare type cards */
  uint32_t id;
  id = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);
  if (id != 0) {
    Serial.print("Read card #");
    Serial.println(id);   
  }
 
  // disable the NFC SPI here so just network is active
  spiSelect(ETHNET_CS);
 // ethernet uses the default MSB first so we need to switch back
  SPI.setBitOrder(MSBFIRST);
   
  // check ethernet is still working
  Serial.print("Arduino IP is ");
  Serial.println(Ethernet.localIP());
 
}

The output from this is:

Code:
Arduino Powered On
Sending DHCP request
Obtained DHCP lease
Arduino IP is 192.168.0.10
Connected to web server
Found chip PN532
Firmware ver. 1.6
Supports 7
Arduino IP is 192.168.0.10
Found 1 tags
Sens Response: 0x344
Sel Response: 0x20
 0x4 0x86 0x20 0x29 0x93 0x26 0x80
Read card #697509504
Arduino IP is 192.168.0.10
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I hope someone will see my new answer...

I had a lot of trouble to understand everything, now, my arduino can see the NFC and the eternet shields, but.....
when I start the sketch, everythin is ok ( connected to web server, Found chip PN520..), when I put a tag on the NFC shield, something is happening, but not everything :
Found 1 tags
Sens Response: 0x0
Sel Response: 0x0
and the id of the tag is 0, so no card reading !!!!!
Did I miss something ?

Logged

Pages: [1]   Go Up
Jump to: