RFID Playing Card Reader

Hey All

I am trying to create an RFID Playing Card Reader.

I have an Arduino Uno with the RC522 RFID reader board.

So far, I have written a sketch that looks for new PICC's and reads their UID.

Currently I only have two cards/tags, I am calling these two, Ace of Diamonds and Ace of Hearts

There is then a simple If/Else statement that checks to see if the UID matches the UID's (hardcoded for now) for either of these two cards. If it does, it prints a serial string to identify its card name. If it doesn't match either, it prints a string to say that the card is not registered. This is all outputed to the Serial Monitor at present.

What I want to be able to do is receive the UID, determine the card name based on the UID (hardcoded at present), record once two cards have been read, log that as a "hand" and assign a hand number to it.

The next step is then based on a button click on a GUI for the application I will write, to check again, determine card name, record the two cards, incriment the hand number and then store it.

So for example, two cards are placed on the reader, they are noted as Ace of Diamonds and Ace of Hearts and recorded as Hand number 1.

A button is pressed.

Two new cards are placed on the reader, they are noted as King of Spades and King of Clubs and recorded as Hand Number 2.

I guess for now, I could use a time delay to pause the program and then check again, until the GUI is ready?!

I think ideally I want to log this data into a database (via the USB connection to the PC), so that I can then write said GUI to display the cards.

I am just looking for some general advice on how to go from where I am to where I want to be, as well some advice on how feasable this all is?

Thanks

Anton

So, I managed to get a little further last night.

My New sketch, reads a card, compares its UID with the first hard coded UID. If it matches, it increases Card1Read variable by 1, and increases CardNumber variable by 1 then prints the card name.
It then loops back and checks again, if the UID is the same as first time, it now says card already scanned (it does this by checking the UID and if the Card1Read variable is > 0).

It loops back again, if the UID is the second hard carded UID, it will then print the card name, and increase Card2Read variable by 2 as well the CardNumber variable by 1.

A seperate If statement at the bottom waits to see if CardNumber is >= 2. If it is < than 2 (so only one card has been found so far), then it loops back and checks again.

If its >= 2, then it knows it has found two unique cards, then increases HandNumber variable by 1 then prints the current hand number. Additionally this IF resets the CardNumber, Card1Read and Card2Read numbers back to 0 so the loop can start again.

This all works great, however its all hard coded.

My current plan is to store the UIDs in some kind of list/memory with UID, CardName and CardID (which will be 1 > 52).

I will then create an Array that will store the read Card ID

Then the loop will read the presented Card’s UID, if the CardID is already in the array, it will skip it and go back to start of the loop

If the CardID isn’t in the array, it will print the CardName, increase the CardNumber by 1 and add the CardID to the array.

Once the CardNumber has reached 2, it will then increase the HandNumber by 1, print the hand number, reset the CardNumber to zero and clear the array ready to loop through.

I would be grateful if anyone could off some assistance on storing the UID, CardName and CardID into memory/list. I am trying to find articles on this at present, but a pointer would be great!

Thanks

Anton

Look at storing the array in program memory. If the card number is 1 to 52 there is no need to store that in an array. Just subtract one from the card number and that is the index of the card name in the card name array.

Have you used arrays before?

Mike

Thanks for the feedback!

I have used arrays before, but not for a very long time.

I have been reading the Articles on this site, about array's in an effort to understand them a little better.

I get what you are saying about not needing the CardID as I can just use the array index, that makes sense.

With an array, you cant store associated data though can you? I need to store the Card Name for each unique card then return that when its detected.

Its also worth pointing the CardName will always be the same for each Unique CardID, so loading this into the EEPROM memory might make sense? But I dont know how I would querry that?!

What I am hoping to do is the follwoing.

The reader detects a card. It reads the UID. It then checks the list of cards (Array/eeprom, what ever is best). Based on the UID it then returns the Card Name (as stored in the list) and prints it. The reader then somehow recored that this UID has already been read (maybe based on its index in the card list to save space) in an Array called ScannedCards.

An if statement checks if the number of entries in the array ScannedCards is => 2. If not it keeps waiting for the next card.

