Hi all! I'm very new to arduinos and I'm working on a project that involves 4 RFID readers reading 4 different tags. It's for an escape room puzzle and essentially there are 3 distinct sequences of the 4 tags, and the players need to put the tags on the readers in the orders of the three different sequences, one after the other. For my practice setup, I just want each sequence to light up a different LED.
I was told (and I'm not sure now if this is accurate or not) that it's best practice to use a separate arduino for each RFID reader. So for my setup I have four Arduino Unos which each read a tag through a reader and output either '0', '1', '2' or '3' through the serial port to represent which tag they've read (or '4' if no tag is read).
These are then connected to the serial ports of an Arduino Mega, which determines whether the tags are in the next correct sequence and then lights up the corresponding LED if so. The setup is like this:
The code for the unos seems to be working fine, but I'm struggling to get the mega to turn the LEDs on correctly - when I connect all of the unos to the mega, only some of the serial inputs seem to be reading correctly and others don't. This is the code I've got currently for the arduino mega:
#define RED 53
#define GREEN 51
#define BLUE 49
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
Serial2.begin(9600);
Serial3.begin(9600);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
digitalWrite(RED, LOW);
digitalWrite(GREEN, LOW);
digitalWrite(BLUE, LOW);
}
char sequences[3][4] = {
{'0', '1', '2', '3'}, // 0th sequence
{'1', '2', '3', '0'}, // 1st sequence
{'2', '3', '0', '1'}, // 2nd sequence
};
int nextSequence = 0;
bool triggered = false;
char tags[4] = {'4', '4', '4', '4'};
bool arrayEq(char arr1[], char arr2[]) {
for (int i=0; i<4; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
void loop() {
// read all data from each serial buffer to ensure we don't build up a backlog and we're reading latest data
while (Serial.available() > 0) {
tags[0] = Serial.read();
}
while (Serial1.available() > 0) {
tags[1] = Serial1.read();
}
while (Serial2.available() > 0) {
tags[2] = Serial2.read();
}
while (Serial3.available() > 0) {
tags[3] = Serial3.read();
}
// if any tags have been taken off their reader (and hence have sent data '4' to master chip), untrigger sequence
if (triggered) {
for (int i=0; i<4; i++) {
if (tags[i] == '4')
triggered = false;
break;
}
}
}
// if not triggered, compare tags to latest sequence to see if we need to trigger
else {
// trigger sequence 0 (always allowed)
if (arrayEq(sequences[0], tags)) {
triggered = true;
digitalWrite(RED, HIGH);
delay(2000);
digitalWrite(RED, LOW);
if (nextSequence == 0) nextSequence = 1;
}
// trigger sequence 1 (allowed if sequence 0 has been triggered and sequence 3 hasn't yet)
else if ((nextSequence == 1 || nextSequence == 2) && arrayEq(sequences[1], tags)) {
triggered = true;
digitalWrite(GREEN, HIGH);
delay(2000);
digitalWrite(GREEN, LOW);
if (nextSequence == 1) nextSequence = 2;
}
// trigger sequence 2 (allowed only if sequence 0 and 1 have been triggered)
else if (nextSequence == 2 && arrayEq(sequences[2], tags)) {
triggered = true;
digitalWrite(BLUE, HIGH);
delay(2000);
digitalWrite(BLUE, LOW);
nextSequence = 0;
}
}
delay(1000);
Serial.print("inputs found: ");
Serial.print(tags[0]);
Serial.print(" ");
Serial.print(tags[1]);
Serial.print(" ");
Serial.print(tags[2]);
Serial.print(" ");
Serial.print(tags[3]);
Serial.println();
}
And this is the code that each Uno is running:
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
/* Configure tag uids here */
byte uids[4][4] = {
{0xD3, 0x19, 0x67, 0xB7}, // tag 1
{0x82, 0x62, 0x7A, 0x09}, // tag 2
{0x82, 0x05, 0x7E, 0x09}, // tag 3
{0x7D, 0x47, 0x4F, 0x96} // tag 4
};
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
}
int check_uid() {
for (int i=0; i<4; i++) {
bool match = true;
for (int j=0; j<4; j++) {
if (mfrc522.uid.uidByte[j] != uids[i][j]) {
match = false;
break;
}
}
if (match) return i;
}
return 4;
}
void loop() {
// Look for new cards, and send id '4' if none exists
byte bufferATQA[2];
byte bufferSize = sizeof(bufferATQA);
MFRC522::StatusCode result = mfrc522.PICC_WakeupA(bufferATQA, &bufferSize);
if ( result != MFRC522::STATUS_OK && result != MFRC522::STATUS_COLLISION && ! mfrc522.PICC_ReadCardSerial() )
{
Serial.write('4');
Serial.flush();
delay(500);
return;
}
// Now a card is selected. Find its id and send it to the master chip
int id = check_uid();
mfrc522.PICC_HaltA(); // halt picc after using it, ready for next wake up call
char buffer [1];
char* strId = itoa(id, buffer, 10);
Serial.write(strId);
Serial.flush();
delay(500);
}
My questions are:
- is there anything wrong with the serial connection setup I've shown in the diagram above, or should this in theory work to do what I want?
- assuming the wiring setup is fine, is anything about the code dodgy
- is this whole setup overkill? Would it be possible/advisable to run it all from just one uno or one mega? Or if not, is there a better way to communicate between the 5 chips?
Many thanks in advance for any insight into any of the above