RFID-RC522 (MFRC522) with NDEF Format

Hola Everyone,

I am messing around with NFC & RFID boards. Currently I have a RFID-RC522 Board for reading MiFare cards. The board is working, and I can read RFID MiFare 1k Cards. Kinda. I don't understand the data display functions that the libraries seem to use. I am having problems processing the data once it's picked up.

GitHub - miguelbalboa/rfid: Arduino RFID Library for MFRC522 Spits out all sorts of data that I dont really get what to do with it, aside from check if my cards uid is the same as the one in the file?

Or this https://github.com/ljos/MFRC522/blob/master/examples/auth_read_write/authenticate.ino has an authenticate function that spits out hex or decimal values.

My confusion stems from the fact that I also have a different RFID reader/writer. That PN532 RFID writer stores the data in NDEF format. I really like that. And I wanted this reader to read that NDEF formatted data.

Like the Arduino_NFC Library here does.

Basically, I don't get how to use a RFID-RC522 's response data and read it with that NDEF library. Do I need a second PN532 chip RFID reader to do that?

Im trying to print the cards NDEF value to an lcd or serial or anything to start out with.

Thanks for Reading!

I just started playing with my 522 last night also! I was actually a bit surprised to discover you can store data on the tokens, mine all have 1kb capacity. But for my use right now, a unique identifier for each one is sufficient. For that, you can just use the token's ID number. They should be fairly unique. Token IDs can be 4, 7, or 10 bytes, and appear to be a number stored in little endian order.

So for my purposes, I am just reading the first four bytes and converting to a number and going with that. I have no need to read or write any of the data blocks on the tokens. I've done a bit of work with my code and it looks to be about good for use in my other sketches now. I will paste it below, maybe this is sufficient for your needs also. This is using the library available at GitHub - miguelbalboa/rfid: Arduino RFID Library for MFRC522

Edit "#define debugging false" to true to enable debug output and it will display your token IDs in console for you to fill in the array with. I have my console speed set to max rate (115200) so pay attention to that if you're using 9600. (some tokens come with their ID laser stamped on them)

/*

mfrc522_id_authenticate
by N0ZYC  4/16/2014
based on example sketches

This sketch demonstrates how to use RFID tags for identification or authentication
MRF-522 reader is compatible with 13.56 MHz RFID tags: mifare1 S50, mifare1 S70 MIFARE Ultralight, mifare Pro, MIFARE DESFire
http://www.nxp.com/documents/data_sheet/MFRC522.pdf

 * Pin layout should be as follows:
 * Signal     Pin              Pin               Pin
 *            Arduino Uno      Arduino Mega      MFRC522 board
 * ------------------------------------------------------------
 * Reset      9                5                 RST              reset,               can be changed on arduino, defined below
 * SPI SS     10               53                SDA              slave select,        can be changed on arduino, defined below

 * SPI MOSI   11               51                MOSI             master out slave in, hard-wired, varies between arduino models
 * SPI MISO   12               50                MISO             master in slave out, hard-wired, varies between arduino models
 * SPI SCK    13               52                SCK              spi clock,           hard-wired, varies between arduino models

BE CAREFUL!  The modules commonly available require 3.3 volts on their VCC
this module does not appear to have a level converter for 5v spi logic, but mine hasn't cooked mine yet

*/





//  include SPI and RFID libraries
#include <SPI.h>
#include <MFRC522.h>  //  library available at https://github.com/miguelbalboa/rfid





//  define changeable pins
#define SS_PIN 10  //  all SPI peripherals share the same predefined pins for miso, mosi, and sck, but each peripheral uses its own Slave Select
#define RST_PIN 9  //  the reset pin is not part of the SPI protocol, and can be shared or changed





//  operational configurations
#define startup_chirp true   //  define true to chirp twice on power-up
#define debugging     false  //  define true to display more information during read attempts





//  you can attach a little piezo beeper to make a chirp in response to reading a valid or invalid token
//  tie (-) on the beeper to ground and (+) to the specified pin:
#define chirp_dpin 8          //  define this to chirp when a token registers
#define chirp_valid_ms   100  //  define this to chirp this many ms when a valid token is presented
#define chirp_invalid_ms  10  //  define this to chirp this many ms when an invalid token is presented
//  after you're done testing, for security purposes, you may want to leave chirp_invalid_ms set to 0





//  Create MFRC522 instance
MFRC522 mfrc522(SS_PIN, RST_PIN);





//  create a list of valid RFID tokens
#define user_count 16
#define token_invalid -1  //  invalid token ID or user ID
unsigned long user_tokens [user_count] = {
  0x745CB413,0x745ADFED,0x745F0CEE,0x745DABC2,0x745E56C1,0xA9BA5D53,0xA9BE5843,0xA9BB5773,
//  0xA9C22333,0xA9B995F3,0x3281DE64,0x326733B4,0x3287CF24,0x32886664,0x3282A744,0x328755F4
  0xA9C22333,0xA9B995F4,0x3281DE64,0x326733B4,0x3287CF24,0x32886664,0x3282A744,0x328755F4  //  invalidated token B5 for testing
};

/*
A1 - A5: (my white cards)
Card UID: 13 B4 5D 74  ($745CB413 / 1952232467)   0 = A1
Card UID: ED DF 5B 74  ($745ADFED / 1952112621)   1 = A2
Card UID: EE 0C 5F 74  ($745F0CEE / 1952386286)   2 = A3
Card UID: C2 AB 5E 74  ($745DABC2 / 1952295874)   3 = A4
Card UID: C1 56 5E 74  ($745E56C1 / 1952339649)   4 = A5  secondary test token

B1 - B5: (my blue keyfobs)
Card UID: 53 5D BA A9  ($A9BA5D53 / 2847563091)   5 = B1
Card UID: 43 58 BE A9  ($A9BE5843 / 2847823939)   6 = B2
Card UID: 73 57 BB A9  ($A9BB5773 / 2847627123)   7 = B3
Card UID: 33 23 C2 A9  ($A9C22333 / 2848072499)   8 = B4
Card UID: F3 95 BA A9  ($A9B995F3 / 2847512051)   9 = B5  secondary test token

C1 - C6: (my tan keyfobs)
Card UID: 64 DE 82 32  ($3281DE64 / 847371876)  19 = C1
Card UID: B4 33 67 32  ($326733B4 / 845624244)  11 = C2
Card UID: 24 CF 88 32  ($3287CF24 / 847761188)  12 = C3
Card UID: 64 66 88 32  ($32886664 / 847799908)  13 = C4
Card UID: 44 A7 83 32  ($3282A744 / 847423300)  14 = C5
Card UID: F4 55 87 32  ($328755F4 / 847730164)  15 = C6  primary test token
*/





void setup() {
  Serial.begin(115200);	// Initialize serial communications with the PC
  delay(100);
  SPI.begin();		// Init SPI bus
  mfrc522.PCD_Init();	// Init MFRC522 card
  //  init the chirp
  #ifdef chirp_dpin
    pinMode(chirp_dpin,OUTPUT);
    //  make a double chirp at startup if so configured
    if (startup_chirp) {
      digitalWrite(chirp_dpin,HIGH);
      delay(50);
      digitalWrite(chirp_dpin,LOW);
      delay(50);
      digitalWrite(chirp_dpin,HIGH);
      delay(50);
      digitalWrite(chirp_dpin,LOW);
      delay(50);
    }
  #endif
  Serial.println("\n\nReady to begin identifying cards, scan cards now:\n\n");
}





//  return a user id (index) based on provided token id (return token_invalid if not found in user list)
int UserFromToken(unsigned long got_id) {
  for (uint16_t i = 0 ; i < user_count ; i++) {
    if (got_id == user_tokens[i]) {
      return i;
    }
  }
  return token_invalid;
}





//  return the ID of the user whose token has just been presented, or return token_invalid if no new valid token
int UserTokenPresented (boolean got_multi = false, boolean got_debug = false) {
  //  return token_invalid if no new token has been presented
  if (not mfrc522.PICC_IsNewCardPresent()) {
    return token_invalid;
  }
  //  return token_invalid if unable to read presented token
  if (not mfrc522.PICC_ReadCardSerial()) {
    return token_invalid;
  }
  //  a new functional (though not necessarily valid) token has been presented AND read
  // halt the selected card.  prevent another read moments from now (unless requested)
  if (not got_multi) {
    mfrc522.PICC_HaltA();
  }
  //  calculate token id and look up user id.  use only the first four bytes of the id (should be little endian, length valid on any token almost guaranteed unique)
  unsigned long token_id = mfrc522.uid.uidByte[0] + mfrc522.uid.uidByte[1] * 0x100 + mfrc522.uid.uidByte[2] * 0x10000 + mfrc522.uid.uidByte[3] * 0x1000000;
  int user_id = UserFromToken(token_id);
  //  print token information if requested by caller
  if (got_debug) {
    Serial.print("Card UID:");
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
      Serial.print(mfrc522.uid.uidByte[i], HEX);
    }
    Serial.print("  ($");
    Serial.print(token_id,HEX);
    Serial.print(" / ");
    Serial.print(token_id,DEC);
    Serial.print(") user_id = ");
    Serial.print(user_id,DEC);
    if (user_id == token_invalid) {
      Serial.print(" (invalid token / no such user)");
    }
    Serial.println();
  }
  //  chirp the beeper if configured to do so
  #ifdef chirp_dpin
    if ((user_id != token_invalid) && (chirp_valid_ms > 0)) {
      //  token is a valild user and we are supposed to chirp
      digitalWrite(chirp_dpin,HIGH);
      delay(chirp_valid_ms);
      digitalWrite(chirp_dpin,LOW);
    } else if ((user_id == token_invalid) && (chirp_invalid_ms > 0)) {
      //  token is NOT a valild user and we are supposed to chirp
      digitalWrite(chirp_dpin,HIGH);
      delay(chirp_invalid_ms);
      digitalWrite(chirp_dpin,LOW);
    }
  #endif
  //  return the user id (index) or token_invalid
  return user_id;
}





//  test loop - acknowledge any valid tokens
void loop() {
  
  int user_id = UserTokenPresented(false,debugging);
  if (user_id != token_invalid ) {
    Serial.print("Valid user ID # "); Serial.print(user_id,DEC); Serial.println(" identified.");
  }

}

Hey thanks virtual1 for that code!

I liked your Chirpy idea!

So basically, you're just grabbing the UID of the card, seeing if its the same one as in a array?

Im trying to like, put someones email on the card in NDEF format. then later, when they scan it, read them back their email. Eventually to a LCD but for serial now would be great.

With my other reader writer, it goes like this for the main loop function. and that's what im trying to accomplish with this reader.

void loop(void) {
 uint8_t * uid = mifare.readTarget();
 if(uid){
   Serial.println(Mifare::cardType == MIFARE_CLASSIC ?"Classic" : "Ultralight");
    memset(payload, 0, PAYLOAD_SIZE);
	
	//read 

	mifare.readPayload(payload, PAYLOAD_SIZE);

	FOUND_MESSAGE m = NDEF().decode_message(payload);

	switch(m.type){
	case NDEF_TYPE_URI:
	 Serial.print("URI: ");
	 Serial.println((int)m.format);
	 Serial.println((char*) m.payload);
	break;
	case NDEF_TYPE_TEXT:
	 Serial.print("TEXT: "); 
	 Serial.println(m.format);
	 Serial.println((char*)m.payload);
	break;
	case NDEF_TYPE_MIME:
	 Serial.print("MIME: "); 
	 Serial.println(m.format);
	 Serial.println((char*)m.payload);
	break;
	default:
	 Serial.println("unsupported");
	break; 
	}
  }
  delay(2000);
}

