avoiding interference between music maker shield and RFID RC522

Hello,

I'm working on a project where I can play audio files when reading out RFID tags. Each tag is coupled to a specific sound.

I've been able to make a prototype that uses arduino for the ID recognition and uses processing on my laptop to play the audio files.

I've ordered an adafruit music maker shield VS1053 so I don't need the connection with my laptop anymore to play the audio files. I've been able to let the example file work (player_simple). But when I connect the RFID reader even without changing the code, the example doesn't work anymore. It says: Adafruit VS1053 Simple Test
Couldn't find VS1053, do you have the right pins defined?

When I pull out pin 12 from my RFID reader it does work again. Then it says: Adafruit VS1053 Simple Test
VS1053 found
Playing track 001

Pin 12 on the RFID reader equals MISO. I thought MISO (12), MOSI (11) and SCK (13) pins can be shared.
Why does there seem to be some interference between the RFID RC522 and music maker shield on pin 12 and how can I solve this?

Here's a link with the connection of the RFID RC522.
rfid rc5 - Google Search ... 8nJlCkM%3A

Thanks,

Marieke

I thought MISO (12), MOSI (11) and SCK (13) pins can be shared.

Only if there is a separate chip enable for each device.

Would it help to use a seperate nfc shield like this one? http://www.dx.com/nl/p/nfc-shield-rfid-rc522-rf-ic-card-sensor-module-s50-rfid-smart-card-for-arduino-uno-mega2560-383996#.VoU9ilKWXVI

they claim to be compatible with an mp3 module

they claim to be compatible with an mp3 module

No they don't, they say:-

It also lead out the UART interface which can be connect with Serial Bluetooth module or Serial Wifi module, Serial MP3 Player module and D3 / D4 port that can connect to I2C OLED module.

Which is not the same as saying that it will work with your MP3 player.

That page was very poor at telling you what the interface actually is.

We've managed to solve the problem. For some reason the SPI communication didn't work properly, although the MP3 and RFID board didn't use the same pins except for the SPI pins (11,12,13). Both boards used a seperate enable pin.
We solved it by implementing an optocoupler.

We solved it by implementing an optocoupler.

I think solved is too strong a statement. Maybe you side stepped it. The opto probably just inverted the signal and it was this inversion that cleared up the problem.

Do you know that there are four modes that the SPI can operate in, but only one mode that your device requires. Two devices on the same SPI bus might require different SPI modes and this would make one of them not work.

See:-

I've looked at it together with a colleague, but for some reason the RFID RC522 keeps given interference even if we set the communication on low or high or change the mode. So we implemented an opto. This way we can first start the mp3 shield and only after succesfull playing a test sound, we startup the communication with the RFID.
It's not really clear why the RFID shield gives interference, but with the optocoupler we managed to get around this error.

What Mar91 meant by the implementing of the optocoupler is that we used one to turn of the RFID reader while the mp3 module was started.

So now the code first starts connection with the MP3 board, then the sd card (both spi).
But the RFID was powerless. (MISO and MOSI pins remain connected).
Only when we had positive feedback that the MP3 was started up correct we turned on the power to the RFID module (the 3.3V VCC) using an optocoupler powered by an other arduino digital output.

Must admit it is not the cleanest solution, but the RFID blocked the data of the MP3 at startup. Not sure how or why, the select pin was low as specified in the documentation but hey, time is money so this was easyer for now.

Jokohoko, colleage of Mar91

implementing of the optocoupler is that we used one to turn of the RFID reader while the mp3 module was started.

Why would you want to use an optocoupler for that?

It sounds more smoke an mirrors by the second.

Can you draw a schematic of what "works"?

I had the same problem as this and found this thread after googling it. I thought I'd reply as I ended up working out a solution that worked for me after reading this thread that is software only which might help someone who googles the same problem.

As mentioned there is interference with the rfid reader when music is playing so the solution for me was to not access the rfid reader while a sound is playing. I'm actually using a geetech VS1053 shield which uses SparkFun's SFEMP3Shield library which has an isPlaying() method which returns 1 if a sound is playing. The code below solved the issue for me and stopped my arduino randomly crashing

if(MP3player.isPlaying() < 1)
  {
     // A method I created that wraps up RFID reading
     processRfid();
  }

The reason why this worked for you is that the playing of the sound file was using the same SPI bus resources as the RFID reader. This would not have happened with either device being controlled on a different bus.

I'm not sure that was an option with the components I had. The MP3 player is a shield and and connects to the SPI bus pins and the RFID breakout board that I had also needed to connect to the same bus. I was considering buying different components but managed to get it to work satisfactorily in the end as I dont really need to read the RFID while the sound is playing.

