How to define multile instances of I2C PN532 readers in code

I have coded a working PN532 NFC reader on my Arduino. I would like to connect multiple ones to the same Arduino. How would i define a 2nd instance of that in code. I have used multiple I2C devices in the past and usually they have a address pad to solder to change the address, but this one doesn't. I dont mind using SPI or wiring interrupt pins if needed.

Here is the code for the PN532

/*!
 *@file nfcCardInfo.ino
 *@brief read the basic information of the card
 *@details  This demo runs on the arduino platform.
 *@        Download this demo to read the basic information of the card,
 *@        including UID, manufacturer, storage space, RF technology etc.
 *@        
 *@        Suported NFC card/tag:
 *@        1.MIFARE Classic S50/S70
 *@        2.NTAG213/215/216
 *@        3.MIFARE Ultralight
 *@copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 *@license     The MIT license (MIT)
 *@author [fengli](li.feng@dfrobot.com)
 *@version  V1.0
 *@date  2019-7-3
 *@url https://github.com/DFRobot/DFRobot_PN532
 */
#include <DFRobot_PN532.h>
#define  BLOCK_SIZE      16
#define  PN532_IRQ      (2)
#define  INTERRUPT      (1)
#define  POLLING        (0)
// Use this line for a breakout or shield with an I2C connection
// Check the card by polling
DFRobot_PN532_IIC  nfc(PN532_IRQ, POLLING); 
DFRobot_PN532:: sCard_t NFCcard;

const int output_pin = 6;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(output_pin, OUTPUT);
  Serial.begin(115200);
  //Initialize the NFC module
  while (!nfc.begin()) {
    Serial.println("initial failure");
    delay (1000);
  }        
  Serial.println("Please place the NFC card/tag on module..... ");
}

void loop() 
{
  //Scan, write and read NFC card every 2s
  //Print all what is to be written and read
  
  if (nfc.scan()) 
  {
    //Read the basic information of the card
    NFCcard = nfc.getInformation();
    Serial.println("----------------NFC card/tag information-------------------");
    Serial.print("UID Lenght: "); Serial.println(NFCcard.uidlenght);
    Serial.print("UID: ");
    for (int i = 0; i < NFCcard.uidlenght; i++) {
      Serial.print(NFCcard.uid[i], HEX);
      Serial.print(" ");
        //call here 
            if (readRFID()) {
          // Access granted.
            digitalWrite(output_pin, LOW);
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println("Valid");
           }
          else {
        // Access denied
            digitalWrite(output_pin, HIGH);
            digitalWrite(LED_BUILTIN, HIGH);
            Serial.println("Invalid");
           }
    }
    Serial.println("");
  }
  else 
  {
    //Serial.println("no card!");
    digitalWrite(output_pin, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);
  }
  delay(200);
}



boolean readRFID()
{
  byte card_ID[4];                                        // card UID size 4byte
  const int numOfCards = 1;                               // the number of cards used. this can change as you want
  byte cards[numOfCards][7] = {{0x93, 0xDB, 0x1B, 0xFB}}; // array of UIDs of rfid cards
//1 0xFD, 0xF8, 0x92, 0xDA 
//2 0x3D, 0xD2, 0x93, 0xDA 
//3 0xCD, 0xE7, 0x94, 0xDA 
//4 0x0D, 0x74, 0x94, 0xDA
//5 0xCD, 0x73, 0x94, 0xDA
//6 0x7D, 0xD2, 0x93, 0xDA
  for (byte i = 0; i < NFCcard.uidlenght; i++)
  {    card_ID[i] = NFCcard.uid[i];  }

  for (int i = 0; i < numOfCards; i++)
  {
    if ((card_ID[0] == cards[i][0]) && (card_ID[1] == cards[i][1]) && (card_ID[2] == cards[i][2]) && (card_ID[3] == cards[i][3]))
    {    return true;    }
  }

 return false;
}

After searching online I found this forum post and this board that would allow me to connect multiple locked address I2C devices.

The code in the adafruit board tutorial is

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

#define TCAADDR 0x70

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag1 = Adafruit_HMC5883_Unified(1);
Adafruit_HMC5883_Unified mag2 = Adafruit_HMC5883_Unified(2);

void displaySensorDetails(Adafruit_HMC5883_Unified *mag)
{
  sensor_t sensor;
  mag->getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}


