Adafruit RFID/NFC Shield Coding Issues

I’ve been working on a project based on the Adafruit Babelfish tutorial, but have been encountering some interesting problems when trying to get it to recognize multiple RFID cards. I made a post over on the Adafruit forums but haven’t had any luck with it yet. I just thought I would see if anyone here could help me out.

Here is the code in case you don’t want to open the link:

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


#define IRQ 6 // this trace must be cut and rewired!
#define RESET 8

Adafruit_NFCShield_I2C nfc(IRQ, RESET);

SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the volumes root directory
FatReader file; // This object represent the WAV file for a pi digit or period
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
/*
* Define macro to put error messages in flash memory
*/
#define error(msg) error_P(PSTR(msg))

//////////////////////////////////// SETUP

void setup() {
  // set up Serial library at 9600 bps
  Serial.begin(9600);
  
  PgmPrintln("Pi speaker");
  
  if (!card.init()) {
    error("Card init. failed!");
  }
  if (!vol.init(card)) {
    error("No partition!");
  }
  if (!root.openRoot(vol)) {
    error("Couldn't open dir");
  }

  PgmPrintln("Files found:");
  root.ls();
  
  // find Adafruit RFID/NFC shield
  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();

}

/////////////////////////////////// LOOP

unsigned digit = 0;

void loop() {
  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 RFID card to show up!
  Serial.println("Waiting for an ISO14443A Card ...");

    
  // 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);

  uint32_t cardidentifier = 0;
  
  if (success) {
    // Found a card!

    Serial.print("Card detected #");
    // turn the four byte UID of a mifare classic into a single variable #
    cardidentifier = uid[3];
    cardidentifier <<= 8; cardidentifier |= uid[2];
    cardidentifier <<= 8; cardidentifier |= uid[1];
    cardidentifier <<= 8; cardidentifier |= uid[0];
    Serial.println(cardidentifier);

  // repeat this for loop as many times as you have RFID cards
    if (cardidentifier == 3266796292) {
      playcomplete("cfalc.WAV");
    }
    if (cardidentifier == 1519730948) {
      playcomplete("samus.WAV");
    }  
    if (cardidentifier == 3125957124) {
      playcomplete("lmac.WAV");
    }  
    if (cardidentifier == 2456861188) {
      playcomplete("fox.WAV");
    }  
    if (cardidentifier == 3270290948) {
      playcomplete("wft.WAV");
    }  
    if (cardidentifier == 3398987780) {
      playcomplete("villager.WAV");
    }  
    if (cardidentifier == 2186368004) {
      playcomplete("marth.WAV");
    }  
    if (cardidentifier == 2057060100) {
      playcomplete("yoshi.WAV");
    }
    if (cardidentifier == 581738756) {
      playcomplete("pit.WAV");
    }  
    if (cardidentifier == 1648956676) {
      playcomplete("kirby.WAV");
    }  
    if (cardidentifier == 1653835268) {
      playcomplete("pikachu.WAV");
    }  
    if (cardidentifier == 719015684) {
      playcomplete("link.WAV");
    } 
    if (cardidentifier == 3264737284) {
      playcomplete("luigi.WAV");
    }
    if (cardidentifier == 3259030020) {
      playcomplete("luigi2.WAV");
    }
    if (cardidentifier == 851602436) {
      playcomplete("diddy.WAV");
    } 
    if (cardidentifier == 3673369860) {
      playcomplete("dk.WAV");
    }
    if (cardidentifier == 2458258948) {
      playcomplete("peach.WAV");
    }
    if (cardidentifier == 2588707844) {
      playcomplete("zelda.WAV");
    } 
    if (cardidentifier == 3401629188) {
      playcomplete("mario.WAV");
    }
  }
}

/////////////////////////////////// HELPERS