I'm not sure that was an option with the components I had.

Yes it was.
If two mutually exclusive devices need the SPI bus at the same time you can always put on of them onto three other pins and bit bang the bus protocol.

Hi Grumpy_Mike,

I too am stuck around a similar issue though I have been trying to use two different SS pins. It seems that you are a god of SPI so I thought I'd ask for your help.

Basically I have the 522 RFID card and I've set the SS pin to 6. I have the adafruit Wave shield which by default is using SS pin 10. With two separate sketches (the library examples slightly modified) they work fine. But when put together they don't.

I'm trying to make an rfid tag based music player for my 3 year old but failing so far :frowning:

I believe I have done the correct thing by by first setting the SS pin 10 to LOW and SS pin 6 to HIGH to play the initial startup chime. This works. The then I reverse this to pin 6 is HIGH and initialise the RFID card and wait for a card to be read. It reads it ok and matches to a particular WAV file. Then SS pin 6 set HIGH again and pin 10 LOW and tried to play but fails at this point with Couldn't open file error.

I appreciate this thread has talked about other methods to separate these cards from running at the same time on SPI, but if possible I want to get this working as intended, as two different SPI devices using 2 different SS pins. Any help would be appreciated.

/*

  Combined RFID and WAV player sketch
*/
#include <SdReader.h>
#include "WaveUtil.h"
#include "WaveHC.h"

// Using SPI hardware serial. I need to use 2 different SS channels
// and set one to Low and others to high when using a selected channel.
// I need to use two different SS pins

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

#define SS_PIN_RFID 6
#define RFIDResetPin 9 // same reset pin I think is ok

byte readCard[4];
boolean debug = true;

//  define tag id list and tracks to play
#define NUMTAGS 2

byte tagid[2][4] = {{0xE0, 0x45, 0xA1, 0x7C},
  {0x2E, 0xDC, 0xE4, 0x5E}
};

// no longer than 8 char file name plus ext
String track[NUMTAGS] = {"TRACK001.wav",
                         "TRACK002.wav"
                        };

//  audio settings
boolean PlayComplete = true;
long playnext_prevmillis = 0;
long playanother_time = 3000;

//  sdcard settings
SdReader card;
FatVolume vol;
FatReader root;
FatReader f;

WaveHC wave;

// Set up mfrc522 object instance
MFRC522 mfrc522(SS_PIN_RFID, RST_PIN);


void setup() {
  Serial.begin(9600);
  //  set output pins for DAC control for Wav player
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  pinMode(SS_PIN, OUTPUT); //WAV SS pin
  pinMode(SS_PIN_RFID, OUTPUT); //new RFID SS pin

  // set Wave player SS active
  digitalWrite(SS_PIN_RFID, HIGH);
  digitalWrite(SS_PIN, LOW);

  // pin13 LED
  pinMode(13, OUTPUT);

  if (!card.init()) {
    putstring_nl("Card init. failed!");
    sdErrorCheck();
    while (1);
  }

  // enable optimize read
  card.partialBlockRead(true);

  // fat partition?
  uint8_t part;
  for (part = 0; part < 5; part++) {
    if (vol.init(card, part))
      break;
  }
  if (part == 5) {
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();
    while (1);
  }

  // show infos
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(), DEC);

  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!");
    while (1);
  }

  // Whew! We got past the tough parts.
  putstring_nl("Files found (* = fragmented):");

  // Print out all of the files in all the directories - just for debugging
  root.ls(LS_R | LS_FLAG_FRAGMENTED);

  SPI.begin(); // Init SPI bus

  // play startup chime
  delay(500);  // avoid loudspeaker click noise
  playcomplete("CHIME.WAV");

  // set RFID SS active
  digitalWrite(SS_PIN_RFID, LOW);
  digitalWrite(SS_PIN, HIGH);
  mfrc522.PCD_Init(); // Init MFRC522
  putstring_nl("> rfid ready");



}

void loop() {

  // set RFID SS active ready to read tags
  digitalWrite(SS_PIN_RFID, LOW);
  digitalWrite(SS_PIN, HIGH);

  ReadTAG();

}

// Read tag and output the ID in the serial monitor.
void ReadTAG() {

  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
    for (int i = 0; i < 4; i++) {
      readCard[i] = mfrc522.uid.uidByte[i];
    }

    //  check tag and play track if tag id found
    checkTag(readCard, 4);

    // If the TAG was read then the reading stops as it continues many times otherwise.
    mfrc522.PICC_HaltA();
  }
}