void setup(void) 
{
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
  
  /* Initialise the 1st sensor */
  tcaselect(2);
  if(!mag1.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
  
  /* Initialise the 2nd sensor */
  tcaselect(6);
  if(!mag2.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
  
  /* Display some basic information on this sensor */
  tcaselect(2);
  displaySensorDetails(&mag1);
  tcaselect(6);
  displaySensorDetails(&mag2);
}

void loop(void) 
{
  /* Get a new sensor event */ 
  sensors_event_t event; 
  
  tcaselect(2);
  mag1.getEvent(&event);
 
  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print("Sensor #1 - ");
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.println("uT");
  
  tcaselect(6);
  mag2.getEvent(&event);
  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print("Sensor #2 - ");
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.println("uT");
  
  delay(500);
}

How would I put the PN532 code into this example?

As the I2C address is fixed then the only way you can do this is by using an I2C multiplexer. Like this one:-

I looked at the example and tried to make code to use two PN532, it compiled with no errors. I have to wait for the board to arrive before i can test it. Here is my code does it look alright?

//------TCA9548A I2C multiplexer----------------------
#include <Wire.h>
#define TCAADDR 0x70

void tcaselect(uint8_t i) 
{
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}
//--------------PN532-----------------------------------------------
#include <DFRobot_PN532.h>
#define  BLOCK_SIZE      16
#define  PN532_IRQ      (2)
#define  INTERRUPT      (1)
#define  POLLING        (0)

DFRobot_PN532_IIC  nfc1(PN532_IRQ, POLLING); 
DFRobot_PN532:: sCard_t NFC1card;

DFRobot_PN532_IIC  nfc2(PN532_IRQ, POLLING); 
DFRobot_PN532:: sCard_t NFC2card;
//-------------------------------------------------------------

void setup(void) 
{
  Serial.begin(9600);
  Serial.println("Sensors Test"); Serial.println("");
  
  /* Initialise the 1st sensor */
  tcaselect(2);
  if(!nfc1.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("NFC 1 not connected");
    while(1);
  }
  
  /* Initialise the 2nd sensor */
  tcaselect(6);
  if(!nfc2.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("NFC 2 not connected");
    while(1);
  }
  
}

void loop(void) 
{ 

  tcaselect(1);
/* Call sensor 1 *///-------------------------
  if (nfc1.scan()) 
  {
    //Read the basic information of the card
    NFC1card = nfc1.getInformation();
    Serial.println("----------------NFC1 card/tag information-------------------");
    Serial.print("UID Lenght: "); Serial.println(NFC1card.uidlenght);
    Serial.print("UID: ");
    for (int i = 0; i < NFC1card.uidlenght; i++) {
      Serial.print(NFC1card.uid[i], HEX);
      Serial.print(" ");
        //call here 
            if (readRFID1()) {
          // Access granted.
            digitalWrite(output_pin, LOW);
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println("Valid");
           }
          else {
        // Access denied
            digitalWrite(output_pin, HIGH);
            digitalWrite(LED_BUILTIN, HIGH);
            Serial.println("Invalid");
           }
    }
    Serial.println("");
  }
  else 
  {
    //Serial.println("no card!");
    digitalWrite(output_pin, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);
  }
//----------------------------------------

  tcaselect(2);
/* Call sensor 2 *///-------------------------
  if (nfc2.scan()) 
  {
    //Read the basic information of the card
    NFC2card = nfc2.getInformation();
    Serial.println("----------------NFC2 card/tag information-------------------");
    Serial.print("UID Lenght: "); Serial.println(NFC2card.uidlenght);
    Serial.print("UID: ");
    for (int i = 0; i < NFC2card.uidlenght; i++) {
      Serial.print(NFC2card.uid[i], HEX);
      Serial.print(" ");
        //call here 
            if (readRFID2()) {
          // Access granted.
            digitalWrite(output_pin, LOW);
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println("Valid");
           }
          else {
        // Access denied
            digitalWrite(output_pin, HIGH);
            digitalWrite(LED_BUILTIN, HIGH);
            Serial.println("Invalid");
           }
    }
    Serial.println("");
  }
  else 
  {
    //Serial.println("no card!");
    digitalWrite(output_pin, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);
  }
//----------------------------------------

  delay(200);
}

boolean readRFID1()
{
  byte card_ID[4];                                        // card UID size 4byte
  const int numOfCards = 1;                               // the number of cards used. this can change as you want
  byte cards[numOfCards][7] = {{0x93, 0xDB, 0x1B, 0xFB}}; // array of UIDs of rfid cards
  //1 0xFD, 0xF8, 0x92, 0xDA 
  //2 0x3D, 0xD2, 0x93, 0xDA 
  //3 0xCD, 0xE7, 0x94, 0xDA 
  //4 0x0D, 0x74, 0x94, 0xDA
  //5 0xCD, 0x73, 0x94, 0xDA
  //6 0x7D, 0xD2, 0x93, 0xDA
  for (byte i = 0; i < NFC1card.uidlenght; i++)
  {    card_ID[i] = NFC1card.uid[i];  }

  for (int i = 0; i < numOfCards; i++)
  {
    if ((card_ID[0] == cards[i][0]) && (card_ID[1] == cards[i][1]) && (card_ID[2] == cards[i][2]) && (card_ID[3] == cards[i][3]))
    {    return true;    }
  }

 return false;
}

boolean readRFID2()
{
  byte card_ID[4];                                        // card UID size 4byte
  const int numOfCards = 1;                               // the number of cards used. this can change as you want
  byte cards[numOfCards][7] = {{0x93, 0xDB, 0x1B, 0xFB}}; // array of UIDs of rfid cards
  //1 0xFD, 0xF8, 0x92, 0xDA 
  //2 0x3D, 0xD2, 0x93, 0xDA 
  //3 0xCD, 0xE7, 0x94, 0xDA 
  //4 0x0D, 0x74, 0x94, 0xDA
  //5 0xCD, 0x73, 0x94, 0xDA
  //6 0x7D, 0xD2, 0x93, 0xDA
  for (byte i = 0; i < NFC2card.uidlenght; i++)
  {    card_ID[i] = NFC2card.uid[i];  }

  for (int i = 0; i < numOfCards; i++)
  {
    if ((card_ID[0] == cards[i][0]) && (card_ID[1] == cards[i][1]) && (card_ID[2] == cards[i][2]) && (card_ID[3] == cards[i][3]))
    {    return true;    }
  }

 return false;
}

No not really.

The I2C multiplexer has pins which select which one if the I2C busses gets switched through. You seem not to be doing anything Ike that in your code.

Also you are trying to do too much in one step. Just start off with two busses and see how that goes. Don't ever try to do anything with the resultant read except print it out. Try reading that link again.

1 Like

Is your problem solved by now. And how please?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.