The reader then waits for the second card (two cards are always given to the player). It reads the UID. If this UID is the same as the first card scanned then ignore it and wait for the next card (it is a standard deck of cards, so the same card can't be present in the hand twice) Once a second UID is read, it should then check the list of cards. Based on the UID it then returns the Card Name and prints it. It then records the UID or index from the card list, into the ScannedCards array.

An if statement checks if the number of entries in the array ScannedCards is =>2.

Now that it is 2, the Variable of HandNumber is increased from 0 to 1 and this hand number is printed.

Now that 2 cards have been read, the ScannedCards array should be cleared and it should start again from the top. The same card cant be read twice for the same hand, but could be given to the player two hands in a row!

I hope this makes it a bit clearer as to what I am trying to achieve.

If a number of arrays is the best way to go, then I shall I try and read more into this!

Again, thanks for the feedback so far!

With an array, you cant store associated data though can you?

Yes you can.

But I dont know how I would querry that?!

http://playground.arduino.cc/Main/PROGMEM

If a number of arrays is the best way to go,

Yes it is.

This is my page on arrays but the examples are more associated with hardware. http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

Mike

Thanks once again for your feedback.

I have read through both articles you have linked, but I am still a little confused.

I don't understand how to associate the CardUID with the CardName.

Sorry if this seems a little stupid, but I don't seem to be able to wrap my head around it.

I understand that I will need to create a series of strings, one for each CardUID, then put these in a string table.

I also understand (or hope that my understanding is correct), that I will then need to play back each of these strings one at a time, and comapre the CardUID against the ID of the card presented to the reader.

What I dont undertand is how I get from matching these two ID's, to getting the CardName associated with the ID?

I am happy to post the code I have so far, which works, but is obviously hard coded, so not great in the long run!

Thanks

I thought you said you had a card index value. Never mind it is easy enough to get one.
Have an other array of the cardUID. The first UID in it corresponds to the first entry in the card name array, and so on.
You then read a card UID and search this array until you find it in the nth entry. Then your card name is at the nth entry of your card name array.

Alternately have a two dimensional array with two elements in the second dimension, the first containing the UID and the other card name. Again search for a match with the first element with your read ID and when you find it the card name is in the second element.

Mike

I was reading into 2 dimensional array's earlier and I feel like this suits my requirements well!

So i have implemented a new version, it compiles, and uploads, but I never get a response when I place a card there.

I think there is an issue when its trying to match the cardUID it reads, with the cardUID stored?

I am also not sure if my way of making sure I don't read the same card twice is causing an issue or not.

Basically, I have a int variable called ReadCardId (which starts as 55, as 55 can never be reached).

Once a card is read, the index value of that card (readCard*) gets set as the new ReadCardId.* At the start of the if which checks whether the cardUID matches the list, it also checks if the index value of the entry in the cardList matches the ReadCardId, since we have just set that as the index of the last read card, if its the same card twice it should ignore it. I will post the code below. Thanks for the help so far!

/*
   --------------------------------------------------------------------------------------------------------------------
   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 = 55;

  String cardList[10][2]= {
    {"416B19A744D81","Qh"},
    {"437B19A744D81","8s"},
    {"4D4B19A744D80","Ad"},
    {"4D3B19A744D80","5h"},
    {"4B2B19A744D80","5s"},
    {"457B19A744D81","Kh"},
    {"415B19A744D81","Ks"},
    {"4F3B19A744D80","As"},
    {"4F4B19A744D80","10c"},
    {"490B19A744D80","6c"},
  };

  byte readCard[8];

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;
  }

    for (int i = 0; i < mfrc522.uid.size; i++) {  // 
    readCard[i] = mfrc522.uid.uidByte[i];
  }

  for(int i=0; i<52; i++) {
    
    if ((cardList[i][1]) == (readCard[i], HEX) &&
        (ReadCardId != cardList[i]))
      {
       Serial.println(cardList[i][2]);
       CardNumber++;;
       ReadCardId = (readCard[i]);
      }
      else {
       return;
      }
  }
    mfrc522.PICC_HaltA(); // Stop reading

  if (CardNumber < CardNumMax) {
    return;
  }

  else {
    HandNumber++;
    Serial.println("Hand Number :");
    Serial.println(HandNumber);
    CardNumber = CardNumber - 2;
    ReadCardId = 0;
  }
  
}

Your array contains strings but you are comparing it against a number. So you have to convert one of them to be in the same format as the other. Storing the IDs as a string is a bit wasteful as you are taking 13 bytes to store seven. I noticed that all your strings are all 13 bytes long where as they could be 14 bytes depending on the card number.

Mike

You are right, I noticed this a little while after i posted, and after having sorted a few other bits, the program now runs as I wanted it to!

So thank you for all the pointers!

Next I need to expand this to read more than one players cards at a time!

To do this I will need multiple card readers.

I want up to 10 people to be able to play this game eventually, so do you think I would be better with a mega Arduino with this many readers attached, or should my Uno do the job?

Again, thanks for all the pointers!

Anton

A Uno should do the job. Basically you need an output line for each reader to enable it before you do the read. So that is 10 lines plus the 3 SPI lines, 13 in all. The Arduino has 20 lines, and you need two for serial connections with the computer so you have 5 lines to spare. Remember that the analogue inputs can be porgramed to act as normal digital outputs as well.

Mike

Thats good to hear, I seem to have 15 digital inputs (including 1 labeled TX, 1 labelled RX, 1 labelled IORF and one labled AREF), plus the 5 analog.

I didnt realise, you could program the 5 analog to be digital! Thats very cool.

Is there any need to have a seperate RST_PIN for each reader?

I plan to read each reader in order, then disable all the readers till the next hand is dealt, to save on power consumption.

Speaking of, will I be able to run all 10 readers off the same 3.3V power output, or will I need to come up with some alternative power arrangement.

Again, thanks for the advice!

Anton

Is there any need to have a seperate RST_PIN for each reader?

No.

will I be able to run all 10 readers off the same 3.3V power output

What power output is this then? If it is the Uno's power output then no you will need an extra power supply to handle the current.

How about this to simplify things? Do not store any name or ID number in the Arduino but store the data on the card itself. That will make the program a lot shorter.

Mike

I had been thinking about doing that, and I might change it to be that way in the future, especially as I start to add more readers!

This is the 3.3v power output of the UNO at present, so I will look for a seperate power supply to power the readers!

I will ask in the electronics sub forum for a recomendation! I have also bought some proper connectors and a project box, so I can start to sort out how to get it all stored and laid out!

Ok fine. This is a look at my last RFID project, only three readers though. https://vimeo.com/172555808

Mike

Thats awesome! Really cool idea!

I like the idea of lining the bottom of your project box with wood, so that you can screw in the risers etc! I might have to steal that idea, if thats ok!

Thanks

Anton

AntonZdz: I might have to steal that idea, if thats ok!

Feel free, it's all open source. The magazine it is in is a free download as well although it is specifically for the Raspberry Pi.

Mike

Can I trouble you for some more help?

I now have the rest of my tags, so I have stuck these onto the remaining cards, meaning I now have 52 RFID enabled cards!

However, there seems to be a problem when I add more than 22 entries into my array cardList.

Having 22 entries the system works fine, as soon as i add a 23rd it stops functioning.

I have added in some extra prints to try and find out whats going wrong, and it seems that my variable readCard which is made up of the UID of the presented card in string form somehow doesnt capture all the information?

When I have 22 cards in the array, the UID of the read card is "416617415411677128".

Once there are 23 cards in the array, the UID of the read card is "11677128" which is the last 8 characters.

Obviously there is something going on, but I cant work out why?

Code to be posted below.

On another note, I might have to take up your suggestion earlier of righting the card name to the card and reading that rather than reading the UID and comparing it in an array, as I wont have enough memory to store all 52 cards!

First however, I would like to understand why its not working!

Thanks

Code to be posted below.

It is not.

Sounds to me, without looking at the code, that you are running out of memory on the Arduino.