void checkTag(byte tag[], int sizeT) {
  if (strlen(tag) == 0) return;

  if (debug) {
    // print out all elements to check they came through
    Serial.print("rfid: ");
    for (int d = 0; d < sizeT; d++) {
      Serial.print(tag[d], HEX);

    }
  }

  boolean matching = true;
  //  read each array row and compare tag id byte by byte
  for (int a = 0; a < 2; a++) {
    matching = true;
    //     loop through each byte of the RFID until one doesn't match, then jump out and read next record
    for (int c = 0; c < sizeT; c++) {
      if (tag[c] != tagid[a][c]) {
        matching = false;
        break;
      }
    }

    //  in case of a match play the track
    if (matching) {
      // set Wave player SS active ready to play
      digitalWrite(SS_PIN_RFID, HIGH);
      digitalWrite(SS_PIN, LOW);

      Serial.print(" now playing: "); Serial.println(track[a]);
      delay(500);  // avoid loudspeaker click noise
      if (PlayComplete) {
        digitalWrite(RFIDResetPin, LOW);
        //        playcomplete(track[a]);
        playcomplete("Track001.wav");  //hardcoded track as above errors coverting string to char*
      } else {
        unsigned long playnext_currentmillis = millis();
        // wait with playing another audio track
        if (playnext_currentmillis - playnext_prevmillis > playanother_time) {
          //          playfile(track[a]);
          playfile("Track001.wav"); //hardcoded track as above errors coverting string to char*
          playnext_prevmillis = playnext_currentmillis;
        }
      }
      break;
    }
  }
}

void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying) {
    // playing
  }
}

void playfile(char *name) {
  if (wave.isplaying) {
    wave.stop();
  }


  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.println(name); return;
  }
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }

  wave.play();
}


void sdErrorCheck(void) {
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while (1);
}

I suspect this needs to occur sooner in setup(), before you do the card reads (using SPI).
SPI.begin(); // Init SPI bus

Thank you CrossRoads for the reply. The initial read from the SD card works as it plays the chime.wav startup file ok. It's only later when it returns from the matched RFID card read that it fails to open the SD card file. I've moved SPI.begin though on your recommendation. It hasn't made a difference unfortunately.

/*

  Combined RFID and WAV player sketch
*/
#include <SdReader.h>
#include "WaveUtil.h"
#include "WaveHC.h"

// Using SPI hardware serial. I need to use 2 different SS channels
// and set one to Low and others to high when using a selected channel.
// I need to use two different SS pins

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

#define SS_PIN_RFID 6
#define RFIDResetPin 9 // same reset pin I think is ok

byte readCard[4];
boolean debug = true;

//  define tag id list and tracks to play
#define NUMTAGS 2

byte tagid[2][4] = {{0xE0, 0x45, 0xA1, 0x7C},
  {0x2E, 0xDC, 0xE4, 0x5E}
};

// no longer than 8 char file name plus ext
String track[NUMTAGS] = {"TRACK001.wav",
                         "TRACK002.wav"
                        };

//  audio settings
boolean PlayComplete = true;
long playnext_prevmillis = 0;
long playanother_time = 3000;

//  sdcard settings
SdReader card;
FatVolume vol;
FatReader root;
FatReader f;

WaveHC wave;

// Set up mfrc522 object instance
MFRC522 mfrc522(SS_PIN_RFID, RST_PIN);


void setup() {
  Serial.begin(9600);
  //  set output pins for DAC control for Wav player
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  pinMode(SS_PIN, OUTPUT); //WAV SS pin
  pinMode(SS_PIN_RFID, OUTPUT); //new RFID SS pin

  // set Wave player SS active
  digitalWrite(SS_PIN_RFID, HIGH);
  digitalWrite(SS_PIN, LOW);

  // pin13 LED
  pinMode(13, OUTPUT);

  SPI.begin(); // Init SPI bus

  if (!card.init()) {
    putstring_nl("Card init. failed!");
    sdErrorCheck();
    while (1);
  }

  // enable optimize read
  card.partialBlockRead(true);

  // fat partition?
  uint8_t part;
  for (part = 0; part < 5; part++) {
    if (vol.init(card, part))
      break;
  }
  if (part == 5) {
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();
    while (1);
  }

  // show infos
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(), DEC);

  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!");
    while (1);
  }

  // Whew! We got past the tough parts.
  putstring_nl("Files found (* = fragmented):");

  // Print out all of the files in all the directories - just for debugging
  root.ls(LS_R | LS_FLAG_FRAGMENTED);

  // play startup chime
  delay(500);  // avoid loudspeaker click noise
  playcomplete("CHIME.WAV");

  // set RFID SS active
  digitalWrite(SS_PIN_RFID, LOW);
  digitalWrite(SS_PIN, HIGH);
  mfrc522.PCD_Init(); // Init MFRC522
  putstring_nl("> rfid ready");



}

