Hi Community!
I've got a problem with reliable reading from multiple (4) MFRC522-RFID-readers.
The idea is to make an "RFID-puzzle", where you have to place 4 correct tags on the matching reader to solve it.
My setup is essentially like this:
The differences are in the SS-pins (you will find it in the sketch) and it is all connected to an Arduino Nano.
// SPI-DECLARATION
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 10
#define SS_1_PIN 4
#define SS_2_PIN 5
#define SS_3_PIN 6
#define SS_4_PIN 7
#define NR_OF_READERS 4
byte ssPins[] = {SS_1_PIN, SS_2_PIN, SS_3_PIN, SS_4_PIN};
MFRC522 mfrc522[NR_OF_READERS]; // Create MFRC522 instance.
uint8_t reader;
byte uidreadarray[4][7]; // arrays for read UIDs
byte uidwinarray[4][7]; // arrays for comparing read UID (set by Eeprom)
boolean tagpresent[4]; // arrays for placed tag on readers
bool newtagispresent; // true, if a new tag is placed
//MFRC522::MIFARE_Key key;
// IO-DECLARATION
#define Button A0
// global variables
bool gamewon;
// EEPROM-DECLARATION
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
pinMode(Button, INPUT_PULLUP);
EEPROMreadUID(); // set uidwinarray
while (!Serial); // Do nothing if no serial port is opened
SPI.begin(); // Init SPI bus
checkReaders();
}
void loop() {
gamewon = false;
while (gamewon == false) {
newtagispresent = false;
for (reader = 0; reader < NR_OF_READERS; reader++) { // check all readers for a new tag
delay(1);
if (mfrc522[reader].PICC_IsNewCardPresent()) {
newtagispresent = true;
}
}
if (newtagispresent == true) { // new tag detected
readTags(); // read UID from all tags
checkWinUID(); // compare with correct UIDs
if (gamewon == false) {
Serial.println("Try again..."); // uid combination not correct, show it!
}
}
}
Serial.println("Game won!"); // uid combination is correct, show it!
while (digitalRead(Button) == HIGH) {
delay(1);
}
}
void readTags() {
byte atqa[4][2]; // for identification of tag-type
byte atqaLen = sizeof(atqa[0]);
checkReaders(); // check the readers first
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print(F("Reader :"));
Serial.print(reader);
Serial.print("\t");
delay(1);
//mfrc522[reader].PICC_RequestA(atqa[reader], &atqaLen); // buggy
mfrc522[reader].PICC_WakeupA(atqa[reader], &atqaLen);
if (atqa[reader][0] == 0x04 && atqa[reader][1] == 0) {
Serial.println("Mifare Classic");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 4; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
uidreadarray[reader][4] = 0; // fill the last 3 blocks with 0 (Classic)
uidreadarray[reader][5] = 0;
uidreadarray[reader][6] = 0;
tagpresent[reader] = true;
}
else if (atqa[reader][0] == 0x44 && atqa[reader][1] == 0) {
Serial.println("Mifare Ultralight");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 7; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
atqa[reader][0] = 0;
tagpresent[reader] = true;
}
else {
Serial.println("no valid tag present!"); // no Mifare Classic or Ultralight
atqa[reader][0] = 0;
tagpresent[reader] = false;
for (int n = 0; n < 7; n++) { // empty array for this reader
uidreadarray[reader][n] = 0;
}
}
mfrc522[reader].PICC_HaltA();
mfrc522[reader].PCD_StopCrypto1();
}
Serial.println();
outputUID();
}
void checkWinUID() { // Check if readUID is winUID
byte wincount = 0;
byte checksum = 0;
for (reader = 0; reader < NR_OF_READERS; reader++) {
for (int n = 0; n < 7; n++) {
if (uidreadarray[reader][n] == uidwinarray[reader][n]) {
wincount++;
}
checksum++;
}
}
if (wincount == checksum) {
gamewon = true;
}
}
void EEPROMreadUID() {
// read UID from Eeprom and set uidwinarray
Serial.println("Reading UIDs from Eeprom!");
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print("Reader: ");
Serial.print(reader);
Serial.print("\tADDR/VALUE:\t");
for (int n = 0; n < 7; n++) {
byte addresstoread = (reader * 10) + n + 1; // dynamic Eeprom-address
Serial.print(addresstoread);
Serial.print("/");
uidwinarray[reader][n] = EEPROM.read(addresstoread);
Serial.print(uidwinarray[reader][n]);
Serial.print("\t");
}
Serial.println();
}
}
void outputUID() {
Serial.println("showing read UID-arrays...");
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print ("Reader: ");
Serial.print (reader);
Serial.print ("\tUID:\t");
for (int n = 0; n < 7; n++) {
Serial.print (uidreadarray[reader][n]);
Serial.print ("\t");
}
Serial.println();
}
Serial.println();
}
void checkReaders() {
boolean allworking = true;
Serial.println();
Serial.println("Checking all Readers!");
for (reader = 0; reader < NR_OF_READERS; reader++) {
delay(1);
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 tag
byte verbyte = mfrc522[reader].PCD_ReadRegister(mfrc522[reader].VersionReg);
Serial.print(F("Reader "));
Serial.print(reader);
Serial.print(F(": "));
mfrc522[reader].PCD_DumpVersionToSerial();
if (verbyte != 0x92) {
allworking = false;
}
}
if (allworking == false) {
Serial.println("There is a Problem!");
}
else {
Serial.println("Readers are working");
}
Serial.println();
}
The good news first..: it does work... mostly.
My Problem is, when I play around with the tags over the readers, i.E. swapping them quickly, the readings might get "stuck".
From then on all of the readers are unable to read the UID. They continuously give the info "new tag present" as long as there is a tag on the reader, but are already failing to identify the tag type.
When this problem occurs, the only way to solve it, is to reset the Nano and then everything is well again...
The SPI-connection seems to be fine (I succesfully check the chip-version of all readers before reading the tags).
Actually this is my first project that involves SPI-communication and I don't know, how to "reset" the readers without resetting the Nano.
Does the SPI have a buffer, which might get corrupted by my handling of the tags and could be flushed after every reading?
Maybe my function of reading the tags is not what it should be like, but understanding all the functions that the library provides is a tough process..