Hi All
I am working an Arduino based RFID card reader project.
The core of the project is to read two different cards from one reader, return the IDs of the cards and then exit when 2 distinct cards are read. The system will have multiple readers eventually, so I am using a case switch in the main loop that waits for a command to tell it which reader to use (only 1 reader is defined and one instance of the reader created so far). Once that command is received a second function is then called and in this function we record the card IDs and then when 2 are found it exists the function and goes back to waiting for the switch to be triggered again.
The aforementioned second function sits within a loop, looking a variable called "Cardreadcycle". While this variable is less than 2, the function starts looking for a card. When a card is found, a variable called "CurrentCardId" is set too empty, then the card UID is stored into this variable. Once the full UID has been stored in the variable we then check if this UID is the same as the UID in another variable named "PreviousCardId". Provided it isn't we print the "CurrentCardId" to serial, copy it to the "PreviousCardId" variable and we up the "Cardreadcycle" and start the while loop again. Once a second disctinct card is found we print the new "CurrentCardId" to serial, and up the "Cardreadcycle", as a result of this now being 2, we exit the loop, print to serial confirmation of 2 unique cards being found and clear our variables "CurrentCardId" and "PreviousCardId", and go back to waiting for a command as to which reader to use.
The sketch does pretty much does exactly as it should, except for the fact that somewhere, it keeps seeming to store the previous card ID. When I trigger the next read of cards it immediately finds the 2nd card found in the previous scan and records it as the first card in the next loop. I have been over and over this and just cannot see why.
Please help me Arduino forum... you're my only hope!
Code in post below
* -----------------------------------------------------------------------------------------
* MFRC522 Arduino Arduino Arduino Arduino Arduino
* Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
* Signal Pin Pin Pin Pin Pin Pin
* -----------------------------------------------------------------------------------------
* RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
* SPI SS SDA(SS) 10 53 D10 10 10
* SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
* SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
* SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
*
*/
#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
String PreviousCardId;
String CurrentCardId;
int ReaderId;
int MaxNoCards;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
/**
* Initialize.
*/
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
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println("Please choose an option:");
MaxNoCards = 2;
}
void loop() {
// read the sensor:
if (Serial.available() > 0) {
int inByte = Serial.read();
// do something different depending on the character received.
// The switch statement expects single number values for each case;
// in this exmaple, though, you're using single quotes to tell
// the controller to get the ASCII value for the character. For
// example 'a' = 97, 'b' = 98, and so forth:
switch (inByte) {
case '1':
Serial.println("Scanning Cards on Reader 1... Function will remain open until two unique cards are found!");
ReaderId = 1;
CardScan();
break;
case '2':
Serial.println("Scanning Cards on Reader 2... Function will remain open until two unique cards are found!");
ReaderId = 2;
CardScan();
break;
default:
Serial.println("No option selected");
break;
}
}
}
void CardScan() {
int Cardreadcycle = 0;
while (Cardreadcycle < MaxNoCards){
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
}
CurrentCardId = "";
for (int i = 0; i < mfrc522.uid.size; i++) { //
CurrentCardId = CurrentCardId + mfrc522.uid.uidByte[i];
}
if (CurrentCardId != PreviousCardId)
{
Cardreadcycle++;
Serial.print("*");
Serial.print(ReaderId);
Serial.print("^");
Serial.print(Cardreadcycle);
Serial.print("|");
Serial.println(CurrentCardId);
PreviousCardId = CurrentCardId;
}
mfrc522.PICC_HaltA(); // Stop reading
}
Serial.println("Two cards have been read, function closed");
CurrentCardId = "";
PreviousCardId = "";
mfrc522.PICC_HaltA(); // Stop reading
}
I can't find the error, either. I have a similar project on a NodeMcu, but your code gives me a WDT crash one second after entering "1" or "2". This is because the cardScan function is a blocking function. In general you don't want blocking code.
I would separate the cardscan from the logic that follows.
Here is the loop function from my project. Maybe it will help.
//============================= Loop =============================
void loop() {
// Look for new cards
if ( ! rfid.PICC_IsNewCardPresent())
return;
// Verify if the NUID has been read
if ( ! rfid.PICC_ReadCardSerial())
return;
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
Serial.println(rfid.PICC_GetTypeName(piccType));
// Check is the PICC of Classic MIFARE type
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
Serial.println(F("Your tag is not of type MIFARE Classic."));
return;
}
// A new card has been detected.
cardId = 0;
// Store NUID into nuidPICC array
for (byte i = 0; i < 4; i++) {
nuidPICC[i] = rfid.uid.uidByte[i];
cardId = cardId + nuidPICC[i]; //Make the card ID
}
char buf [6];
sprintf (buf, "%04i", cardId);
client.publish(msgTopic, buf);
Serial.println(buf);
Serial.print(F("cardId= "));
Serial.print(cardId);
Serial.println();
// Halt PICC
rfid.PICC_HaltA();
// Stop encryption on PCD
rfid.PCD_StopCrypto1();
delay(450); // Prevents accidental duplicate reads
}
Hope this helps.