RFID Playing Card Reader

/*
   --------------------------------------------------------------------------------------------------------------------
   Sketch to scan playing card and record its card name to later display to the player on screen.
   --------------------------------------------------------------------------------------------------------------------
*/

#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
  int HandNumber = 0;
  int CardNumber = 0;
  int CardNumMax = 2;
  int ReadCardId = -1;

  String cardList[23][3]= {
    {"42217715411677129","Qh"},
    {"45517715411677129","8s"},
    {"421217715411677128","Ad"},
    {"421117715411677128","5h"},
    {"417817715411677128","5s"},
    {"48717715411677129","Kh"}, 
    {"42117715411677129","Ks"}, 
    {"424317715411677128","As"},
    {"424417715411677128","10c"},
    {"414417715411677128","6c"},
    {"423517515411677128","7s"},
    {"419717415411677128","6h"},
    {"44217415411677129","9c"},
    {"47617415411677129","3c"},
    {"4917415411677129","Ac"},
    {"44117415411677129","4h"},
    {"423217415411677128","Kd"},
    {"43517515411677128","6s"},
    {"49717415411677128","Qs"},
    {"43217415411677128","4s"},
    {"416617415411677128","3d"},
    {"49817415411677128","5c"},
    {"413217415411677128","2h"},
  };

  String readCard;

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

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(F("Scan card to see if it is recognised?"));
}

void loop() {

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
    }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
     }
    readCard = "";
    for (int i = 0; i < mfrc522.uid.size; i++) {  // 
    readCard = readCard + mfrc522.uid.uidByte[i];
    }
    Serial.println("Got this far");
    Serial.println(readCard);
     
    for(int i=0; i<23; i++) {
    if ((cardList[i][0]) == readCard &&
        ReadCardId != i)
      {
       Serial.println(cardList[i][1]);
       CardNumber++;;
       ReadCardId = i;
       break;
      }
  }

    mfrc522.PICC_HaltA(); // Stop reading
    
  if (CardNumber < CardNumMax) {
    return;
  }
  else {
    HandNumber++;
    Serial.println("Hand Number :");
    Serial.println(HandNumber);
    CardNumber = CardNumber - 2;
    ReadCardId = -1;
    delay(1500);
  }  
}

Mike

I got interupted before I could post the code.

I thought, but even with 23 cards in the array, I am only using 56% of dynamic memory?

Thanks

Anton

The card array alone takes up 506 bytes alone that is not included in that list.

Tell you what to test it, remove those two debug print lines

  Serial.println("Got this far");

and

Serial.println("Hand Number :");

and see if it works with 23 cards.

Mike

It sort of works with 23 cards now. It will recognise some of the cards in the array but not all and when it doesnt recognise the card, its truncated the readCard down to 4 characters now!

It works for some cards but not others, which I guess could be a sign of memory issues.

I have been thinking a lot about how I will expand this system with the additional 9 readers I want to use later on, and the more I think about it, the more I feel like I need to build some kind of C# front end to control this all.

Originally I had planned to read each of the 10 readers, one at a time in ascending order from 1 to 10, however the more I think about it, the more I realised this approach just had too many issues.

What if a players steps away from the game for a while? What if one of the readers has an issue and doesn't capture the hand properly? Etc Etc.

As a result, I think I am going to adjust my sketch so that based on key input, it will scan for cards on the relevant reader. For example, submitting "1" would scan reader 1 and report the results back.

I will then try to build a C# front end to control this, so that you can still scan all ten in a row without having to manually input each command, but you can also chose to just scan a selection, such as 1,3,4,5,6,10.

So i am going to re-write my sketch slightly, to make the card reading a seperate function, that can have a variable of reader ID passed in, then use a switch case statement to determine what readerID should be passed in.

Also, the more I think about it, the more I agree that the Array isn't the place to store the card name. I will either write the card name to the RFID tag itself, or maybe use a SQL database with my C# front end that has a look up table.

This SQL option will also let me record the results in a more flexible way, and maybe I can also record the actions around the card, such as what player has done what with their cards, and what actions they take as a result!

Thanks for the advice so far, I might need a bit more going forward, but I feel like I have achieved what i wanted with the POC and now its time to take it closer to end goal with this more structure approach!

Thanks

Anton

Ok, it looks like memory will be an issue going forward. Even having 10 readers will require 10 instances of the MFCR522 object and that is going to take up space.
A long switch statement can often be simplified with simple arrays.

Maybe you need something with more memory like an Arduino Zero, teensey, or even a raspberry Pi.

Mike

I had already been thinking about moving the a Mega to provide extra space.

For now, I will be doing my dev with 3 readers, which should enable to get the system running without using too much programming memory!

Thanks

Anton

Mike

I could do with your assistance again if possible?

So I have spent the past week or so working on the C# front end controller for this project.

At the same time, I ordered a Mega to ensure I don't run out of space.

I am at the point know where I want to test reading cards from the arduino and doing useful things with the output in my application.

Since I last posted, I have ammended my sketch to now include a switch, so that I can control what reader to check.

However, I now seem to have an issue where by the last read card UID seems to stay recorded somewhere?

I have tried to step through it a few times but i just can't see the problem.

If you upload the program, then hit 1 for reader one, it reads the first card, then when you place the second card, it then reads that.

However, when you then press 1 again to read the second set of cards, it immediately has the last recorded card showing as the card ID for the first card this time round, despite the fact that I am pretty sure I am setting it as a null string?

/*
   --------------------------------------------------------------------------------------------------------------------
   Sketch to scan playing card and record its card name to later display to the player on screen.
   --------------------------------------------------------------------------------------------------------------------
 * -----------------------------------------------------------------------------------------
 *             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          53         // Configurable, see typical pin layout above


  String ReadCardId;
  String readCard;
  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... Function will remain open until two unique cards are found!");
        ReaderId = 1;
        HandScan();
        break;
      case '2':
        ReaderId = 2;
        HandScan();
        break;
      default:
      Serial.println("No option selected");
    }
  }
}

void HandScan() {

  int Cardreadcycle = 0;
   while (Cardreadcycle < MaxNoCards){
      // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
     }
    // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
     }
    readCard = "";
    for (int i = 0; i < mfrc522.uid.size; i++) {  // 
    readCard = readCard + mfrc522.uid.uidByte[i];
    }
    if (readCard != ReadCardId)
      {
Cardreadcycle++;
       Serial.print("*");
       Serial.print(ReaderId);
       Serial.print("^");
       Serial.print(Cardreadcycle);
       Serial.print("|");
       Serial.println(readCard);
       ReadCardId = readCard;
      }      
    mfrc522.PICC_HaltA(); // Stop reading
  }
  Serial.println("Two cards have been read, function closed");
  ReadCardId = "";
  readCard = "";
}

I think what is happening is that you read the card and the card is still on the reader, so the chip reads it, but your code does not read the chip so the result is still in the chip. So when you change cards the result of the previous one is still stored.

The solution would be not to pay any attention to a new reading unless you interrogate the reader and find no card. Only then look for a new card.

AntonZdz:

  String ReadCardId;

String readCard;

Why are you using capital-S Strings?