/*
* print error message and halt
*/
void error_P(const char *str) {
  PgmPrint("Error: ");
  SerialPrint_P(str);
  sdErrorCheck();
  while(1);
}
/*
* print error message and halt if SD I/O error
*/
void sdErrorCheck(void) {
  if (!card.errorCode()) return;
  PgmPrint("\r\nSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  PgmPrint(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
/*
* Play a file and wait for it to complete
*/
void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying);
  
  // see if an error occurred while playing
  sdErrorCheck();
}
/*
* Open and start playing a WAV file
*/
void playfile(char *name) {
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  if (!file.open(root, name)) {
    PgmPrint("Couldn't open file ");
    Serial.print(name);
    return;
  }
  if (!wave.create(file)) {
    PgmPrintln("Not a valid WAV");
    return;
  }
  // ok time to play!
  wave.play();
}

The problem is that when I have it try to recognize all of the cards I want to use, (using the “if” statements in the loop) it seems to repeat the beginning of the sketch over and over. It seems like it tries to print “Pi Speaker” and “Files Found:” simultaneously and repeatedly (See the Adafruit post for details from the serial monitor). I can comment out some of the “if” statements and that will allow the sketch to run perfectly. It doesn’t seem to matter which ones I comment out, it all has the same effect. Thanks for your help!

    if (cardidentifier == 3266796292) {

Does that look like an int to you? Try:

    if (cardidentifier == 3266796292UL)
    { // Down here, where it belongs

Hmmm, didn't seem to fix anything, but it does look better!

didn't seem to fix anything

As in "does not play the correct song" or as in "does not result in a match"? Which problem are we trying to solve?

PaulS: As in "does not play the correct song" or as in "does not result in a match"? Which problem are we trying to solve?

I'm still getting the strange readouts in the serial monitor when I don't comment out any of those conditions. If I do this, it works just fine. But the more conditions I uncomment, the more messed the sketch gets, until it reaches the point where it won't run at all.

// repeat this for loop as many times as you have RFID cards
    if (cardidentifier == 3266796292) {
      playcomplete("cfalc.WAV");
    }
    if (cardidentifier == 1519730948) {
      playcomplete("samus.WAV");
    }

    /* 
    if (cardidentifier == 3125957124) {
      playcomplete("lmac.WAV");
    }  
    if (cardidentifier == 2456861188) {
      playcomplete("fox.WAV");
    }  
    if (cardidentifier == 3270290948) {
      playcomplete("wft.WAV");
    }  
    if (cardidentifier == 3398987780) {
      playcomplete("villager.WAV");
    }  
    if (cardidentifier == 2186368004) {
      playcomplete("marth.WAV");
    }  
    if (cardidentifier == 2057060100) {
      playcomplete("yoshi.WAV");
    }
    if (cardidentifier == 581738756) {
      playcomplete("pit.WAV");
    }  
    if (cardidentifier == 1648956676) {
      playcomplete("kirby.WAV");
    }  
    if (cardidentifier == 1653835268) {
      playcomplete("pikachu.WAV");
    }  
    if (cardidentifier == 719015684) {
      playcomplete("link.WAV");
    } 
    if (cardidentifier == 3264737284) {
      playcomplete("luigi.WAV");
    }
    if (cardidentifier == 3259030020) {
      playcomplete("luigi2.WAV");
    }
    if (cardidentifier == 851602436) {
      playcomplete("diddy.WAV");
    } 
    if (cardidentifier == 3673369860) {
      playcomplete("dk.WAV");
    }
    if (cardidentifier == 2458258948) {
      playcomplete("peach.WAV");
    }
    if (cardidentifier == 2588707844) {
      playcomplete("zelda.WAV");
    } 
    if (cardidentifier == 3401629188) {
      playcomplete("mario.WAV");
    }
    */

Well I think I figured it out. Apparently I've been running out of memory and that's what has been causing my issues. Anyone have any ideas to optimize the code?

  Serial.println("Waiting for an ISO14443A Card ...");

String literals take up space in SRAM, unnecessarily.

Serial.println(F(“Waiting for an ISO14443A Card …”));
Use the F() macro to keep them out of SRAM.

PaulS:

  Serial.println("Waiting for an ISO14443A Card ...");

String literals take up space in SRAM, unnecessarily.

Serial.println(F(“Waiting for an ISO14443A Card …”));
Use the F() macro to keep them out of SRAM.

Awesome, that helped free up enough space! Thanks!