Babelfish Wave shield - can't use more than 11 cards
Moderators: adafruit_support_bill, adafruit

Babelfish Wave shield - can't use more than 11 cards

by Jenesis on Wed Nov 28, 2012 4:46 pm

Hi there,

I've got my Babelfish working fine with the demo code provided, but it suddenly stops working if I try to add more than 11 card IDs to the loop() method. But the strange thing is the way it breaks - if I have 12 or more if statements, the system doesn't even start up properly - it doesn't even manage to print out the list of files on the SD card. If I put the full 20 cards I was planning on using, the code throws errors constantly. I'm wondering if there's some kind of timing issue I'm falling foul of. The code isn't too big to be uploaded to the Arduino (it's 14K out of 32K), but something is amiss. Any ideas?
Last edited by Jenesis on Thu Nov 29, 2012 7:57 am, edited 1 time in total.
Jenesis
 
Posts: 6
Joined: Sun Oct 21, 2012 5:39 pm

Re: Babelfinsh Wave shield - can't use more than 11 cards

by adafruit_support_bill on Thu Nov 29, 2012 6:54 am

Sounds like you might be running out of RAM. If you post your sketch we can take a look at ways to reduce RAM usage.
User avatar
adafruit_support_bill
 
Posts: 30887
Joined: Sat Feb 07, 2009 10:11 am

Re: Babelfish Wave shield - can't use more than 11 cards

by Jenesis on Thu Nov 29, 2012 7:56 am

Here's the code - it's pretty much unchanged from the code from the Babelfish tutorial. I've modified it to deal with Ultra cards (7-byte IDs rather than just 4). The only other change I made was to stop it printing out the list of files it finds, to try to reduce the amount of code being run. This didn't help much.

As you can probably gather from the filenames, the aim is to have the device say a different fruit for every card. I've got 20 sound files and 20 cards ready, but I can't use more than 11.

Code: Select all | TOGGLE FULL SIZE
    #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);
    if (!card.init()) {
    error("Card init. failed!");
    }
    if (!vol.init(card)) {
    error("No partition!");
    }
    if (!root.openRoot(vol)) {
    error("Couldn't open dir");
    }
   
    // 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);
     
    uint64_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 #
    for (int i=0; i<uidLength; i++) {
      cardidentifier <<=8;
      cardidentifier |= uid[i];
    }
     
    // repeat this for loop as many times as you have RFID cards
    if (cardidentifier == 0xDD3D57D0) { // this is the card's unique identifier
    playcomplete("APPLE.WAV"); // these are file names for the sample audio files - change them to your own file names
    }
    if (cardidentifier == 0x7AF2D765) {
    playcomplete("ORANGE.WAV");
    }
    if (cardidentifier == 0x48C6792B72080LL) {
    playcomplete("STRAWB~1.WAV");
    }
    if (cardidentifier == 0x4426892B72080LL) {
    playcomplete("KIWI.WAV");
    }
    if (cardidentifier == 0x4587D92B72080LL) {
    playcomplete("RHUBARB.WAV");
    }
    if (cardidentifier == 0x4577D92B72080LL) {
    playcomplete("PEACH.WAV");
    }
    if (cardidentifier == 0xFDB555D0) {
    playcomplete("PINEAP~1.WAV");
    }
    if (cardidentifier == 0xED9D55D0) {
    playcomplete("CHERRY.WAV");
    }
    if (cardidentifier == 0xAD2354D0) {
    playcomplete("COCONUT.WAV");
    }
    if (cardidentifier == 0xBD1656D0) {
    playcomplete("GRAPEF~1.WAV");
    }
    if (cardidentifier == 0x5D2655D0) {
    playcomplete("WATERM~1.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();
    }
Jenesis
 
Posts: 6
Joined: Sun Oct 21, 2012 5:39 pm

Re: Babelfish Wave shield - can't use more than 11 cards

by adafruit_support_bill on Thu Nov 29, 2012 8:40 am

No obvious big RAM usage there. Although WaveHC does need a fair amount for it's buffers.

You already have the error macro that stores your error strings in flash memory. You might benefit from using the "F()" macro for some of your other strings, such as:

change:
Code: Select all | TOGGLE FULL SIZE
        Serial.println("Waiting for an ISO14443A Card ...");

to:
Code: Select all | TOGGLE FULL SIZE
        Serial.println(F("Waiting for an ISO14443A Card ..."));


This page describes the Arduino memory limitations and how to work with them:
http://itp.nyu.edu/~gpv206/2008/04/maki ... o_mem.html
User avatar
adafruit_support_bill
 
Posts: 30887
Joined: Sat Feb 07, 2009 10:11 am