PN532 NFC Library [PORTED]

Thanks for the update! That kind of support would be the bomb haha.

I did manage to get a hack working this weekend that involved an Arduino Uno + Spark Core :stuck_out_tongue:
@BDub If I would like to learn how to port libraries, where could I start?

There are lots of examples of libraries that have been ported... that would be a good start to compare to the originals. There is currently no tutorial for "how"... just a TON of forum posts that help to answer questions.

If you start porting a library, and get an error... check those keywords with a forum search, and a google search. Try to understand the error, and ask yourself "why does this work on Arduino, but not on the Spark Core?".

We have also been talking about doing some tutorials on this, and the best way to present the information.

@BDub,

Has this library been updated and bugs fixed? :smiley:

Need it for an upcoming prototype demo and Iā€™m so gonna need this! Our country has tons of NFC/RFID cards everywhere. :smiley:

Sadly the :spark: nfc shield hasnā€™t shown up quick enough for me to buy!

Sadly, I worked on work stuff all day today (Saturday). PIC microcontroller stuff. It was fun actually because it was the first time in a while that I got to code in C for work. Usually Iā€™m coding in assembly. Whatā€™s not fun is that I got up at 7:30 and I worked til midnight. Butā€¦ itā€™s done, commented and tested to death. Code review Monday morning.

That said, I keep looking at this NFC reader that I have and want to get it going badly. I just need a few hours to mess with it now. I might be able to get to it tomorrow night.

Itā€™s already Sunday afternoon 1.32pm here :D.

So Iā€™m gearing up with plans for the week to work out the 1st demo! :smiley:

Well have some good rest and I hope you have time to get it working. :horse:

BDub, let me if I can help in any way :smiley:

1 Like

I got my NFC shield soldered up and got the adafruit libraries for arduino. It works like magic on my UNO R3ā€¦ and Iā€™m noticing some issues that could be a problem. 1) The NFC Shield supposedly only works on I2C (NFC breakout is SPI) 2) The NFC Shield has I2C pins in a special place that UNO R3 has available, but not the Spark Shield Shield. 3) The library I ported is SPI. 4) Itā€™s 12:54am and itā€™s time for bed again! Why canā€™t I be a robot??? Being mortal is a real pain in the ass sometimes.

2 Likes

Edit: So immediately after posting, it works. I guess this post might now have some utility as a ā€˜how toā€™!

Hi BDub.
Finally back home after a few months on the road, ready to snuggle up to my SC. Thanks again for your wizardry on this subject.

Iā€™ve got everything setup (as best I canā€¦) - seem to have bumped into some issues:

Code I am using as follows:

Hardware I am using as as follows:

Using your Serial Debugging Over USB tweak - works a treat, but it reports it canā€™t find the module (which does in the very least get its LED powered upā€¦)

Thanks in advance, again
Simon

1 Like

Ok I did some testing on this library that I ported a week ago or soā€¦ (the Elechouse library)ā€¦ and I had to tweak the example code to get it to work reliably. I had the same problem with connecting to the NFC chip. Even after connecting though, I determined that their examples for detecting a card were not as good as the Adafruit examples and library. The way adafruit does it, they look for an IRQ output when the card is present. This is a much better approach, rather than polling the reader repeatedly.

My plans would be to scrap the elechouse library and port the adafruit I2C and SPI NFC libraries to the Spark Core. Then create a nice example that responds to the card being present, and latches an LED on. Even the adafruit library will repeatedly report that a card is present if you leave the card on the readerā€¦ but it seems easier to adapt that output to latching a condition such as opening a door latch solenoid for a brief period to allow entry for example.

There are also some issues I noticed when hooking up the adafruit NFC shield to the Spark Shield Shield, but I figured them out and will have to document that as well. The Elechouse breakout is arguably cheaper than the Adafruit solution, but the Adafruit library should work for both boards so it should be a moot point.

Iā€™m not sure when I can get to this though, so Iā€™ll leave my test code here to help you along with the library as Iā€™ve ported it thus far. If you look at the setup() routine you can see what changes Iā€™ve made to get the card to connect. It will usually not connect the first try, but will connect on the second try. I didnā€™t track down the root cause of this, but maybe there just needs to be a delay before connecting? I didnā€™t have this problem with the adafruit library though so shrug this is why Iā€™m also leaning towards their library.

/**
  @file    nfc_mifare_mf1s50_reader.ino
  @author  www.elechouse.com
  @brief   example of reading mf1s50 card for NFC_MODULE
  
    For this demo, waiting for a MF1S50 card or tag, after reading a card/tag UID,
    then try to read the block 4/5/6/7 ..
  
  @section  HISTORY
  
  V1.0 initial version
  
    Copyright (c) 2012 www.elechouse.com  All right reserved.
*/

/** include library */
#include "application.h"

#include "nfc.h"

/** define a nfc class */
NFC_Module nfc;

void setup(void)
{
  Serial.begin(115200);
  while(!Serial.available()) SPARK_WLAN_Loop(); // Keep cloud connected while waiting for Serial input
  nfc.begin();
  Serial.println("MF1S50 Reader Demo From Elechouse!");
  
  uint32_t versiondata;
  do {
    versiondata = nfc.get_version();
    if (!versiondata) {
      Serial.print("Didn't find PN53x board");
      delay(1000);
      SPARK_WLAN_Loop(); // keep cloud connected
    }
  }
  while(!versiondata);
  
  // Got ok data, print it out!
  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);
  
  /** Set normal mode, and disable SAM */
  nfc.SAMConfiguration();
}

