(RFID) RC522 - Reading tags in specific order

Hey all!

So my project consists of a few different pieces:

  1. An RC522 RFID sensor
  2. A 16x2 LCD
  3. Arduino UNO
  4. 16 LED neopixel circle

So, in their beginning states, the LEDs will all be red and the LCD will show "Scan Item to get clue...."

When the first tag is scanned, the LCD reads "Card ONE" and turns 4 of the LEDs green, the second tag reads "card TWO" turning 4 more LEDs green, and so on through four tags. After all 4 tags are scanned(or at least when the fourth tag is scanned) all of the LEDS would be green and the final code would be given on the LCD.

The goal is to make it so that the 4 tags connected to the RFID sensor must be scanned in a specific order. In other words, if tag 2 is scanned first, a message would show on the LCD saying the wrong card has been swiped(in my code that message is "go away"), and all of the LED's would go back to red, causing the operator to start from tag one again.

Unfortunately, in its current state, I can scan any of the tags and the corresponding LEDS will light up, as well as the corresponding message will appear on the LCD. ie. scanning tag two before scanning ANY other tag will allow it to work. Instead, I'd like it to say "Go Away" when the tag is scanned in the wrong order and have any LEDs that are green go back to red, thus restarting the process.

I am relatively new to arduino and coding in general, so I had someone else draft this for me and I just entered the correct NUIDs for the tags that I had. Unfortunately I cant contact that person for help so I reached out here instead! If i left out info let me know, There is a small reference for the wiring at the top of the code.

Here's the code:
(I also attached the file)

/*
 -----------------------------------------------------
 * Arduino                                            |
 *  Uno    RC522 |  Uno     NEOPIXEL   |   Uno    LCD |
 * ---------------------------------------------------- 
 *   9     RST   |    3     DATA IN    |   5V     VCC |
 *  10     SDA   |   GND    POWER -    |   GND    GND |
 *  11     MOSI  |   Vin    POWER 5vDC |   A4     SDA |
 *  12     MISO  |                     |   A5     SCL |
 *  13     SCK   |                     |              |
 -----------------------------------------------------
 */

#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define level
#define I2C_ADDR 0x3f 

LiquidCrystal_I2C lcd(I2C_ADDR,2,1,0,4,5,6,7);

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 3, NEO_GRB + NEO_KHZ800);

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
String Message;

void setup() {

lcd.begin(16, 2);//16 columns 2 rows for 1602A
  strip.begin();
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card
tellThem("Scan item","to get clue...");
allOff();
}

void loop() {
Message="Go Away!";
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {return;}
  if ( ! mfrc522.PICC_ReadCardSerial()) { return;}

 if (mfrc522.uid.uidByte[0] == 21 && mfrc522.uid.uidByte[1] == 13 && mfrc522.uid.uidByte[2] == 10 && mfrc522.uid.uidByte[3] == 43) {Message="Card ONE"; Card1();}
 if (mfrc522.uid.uidByte[0] == 69 && mfrc522.uid.uidByte[1] == 124 && mfrc522.uid.uidByte[2] == 19 && mfrc522.uid.uidByte[3] == 43) {Message="Card TWO"; Card2();}
 if (mfrc522.uid.uidByte[0] == 165 && mfrc522.uid.uidByte[1] == 17 && mfrc522.uid.uidByte[2] == 125 && mfrc522.uid.uidByte[3] == 241) {Message="Card THREE"; Card3();}
 if (mfrc522.uid.uidByte[0] == 181 && mfrc522.uid.uidByte[1] == 78 && mfrc522.uid.uidByte[2] == 98 && mfrc522.uid.uidByte[3] == 241) {Message="9572B"; Card4();}

tellThem(Message,"");
delay(2000);
}

void redOn(){for (int i=0; i <= 15; i++){strip.setPixelColor(i,255,0,0);} strip.show();}
void greenOn(){for (int i=0; i <= 15; i++){strip.setPixelColor(i,0,255,0);} strip.show();}
void allOff(){for (int i=0; i <= 15; i++){strip.setPixelColor(i,16,0,0);} strip.show();}
void Card1(){for (int i=0; i <= 3; i++){strip.setPixelColor(i,0,255,0);} strip.show();}
void Card2(){for (int i=4; i <= 7; i++){strip.setPixelColor(i,0,255,0);} strip.show();}
void Card3(){for (int i=8; i <= 11; i++){strip.setPixelColor(i,0,255,0);} strip.show();}
void Card4(){ for (int i=12; i <= 15; i++){strip.setPixelColor(i,0,255,0);} strip.show();}

void tellThem(String LineOne, String LineTwo)
{
  lcd.begin(16, 2);//16 columns 2 rows for 1602A
  lcd.clear();
  int L1=(16-LineOne.length())/2;
  int L2=(16-LineTwo.length())/2;
  lcd.setBacklightPin(3,POSITIVE);
  lcd.setCursor(L1,0);
  lcd.print(LineOne);
  lcd.setCursor(L2,1);
  lcd.print(LineTwo);
  lcd.setBacklight(HIGH); 
}

RFID_to_LCD.ino (2.94 KB)

The example that you started with is pure garbage. There is no excuse for anyone supplying an example that causes loop() to do NOTHING unless a tag is present.

Get rid of all the nots (!) and all the return statements. Re-organize the code so that loop() does something, as far as reading tags is concerned, when there is a tag present, and can still do stuff when there is no tag present.

You need a variable to keep track of the last tag scanned, initialized to 0. If the tag just scanned is not the proper next tag, either ignore it or cause the program to start over.

byte lastTagScanned = 0;
   byte thisTagScanned = GetTag();

   if(thisTagScanned > 0)
   {
      if(thisTagScanned == lastTagScanned + 1)
      {
          // This tag IS the proper tag
          lastTagScanned = thisTagScanned;
      }
      else
      {
          // Tag scanned out-of-order
      }
   }

Write the GetTag() function to return the tag number (1, 2, 3, or 4), not the tag value.

memcmp() can compare arrays. mfrc522.uid.uidByte is an array. Create 4 more arrays for the valid tag values. Much cleaner, and easier to maintain, than your brute-force method.