void loop() {

  // set RFID SS active ready to read tags
  digitalWrite(SS_PIN_RFID, LOW);
  digitalWrite(SS_PIN, HIGH);

  ReadTAG();

}

// Read tag and output the ID in the serial monitor.
void ReadTAG() {

  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
    for (int i = 0; i < 4; i++) {
      readCard[i] = mfrc522.uid.uidByte[i];
    }

    //  check tag and play track if tag id found
    checkTag(readCard, 4);

    // If the TAG was read then the reading stops as it continues many times otherwise.
    mfrc522.PICC_HaltA();
  }
}

void checkTag(byte tag[], int sizeT) {
  if (strlen(tag) == 0) return;

  if (debug) {
    // print out all elements to check they came through
    Serial.print("rfid: ");
    for (int d = 0; d < sizeT; d++) {
      Serial.print(tag[d], HEX);

    }
  }

  boolean matching = true;
  //  read each array row and compare tag id byte by byte
  for (int a = 0; a < 2; a++) {
    matching = true;
    //     loop through each byte of the RFID until one doesn't match, then jump out and read next record
    for (int c = 0; c < sizeT; c++) {
      if (tag[c] != tagid[a][c]) {
        matching = false;
        break;
      }
    }

    //  in case of a match play the track
    if (matching) {
      // set Wave player SS active ready to play
      digitalWrite(SS_PIN_RFID, HIGH);
      digitalWrite(SS_PIN, LOW);

      Serial.print(" now playing: "); Serial.println(track[a]);
      delay(500);  // avoid loudspeaker click noise
      if (PlayComplete) {
        digitalWrite(RFIDResetPin, LOW);
        //        playcomplete(track[a]);
        playcomplete("Track001.wav");  //hardcoded track as above errors coverting string to char*
      } else {
        unsigned long playnext_currentmillis = millis();
        // wait with playing another audio track
        if (playnext_currentmillis - playnext_prevmillis > playanother_time) {
          //          playfile(track[a]);
          playfile("Track001.wav"); //hardcoded track as above errors coverting string to char*
          playnext_prevmillis = playnext_currentmillis;
        }
      }
      break;
    }
  }
}

void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying) {
    // playing
  }
}

void playfile(char *name) {
  if (wave.isplaying) {
    wave.stop();
  }


  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.println(name); return;
  }
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }

  wave.play();
}


void sdErrorCheck(void) {
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while (1);
}

I have the adafruit Wave shield

That software uses the SPI port to access the SD card and bit bangs the SPI protocol for the D/A converter, so that alone is a good example of what I was saying.

I have not looked too closely into your specific setup but it is the SD card that prevents you using the SPI bus for anything else when there is a file open on the card. This is because the SD card, when it sees the chip enable go high, which it needs to in order to relinquish the bus finishes the read / auto increment sequence and it is this internal counter that is lost.

I think it would be better to bit bang the SD card and use the hardware SPI bus for the RFID and the D/A, but I haven't tried this. Also it would need the rewriting of both libraries and rewiring of both the interfaces.

Alternately you could patch the RFID libiary to use the same bit banging as the D/A. The other problem is that the AdaFruit wav shield software runs under interrupt so unless you go through quite a few hoops it is difficult to ensure that an RFID SPI transaction is not interrupted by a D/A transaction.

Thanks for the response Grumpy_Mike. From what you are saying, bit banging the RFID might be an easier option to code. I am not experienced at this yet, I have to google to find out what it meant. An ECE Blog: Bit Banging Data with the Arduino
Though I'm still not clear on how I would achieve that. Looking through many posts on this forum and adafruit I see very similar posts but nobody seems to have got it working properly.

I also see that I2C is an option on the PN532 RFID breakout board and I wonder if it would be possible to run the RFID on I2C and then music shield/Sd reader on SPI. I also have an RFID 522 board which I could use instead?

I think I've bitten off more than I can chew here but I want to succeed even if I have to consider changing some hardware. e.g. What if I used a Mega Arduino as it has 4 serial UARTS instead of 1?

While the RC522 chip may be capable of I2C and serial options a lot of the cheap RC522 based boards are designed in such a way that this is not possible.
There's an example of bit banging the SPI port in the AdaFruit wav shield library. This bit bangs the D/A chip with an SPI protocol.