PN532 issue with Keyboard.h library

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
Davessi
 
Posts: 5
Joined: Sun Oct 03, 2021 10:38 am

PN532 issue with Keyboard.h library

Post by Davessi »

Hey folks,
I have a project where I would like to use the PN532 breakout board and an Arduino Leonardo to send keyboard commands to a laptop. The idea is to have different RFID cards trigger videos from a media player using the mapped keyboard commands. I have done this many times with just pushbutton switches and using the Keyboard.h library works fine in those applications.

I have connected my PN532 to the Leonardo and used the test sketch using the Adafruit_PN532.h library and the I2C connections. This works great and I can verify the cards on the serial monitor...life is good. Once I add the Keyboard.h library and a simple function to Keyboard.press ("A") based on a Card ID, the loop stops and the sketch never gets off the starting blocks. It's like everything comes to a stop. Has anyone experienced this issue? Kinda stuck here.

Code: Select all

/**************************************************************************/
#include <Keyboard.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>


// If using the breakout with SPI, define the pins for SPI communication.
//#define PN532_SCK  (2)
//#define PN532_MOSI (3)
//#define PN532_SS   (4)
//#define PN532_MISO (5)

// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines.  Use the values below (2, 3) for the shield!
#define PN532_IRQ   (5)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:

// Use this line for a breakout with a SPI connection:
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

// Use this line for a breakout with a hardware SPI connection.  Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins.  On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12.  The SS line can be any digital IO pin.
//Adafruit_PN532 nfc(PN532_SS);

// Or use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

void setup(void) {
  Serial.begin(115200);
  while (!Serial) delay(10); // for Leonardo/Micro/Zero

  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);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  
  Serial.println("Waiting for an ISO14443A Card ...");
}


void loop(void) {
  uint8_t 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, &uidLength);
  
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    
    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ... 
      uint32_t cardid = uid[0];
      cardid <<= 8;
      cardid |= uid[1];
      cardid <<= 8;
      cardid |= uid[2];  
      cardid <<= 8;
      cardid |= uid[3]; 
      Serial.print("Seems to be a Mifare Classic card #");
      Serial.println(cardid);       
    Keyboard.begin();  
     if (cardid == 1839898475)
      Keyboard.press("A");
       delay(100);
      Keyboard.release("A");
       delay(2000);
    Keyboard.end();      
     Serial.println("");
  }
}
}



User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: PN532 issue with Keyboard.h library

Post by adafruit_support_mike »

It looks like you're calling Keyboard.begin() and Keyboard.end() in loop(), which will force a huge number of USB disconnects and reconnects.

Try using Keyboard.begin() like Serial.begin(), and call it once in setup().

User avatar
Davessi
 
Posts: 5
Joined: Sun Oct 03, 2021 10:38 am

Re: PN532 issue with Keyboard.h library

Post by Davessi »

Hey Mike,

Thanks for the advice. I actually noodled around and got this working by adding the Keyboard.begin at the beginning of the void loop. This works just fine and I was able to map the card ID's to the keyboard commands on the media player. Works great.

However, this is just part of a grand design to create a wheel of fortune where each segment (10-pie shaped segments) will have an RFID card that will trigger a different video when read by the reader. The reader (PN532) will be installed at the top of the wheel so when the wheel stops it will send out a keyboard command based on the card ID on that segment. This is tricky because as the wheel spins the PN532 will be reading cards very fast and we don't want false triggers. We will also want the PN532 to trigger the media player with one command and not a continuous series of keyboard commands. Continuous commands would keep triggering the media player and restarting the video over and over.

I haven't figure out how to (A) keep the PN532 from triggering the media player as the wheel spins. Needs to trigger only when stopped (maybe for 2 seconds). And (B) how to keep the keyboard command from constantly triggering the media player once the wheel has stopped. Figure each video will be about 60 seconds.

The test code for reading the cards and keyboard trigger commands is below. I haven't figured out the rest...any help would be appreciated.

Code: Select all

#include <Keyboard.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>


// If using the breakout with SPI, define the pins for SPI communication.
//#define PN532_SCK  (2)
//#define PN532_MOSI (3)
//#define PN532_SS   (4)
//#define PN532_MISO (5)

// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines.  Use the values below (2, 3) for the shield!
#define PN532_IRQ   (6)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:

// Use this line for a breakout with a SPI connection:
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

// Use this line for a breakout with a hardware SPI connection.  Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins.  On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12.  The SS line can be any digital IO pin.
//Adafruit_PN532 nfc(PN532_SS);

// Or use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

void setup(void) {
  Serial.begin(115200);
  while (!Serial) delay(10); // for Leonardo/Micro/Zero

  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);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  
  Serial.println("Waiting for an ISO14443A Card ...");
}


void loop(void) {
  Keyboard.begin();
  uint8_t 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, &uidLength);
  
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    
    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ... 
      uint32_t cardid = uid[0];
      cardid <<= 8;
      cardid |= uid[1];
      cardid <<= 8;
      cardid |= uid[2];  
      cardid <<= 8;
      cardid |= uid[3]; 
      Serial.print("Seems to be a Mifare Classic card #");
      Serial.println(cardid);        
     if (cardid == 1839898475)
      Keyboard.write('A');
       delay(200);
     if (cardid == 3335073343)
      Keyboard.write('B');
       delay(200); 
    if (cardid == 2260681791)
      Keyboard.write('C');
       delay(200); 
    if (cardid == 3329626431)
      Keyboard.write('D');
       delay(200);
    if (cardid == 1186344511)
      Keyboard.write('E');
       delay(200);     
    Keyboard.end();      
     Serial.println("");
  }
}
}

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”