void loop(void)
{
  u8 buf[32],sta;
  
  //delay(3000);
  /** Polling the mifar card, buf[0] is the length of the UID */
  sta = nfc.InListPassiveTarget(buf);
  
  /** check state and UID length */
  if(sta && buf[0] == 4){
    /** the card may be Mifare Classic card, try to read the block */  
    Serial.print("UUID length:");
    Serial.print(buf[0], DEC);
    Serial.println();
    Serial.print("UUID:");
    nfc.puthex(buf+1, buf[0]);
    Serial.println();
    /** factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF */
    u8 key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
    u8 blocknum = 4;
    /** Authentication blok 4 */
    sta = nfc.MifareAuthentication(0, blocknum, buf+1, buf[0], key);
    if(sta){
      /** save read block data */
      u8 block[16];
      Serial.println("Authentication success.");
      
      // uncomment following lines for writing data to blok 4
/*      
      strcpy((char*)block, "Elechoues - NFC");
      sta = nfc.MifareWriteBlock(blocknum, block);
      if(sta){
        Serial.println("Write block successfully:");
      }
*/  

      /** read block 4 */
      sta = nfc.MifareReadBlock(blocknum, block);
      if(sta){
        Serial.println("Read block successfully:");
        
        nfc.puthex(block, 16);
        Serial.println();
      }
      
      /** read block 5 */
      sta = nfc.MifareReadBlock(blocknum+1, block);
      if(sta){
        Serial.println("Read block successfully:");
        
        nfc.puthex(block, 16);
        Serial.println();
      }
      
      /** read block 6 */
      sta = nfc.MifareReadBlock(blocknum+2, block);
      if(sta){
        Serial.println("Read block successfully:");
        
        nfc.puthex(block, 16);
        Serial.println();
      }
      
      /** read block 7 */
      sta = nfc.MifareReadBlock(blocknum+3, block);
      if(sta){
        Serial.println("Read block successfully:");
        
        nfc.puthex(block, 16);
        Serial.println();
      }
    }  
  }
}

@BDub Iā€™m still having some trouble getting my shield to work (Itā€™s the same as @simon) - Do you know how I change the data pins to any pin?
EDIT: just realized I2C is hardwired to certain pins. http://docs.spark.io/#/hardware shows that D0/D1 is used for I2C and A2/A3/A4/A5 is used for SPI. Has anyone had more luck with one over the other?

Can you help me understand what these are doing on line 97 and 105 of the nfc.cpp? It would be cool to learn how to convert those hex values to pin numbers.

(I should have asked you guys in person when I had the chance!)

That elechouse library I ported is I2C only at the moment. I donā€™t want to continue supporting it though, as I think the Adafruit NFC libraries for I2C and SPI are better. We can also implement a Soft SPI mode as well that will allow you to change the pins to whatever you want.

For now you have to hook up the I2C pins of the spark core to the appropriate pins of your elechouse NFC breakout. From my post above.

I donā€™t see those PN532_SPI_DATAWRITE / READ values being used in the code, prolly because SPI is not implementedā€¦ but Iā€™m guessing they are some kind of command values. Not needed in this case, when using I2C anyway.

Oh gotcha - Do those libraries support a different set of chips? or PN532?

What can I do to help you port the Adafruit NFC libraries?

Iā€™m thinking just PN532ā€¦ you can help by creating a machine that speeds my time up relative to everyone elseā€™sā€¦ that way I can have like 7 days occur in like one day.

What I would do is start with the Adafruit SPI library, port itā€¦ then add Soft SPI supportā€¦ then add I2C support. Release each one as they are completed.

BDub, Iā€™m in porting mode right now. You want me to take a crack at it?

UPDATE: The library already uses soft SPI and would be easy peasy to convert to hardware AND software SPI like I did with the microSD library :smile:

Yeah I guess it is Soft SPI already:

And hereā€™s the I2C one:

If you have time to work on the SPI version first, I can test it with my hardware. I think Soft SPI is going to be the most versatile library. Adafruit also had integrated the IRQ output from the shield/breakout with an digital input on the arduino in the I2C library only. Unfortunately they seem to have Polled that pin, but It would be great to have that functionality as is, or used on an attachedInterrupt(). That would be the most efficient way to use this reader in my opinion.

King of a tall order to break that all down without the hardware, which is why I bought one of the NFC Shields. So if you want to take a stab at it, please do and Iā€™ll help testā€¦ otherwise Iā€™ll get to it eventually.

@BDub, I finished the port of the combined hardware and software SPI for you to test. There is a #define in the .h file to select whether you want to use hard or soft SPI. I am in the process of porting the examples and once Iā€™m done, I will post the whole thing on my github for you to test. The only thing I am not sure about is that when you use hardware SPI to read, you have to send dummy data and itā€™s not obvious which byte value to send. So I send a 0x55 which is a wakeup command. There may be a more suitable value but for now that will do. Stand by! :smile:

UPDATE: @BDub, the PN532 LIbrary for Spark is on my github. I have it setup to use hardware SPI by default but you can also use software SPI if you feel bold! Let me know how it goes :slight_smile:

Wow, fast work @peekay123! I'll work on this tonight.

Basically when you do an SPI read you have to write something.... but the SPI slave device should ignore the data on the MOSI pin during a read, so you can just send it anything. Typically it's 0xFF for dummy bytes. If you're debugging though, it's helpful sometimes to set it to a unique value.

@BDub, I was just concerned that 0xFF would be recognized as ā€œPN532_STARTCODE2ā€. You can play with that value in the code if you have any problems.

Just a quick update, I was working on this todayā€¦ I had quite a few issues which Iā€™ll explain once I get this working. So far no dice, but itā€™s getting there. :slight_smile:

@BDub, let me know how I can help! :smiley: