Search code examples
arduinotagsnfcarduino-unouart

Arduino NFC Module (DFRobot) not reading Whiztags


I bought the NFC module from DFRobot and I'm using their example program with some changes since I only want to read the UID of my tag. It works great with the tag that came with it but it doesn't recognize any of my NFC Whiztags (which contain a Topaz 512 chip).

Does anyone know how can I fix this?

This is my code:

#include <SoftwareSerial.h>
/* 

 # Editor : Adrian
 # Date   : 2013.04.18
 # Ver    : 0.1
 # Product: NFC Module for Arduino
 # SKU    : DFR0231

 # Description:     
 # When the a card close to the device , the PC will receive the data 
 # Connect the NFC Card's TXD, RXD, GND, +3.3V to Nano's D0RX, D1TX, GND, +3.3V
 # Or connect the NFC Card's TXD, RXD, GND, +5V to Nano's D0RX, D1TX, GND, +5V


 PN532 reads the tag by Arduino mega/Leonardo
 command list:

 #wake up reader
 send: 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 03 fd d4 14 01 17 00
 return: 00 00 FF 00 FF 00 00 00 FF 02 FE D5 15 16 00

 #get firmware
 send: 00 00 FF 02 FE D4 02 2A 00
 return: 00 00 FF 00 FF 00 00 00 FF 06 FA D5 03 32 01 06 07 E8 00

 #read the tag
 send: 00 00 FF 04 FC D4 4A 01 00 E1 00
 return: 00 00 FF 00 FF 00 00 00 FF 0C F4 D5 4B 01 01 00 04 08 04 XX XX XX XX 5A 00
 XX is tag.

 */

 //************* start **************

const unsigned char wake[24]={
  0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
  0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
  0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_ACK[25] = {
  0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, \
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
char old_id[5];

unsigned char receive_ACK[25];//Command receiving buffer
//int inByte = 0;               //incoming serial byte buffer

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define print1Byte(args) mySerial.write(args)
#define print1lnByte(args)  mySerial.write(args),mySerial.println()
#else
#include "WProgram.h"
#define print1Byte(args) mySerial.print(args,BYTE)
#define print1lnByte(args)  mySerial.println(args,BYTE)
#endif

SoftwareSerial mySerial(10, 11); // RX, TX
unsigned char myUID[12] = "70 89 7E 43";

void setup()
{
  Serial.begin(9600);   // open serial with PC
  mySerial.begin(115200);    //open mySerial with device
  wake_card();
  delay(200);
  Serial.println("Scanning..."); 

}

void loop()
{
  send_tag(); 
  read_ACK(25);
  delay(100);
      if (test_ACK ()) {
        copy_id ();
        displayuid ();
         delay (10000);
       }

    }


void copy_id (void) 
{//save old id
  int ai, oi;
  for (oi=0, ai=19; oi<5; oi++,ai++) {
    old_id[oi] = receive_ACK[ai];
  }
}

int test_ACK (void) 
{// return true if receive_ACK accord with std_ACK
  int i;
  for (i=0; i<19; i++) {
    if (receive_ACK[i] != std_ACK[i])
      return 0;
  }
  return 1;
}


void send_id (void) 
{//send id to PC
  int i;
  Serial.print ("ID: ");
  for (i=19; i<= 23; i++) {
    Serial.print (receive_ACK[i], HEX);
    Serial.print (" ");
  }
  Serial.println ();
}


void UART1_Send_Byte(unsigned char command_data)
{//send byte to device
  print1Byte(command_data);
#if defined(ARDUINO) && ARDUINO >= 100
  mySerial.flush();// complete the transmission of outgoing serial data 
#endif
} 


void UART_Send_Byte(unsigned char command_data)
{//send byte to PC
  Serial.print(command_data,HEX);
  Serial.print(" ");
} 


void read_ACK(unsigned char temp)
{//read ACK into receive_ACK[]
  unsigned char i;
  for(i=0;i<temp;i++) {
  receive_ACK[i]= mySerial.read();
  }
}

void wake_card(void)
{//send wake[] to device
  unsigned char i;
  for(i=0;i<24;i++) //send command
  UART1_Send_Byte(wake[i]);
}


void send_tag(void)
{//send tag[] to device
  unsigned char i;
  for(i=0;i<11;i++) //send command
  UART1_Send_Byte(tag[i]);
}


void displayuid(void)
{//send receive_ACK[] to PC
  unsigned char i;
  for(i=0;i<4;i++) //send command
  UART_Send_Byte(old_id[i]);
  Serial.println();
}


//*********** end *************

Solution

  • Your reader module contains an NXP PN532 NFC transmission module IC. You currently use the following command to poll for tags:

    tag = { 0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};

    This command is an InListPassiveTarget command (command code D4 4A) with the parameters

    • maximum number of initialized tags (MaxTg) = 1 (0x01) and
    • tag protocol type (BrTy) = ISO/IEC 14443A at 106 kbps (0x00).

    Hence, you can only detect tags that speak the full type A protocol defined in ISO/IEC 14443-3 (including anti-collision). Such tags are, for instance,

    • NFC Forum Type 2 tags,
    • NFC Forum Type 4 tags using the Type A protocol variant,
    • NXP MIFARE Ultralight / Classic / DESFire / NTAG,
    • NXP NTAG,
    • Infineon my-D,
    • Kovio 2K,
    • and possibly others.

    The Whiztags contain a Topaz 512 chip (which is an NFC Forum Type 1 tag). This tag type only partially implements ISO/IEC 14443 Type A (anti-collision mechanism not supported). Consequently, the above polling command won't enumerate such tags. Instead, you would need to switch the BrTy parameter to "Innovision Jewel tag at 106 kbps" (0x04). The modified command (including the update checksum byte) would look like this:

    tag = { 0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x04, 0xDD, 0x00};
    

    You can find further details in the PN532 user manual.