I'm not new to programming but am still a little green to arduino (and C++ actually) but I've made some headway. The library has multiple errors in it that aren't helping matters, and as you've noticed it also lacks good read/write. I've gotten the read working for the firt 1kb area anyway. Per the specs I've created a function call to read a (16 byte) block provided an index 0-44. This skips the unwritable sector 0 (containing blocks 0-3) as well as the trailer block in each sector. (which without this skipping would otherwise give you 64 blocks to attempt to access, probably with unfortunate results)

You have to be careful, if you mung up the access bits in a trailer block or try to read something you're not allowed to, the token's security will permanently disable access to the entire sector! So I'm just going to leave those out of reach for now, the tokens are supposed to ship with full write enable, giving you 720 bytes of data (in 16 byte chunks) easily accessible in a 1kb token.

I've gotten the writing working without generating any errors, but it doesn't appear to be performing the writes. I'm investigating that now.

hah. library was fine. my test sketch had a bug :wink: meant to zero the buffer and then change one byte randomly. got that backward, zeros just wouldn't go away!

so it appears to be working in basic form. I'll probably tweak it quite a bit. Here's a few sketches and the updated h and cpp. Let me know what you think of it, I appreciate feedback regardless of what you think. You could use it now as-is by breaking up your character array that stores the email address.

(btw, my module appears to be 3.3v, I am powering it with 3.3 but my isp lines are connected directly... is this bad for this module to an uno? need level conversion?)

ok.... got "The message exceeds the maximum allowed length (9500 characters)." but my post was under 2000 lines. go fig. h and cpp to follow. oh... characters. I can't even post the .h here for that.

http://vftp.net/N0ZYC/arduino/RFID/MFRC522.zip

Virtual1,

Hey thanks I really appreciate your replies! I downloaded your library and I'm going to get started with your code. I will report back later with my progress.

Thanks a bunch!!!

Try this one. I have added functions that should make your storing character arrays (for email addresses or other string data) easy. They lump the entire first kb of the tag into a block of 720 continuous bytes, and you access them by passing in an offset into the block, an array, and a length. it loads or stores the array automatically, so you don't need to try to juggle sectors or blocks.

http://vftp.net/N0ZYC/arduino/RFID/MFRC522.1.zip

I also moved a few of the common functions from the examples into the library, to simplify the user's sketches. It should be possible to do basic things with RFID tags now in under a dozen lines.

I plan on implementing this in a hunt. Players will be looking for hidden boxes, and will "mark" them by passing a tag over the marked area on the box when they find one, before moving on to the next one. The boxes can identify who found them, when, and in what order. (these are actually going to be foxes for radio direction finding) Before the hunt begins, I can quickly program the tags with the names of the players. At least one of my foxboxes will have an emic2 in it and should be able to announce the names of those that find it, without having to be programmed with their names in advance of the game. :slight_smile:

johnnyfortune:
You have to be careful, if you mung up the access bits in a trailer block or try to read something you're not allowed to, the token's security will permanently disable access to the entire sector!

hi there, can you please confirm?
one a protected sector is being read with no password supplied, the sector is permanently blocked?

sounds convinient but this way you can destroy every tag in range by trying to dump it...

hello,

I am new in arduino, and would like to know if anyone managed to read ndef tag with the rc522 and arduino.

I can read the uid, but I can not read the ndef tag message.

instead I have found on the internet library ndef for the pn532 and ndeh and these connected to arduino cand scan the uid and the ndef tag message, but I can't manage to do it with the rc522

can anyone please help me???

thanks

Hi, I'd like to take a look at the code in this zip

yasuoiwakura:
http://vftp.net/N0ZYC/arduino/RFID/MFRC522.1.zip

but the link appears to be dead. Any help would be much appreciated!

gauzzastrip:
Hi, I'd like to take a look at the code in this zip

but the link appears to be dead. Any help would be much appreciated!

Try the following link: http://vftp.net/N0ZYC/arduino/projects/RFID/MFRC522.1.zip

Hi,

just use the read/write example of the library, read a block and interprete it using the ndef format.

regards,
RFIDBOY