Help learning about the NFC/RFID PN532

Hi all,

Got my hands on a NFC/RFID PN532 module. But I'm having difficulty trying to learn to code for the pn532. I can't seem to find any good tutorial online since many of them use a different module. I was able to get some examples to try and learn from but its not good.

Basically what I want to do for now it use it to turn a specific led on depending on which tag I use. Like if I use tag 1 then that would light up a green led then tag 2 would light a red led and lastly tag 3 would light a yellow led.

How you are communicating with PN532?

This might be a stupid question but what exactly do you mean? I use an Arduino uno and plug the pn532s ground, vcc, sda, and scl to their designated places, at least to what the example says.

Then you are communicating via I2C bus. Then you should use this Library

Those are the exact same examples I'm using and trying to learn from. But without anyone actually teaching me, I'm going nowhere. BTW, I'm quite a noob at programming in general.

But without anyone actually teaching me, I'm going nowhere.

So is this thread, since you are not describing what you need help with, what problems you are having, etc.

Oh, I thought I made that clear by saying what I want to make but cant cause I don't know the first thing about coding with the NFC/RFID PN532.

What I want to create is quite simple for now. Use the arduino and the module to light up an led depending on which tag it reads. So if it reads tag 1 then it will light up led 1. If it read tag 2 then led 2 with respond. And so on...

Now what I don't know is really... anything. I don't know where to start. I don't what code to initialize communication between the arduino and the module. I don't know what code to use to make the module read a tag and do something depending on what it reads from the tag.

I thought i was pointed out where to begin.

You can begin with library's example, and it covers most of your questions.

I don't know where to start.

Those are the exact same examples I'm using

One of these may be true. They can't both possibly be true.

If the second is true, the first is whining. If the first is true, the second is a lie.

Which is it?

If you have compiled, linked, and uploaded some code, show that code. Explain what happens when you wave a tag by the reader.

If you haven't compiled, linked, and uploaded the example, you'd better have a damned good reason why not.

I guess I ain't explaining myself quite well.

I got the example and everything works when I use it. But thing is I don't know why. It's like driving a car, I know it works but I don't know exactly how it works. But I want to know how it works.

Although the examples do provide ample descriptions on what code is what, I just can't seem to connect the dots. So I end up confused and end up feeling like I'm trying to learn calculus without first learning algebra.

For show here's what I've got. It's supposed to turn the green led on if it scans the right tag. And turn the red led on if any other tag is scanned.

int greenLED=8;
int redLED=9;

byte goodCard=0x64,0x40,0xB1,0x76;

#include <Wire.h>
#include <Adafruit_NFCShield_I2C.h>

#define IRQ   (2)
#define RESET (3)

Adafruit_NFCShield_I2C nfc(IRQ, RESET);


void setup() {
  nfc.begin();
  pinMode(greenLED,OUTPUT);
  pinMode(redLED,OUTPUT);
}

void loop() {  
  uint8_t uid[] = {0,0,0,0,0,0,0};
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  
  if (uint8_t uid[] == goodCard){
    digitalWrite(greenLED,HIGH);
    delay(1000);
    digitalWrite(greenLED,LOW);
  }
  
  if (uint8_t uid[] != goodCard){
    digitalWrite(redLED,HIGH);
    delay(1000);
    digitalWrite(redLED,LOW);
  }
}
  if (uint8_t uid[] == goodCard){

Please explain what you think you are doing here. I'm sure that that was not in the example.

I'm also sure that that never evaluates to true. You can't use == to compare two arrays, one of which is brand new, containing 0 elements.

You probably want to compare the elements in the uid array that nfc.readPassiveTargetID() populates, but it isn't clear why that array contains 7 elements and the array that you are trying to compare it to contains 4.

To do that, you need to use memcmp() or a for loop.

Below is the example sketch I "tried" to learn from.

And from there I was looking for the code that takes the ID from the tag so I can compare it to another ID. And I thought "uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }" was that.

#include <Wire.h>
#include <Adafruit_NFCShield_I2C.h>

#define IRQ   (2)
#define RESET (3)  // Not connected by default on the NFC Shield

Adafruit_NFCShield_I2C nfc(IRQ, RESET);

void setup(void) {
  Serial.begin(115200);
  Serial.println("Hello!");

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  
  // 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 the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0xFF);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
    
  Serial.println("Waiting for an ISO14443A card");
}

void loop(void) {
  boolean success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  
  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  
  if (success) {
    Serial.println("Found a card!");
    Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("UID Value: ");
    for (uint8_t i=0; i < uidLength; i++) 
    {
      Serial.print(" 0x");Serial.print(uid[i], HEX); 
    }
    Serial.println("");
    // Wait 1 second before continuing
    delay(1000);
  }
  else
  {
    // PN532 probably timed out waiting for a card
    Serial.println("Timed out waiting for a card");
  }
}

And from there I was looking for the code that takes the ID from the tag so I can compare it to another ID. And I thought "uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }" was that.

Assigning an initial value to an array, and then passing that array to a function to overwrite, is silly, isn't it.

The array that the function puts data in IS uid.

It's this code:

  if (uint8_t uid[] == goodCard){

that is nonsense.

First, whenever there is a type, there is a NEW variable. The uid array that the nfc instance created is NOT the uid array that is being compared to goodCard. It is the NEW uid variable, of size 0, that is being compared.

Second, it is the ADDRESS of uid and the ADDRESS of goodCard that == is comparing. There is NO possible way that the two ADDRESSES are the same.

After the call to nfc.readPassiveTargetID(), put something like this:

if(memcmp(uid, goodCard, sizeof(goodCard))
{
    // The cards match
}
else
{
   // Scam alert
}

So in

if(memcmp(uid, goodCard, sizeof(goodCard))

the 'uid' is where 'nfc.readPassiveTargetID()' populates the scanned ID? Then using 'memcmp()' it compares 'uid' to 'goodCard' right?

the 'uid' is where 'nfc.readPassiveTargetID()' populates the scanned ID? Then using 'memcmp()' it compares 'uid' to 'goodCard' right?

Yes.

Cool, so now I need to set 'uid' as some sort of bucket (for lack of better description). What would work?

What is 'uint8_t' used for? From what I understand it its like a byte that holds 8 bits of unsigned integer. So does that mean I can use it as 'uid'?

Cool, so now I need to set 'uid' as some sort of bucket (for lack of better description). What would work?

How about an array? Oh, wait, it already is one. What is the problem?

What is 'uint8_t' used for?

It's a type, like int, long, char, float, etc.

From what I understand it its like a byte that holds 8 bits of unsigned integer.

Yes.

So does that mean I can use it as 'uid'?

No. It means that you can use it as the type of the array whose name is uid.

So I tried it with this code

int greenLED=8;
int redLED=9;
byte goodCard=0x64,0x40,0xB1,0x76;
#include <Wire.h>
#include <Adafruit_NFCShield_I2C.h>
#define IRQ   (2)
#define RESET (3)
Adafruit_NFCShield_I2C nfc(IRQ, RESET);

void setup(){
  nfc.begin();
  pinMode(greenLED,OUTPUT);
  pinMode(redLED,OUTPUT);
}
void loop(){
  uint8_t uid;
  uid=nfc.readPassiveTargetID();
  if(memcmp(uid, goodCard, sizeof(goodCard))){
    digitalWrite(greenLED,HIGH);
    delay(1000);
    digitalWrite(greenLED,LOW);
  }
  else{
    digitalWrite(redLED,HIGH);
    delay(1000);
    digitalWrite(redLED,LOW);
  }
}

but line 17 (uid=nfc.readPassiveTargetID()) keeps getting the error "no matching function for call to 'Adafruit_NFCShield_I2C::readPassiveTargetID()'"

did I miss something I needed to "#include"?
Thanks for helping me out on this.

You had this:

  uint8_t uid[] = {0,0,0,0,0,0,0};
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);

You f**ked it up to look like this:

  uint8_t uid;
  uid=nfc.readPassiveTargetID();

Why?

Well I thought I needed to get a integer and name it 'uid' then I can fill that with 'nfc.readPassiveTargetID()'

It still doesn't seem to work though. Cause arduino keeps poping this error up

no matching function for call to 'Adafruit_NFCShield_I2C::readPassiveTargetID(int, uint8_t*)'