Help with understanding for/if statement in RFID sketch

I recently purchased two RC522 RFID Reader/Writers. I've been playing with them for about three weeks and have done many hours of research and reading in an attempt to understand the programming. There are many YouTube videos and a few code examples, but very little explanation. I now seek your assistance. I found the base code below through one of those YouTube videos, and I'm able to use it, edit it, and make it work, but I don't understand some critical parts of it.

   #include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);
int greenLED = 6; 
int redLED = 4; 

void setup() {
	SPI.begin();
	mfrc522.PCD_Init();
        pinMode(greenLED,OUTPUT); //green LED
        pinMode(redLED,OUTPUT); //red LED
        Serial.begin(9600);        
}

void loop() {
        Serial.println("Scan your RFID card now.");
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
		return;
	}
        
        byte myid[4] ={0x04,0x00,0x41,0x82};   //Card B
        byte myid2[4] ={0x04,0x26,0xA5,0x82};  //Card A
        
        byte isok= 0;
        byte isok2= 0;
        
        for (byte i = 0; i < mfrc522.uid.size; i++) {
          if (mfrc522.uid.uidByte[i]==myid[i]) {
             isok= isok+1;
          }
        }
       
        for (byte i = 0; i < mfrc522.uid.size; i++) {
          if (mfrc522.uid.uidByte[i]==myid2[i]) {
             isok2= isok2+1;
          }
        }
 
        if (isok==4){
          Serial.println("Hello Emma! Welcome to my world!");
          digitalWrite(greenLED,HIGH);
           delay(2000);
           digitalWrite(greenLED,LOW);
           delay(2000);
           digitalWrite(greenLED,HIGH);   
           delay(2000);
           digitalWrite(greenLED,LOW);
           delay(2000);
           }
           
           
           if (isok2==4){
           Serial.println("Hello Benjamin. Prepare for the Robot Invasion!");
           delay(250);
           digitalWrite(greenLED,HIGH);       
           delay(250);
           digitalWrite(greenLED,LOW);
           delay(250);
           digitalWrite(greenLED,HIGH);   
           delay(250);
           digitalWrite(greenLED,LOW);
           delay(250);
           }
        
        
           else if (isok < 4){
            Serial.println("Denied!");
            digitalWrite(redLED,HIGH);
            delay(3000);
            digitalWrite(redLED,LOW);
            delay(2000);
           }
           
}

Question 1) I know that the byte myid[4] = {0x04,0x00,0x41,0x82}; is my RFID card's unique ID. I can change this and get it to register fine. What I don't understand is the [4]. What does the bracket 4 get used to do? And why does byte myid2 also use [4]?

Question 2) What are the two for/if statements doing? Correction, I believe that this is where the sketch is matching the unique ID of the card to the unique ID found in the myid[4], but I don't understand how. I'm not sure how to read this section aloud or explain it. In those if statements there is also a part that adds 1 to the isok variable. I'm not sure why this is happening.

Thank you in advance for any help in explaining how/why this functions. I know that I can continue to use it as is and get away with it, but I'd really like to understand it.

untilrobotsreplaceus:
Question 1) I know that the byte myid[4] = {0x04,0x00,0x41,0x82}; is my RFID card's unique ID. I can change this and get it to register fine. What I don't understand is the [4]. What does the bracket 4 get used to do? And why does byte myid2 also use [4]?

the array contains four elements, in your case they are bytes.

Question 2) What are the two for/if statements doing? Correction, I believe that this is where the sketch is matching the unique ID of the card to the unique ID found in the myid[4], but I don't understand how. I'm not sure how to read this section aloud or explain it. In those if statements there is also a part that adds 1 to the isok variable. I'm not sure why this is happening.

Thank you in advance for any help in explaining how/why this functions. I know that I can continue to use it as is and get away with it, but I'd really like to understand it.

it is testing for matches of the arrays and counting them. If four matches, that is a successful scan. it does this in an awkward fashion.

don't beat yourself up... the code is not written well and has a lot to do with your difficulty understanding it.

Thank you Bulldog!

I'm going to spend a few hours and see what I can do to rewrite this code. I'll repost when I'm finished and/or stuck! :slight_smile:

great!

and we can also teach you how to blink those LEDs without any blocking code...

I'm all about struggling, but there is a time to just ask for help. I've spent the better part of 5 hours trying to find a way to clean up that for/if statement combination. I thought that I could take the result of the "mfrc522.PICC_ReadCardSerial()" function, which in my mind is the unique ID (UID) and set it equal to a byte variable named currentCard. That is my code below. It doesn't work though because "ISO C++ forbids comparison between pointer and integer" or so says the error being thrown. I researched this error, but my syntax looks okay to me. Arduino Reference is amusingly silent on Pointers (http://arduino.cc/en/Reference/Pointer)

Am I way off base trying to create a a byte variable from the function? If so, what direction should I be looking? If not, can you suggest a way for me to correct my syntax?

void loop() {

byte cardA[4] ={0x04,0x00,0x41,0x82};   //Card A
byte cardB[4] ={0x04,0x26,0xA5,0x82};  //Card B
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
		return;
	}

byte currentCard = mfrc522.PICC_ReadCardSerial();       
              
        if (currentCard == cardA) {
            Serial.println("Success");
          }
        }

MFRC522.cpp (54 KB)

I've come full circle and am back to original for/if statement. I'm hoping someone can point me in the right direction.

How do I take the output of this for statement, which should be something like: 426A5821F2380 and put it into a variable so that I can perform a comparison on it? I don't care about printing it out, I just need the string of letters and numbers in a variable.

 for (byte i = 0; i < mfrc522.uid.size; i++) {
         Serial.print(mfrc522.uid.uidByte[i], HEX);
	}

Thank you!

I think I may be close... Any help would be nice.

My problem is still in the for statement... Instead of stringOne being the full 12 characters which comprise the unique ID (uid) on each RFID card, it prints out only two characters... but each time through the loop it spits out the next two characters in sequence. So, it is reading the unique ID and it is passing it to the String, but it isn't reading the full unique ID all at the same time. How can I both get it to read the full unique ID in one loop and pass it to the String?

Full Code:

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.
String stringTwo =  "4041821F2381";
void setup() {
	Serial.begin(9600);	// Initialize serial communications with the PC
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();	// Init MFRC522 card
	Serial.println("Scan PICC to see UID and type...");
}

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

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
  return;
}
         
         for (byte i = 0; i < mfrc522.uid.size; i++) {
         String stringOne = String(mfrc522.uid.uidByte[i], HEX);
        Serial.println();
        if (stringOne == stringTwo){
          Serial.print("Welcome to Wonderland");
        }
        else{
          Serial.print("Denied,");
          Serial.print(stringOne);
          Serial.println();
          Serial.print(stringTwo);
        }
        
}
}

Last post before crashing for a few short hours.

I have the code spewing out the UID as a single line string. The problem now is that I can't do the comparison because the String data is not updating beyond the for statement. In other words, the stringOne String is reading correctly inside the for statement, but it does not retain that state/information once the for statement ends. Somehow I need StringOne to be accessible beyond the for statement. I've tried making it a global variable, but it does not get updated based on the for statement results.

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.
String stringTwo =  "4041821F2381";
String stringOne =  "1234";
void setup() {
	Serial.begin(9600);	// Initialize serial communications with the PC
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();	// Init MFRC522 card
	Serial.println("Scan PICC to see UID and type...");
}

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

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
  return;
}
       for(byte i = 0; i < mfrc522.uid.size; i++) {
        stringOne =  String(mfrc522.uid.uidByte[i], HEX); //How do I get this to update the global variable?
       Serial.print(stringOne);
       }
   Serial.println (); 
        if(stringOne==stringTwo){ //The problem is here. The stringOne variable is not being updated above
          Serial.print("Welcome to Wonderland.");
        }
        else {
          Serial.print("Denied.");
          //Serial.print(stringOne);
         
}
}

Try changing

stringOne =  String(mfrc522.uid.uidByte[i], HEX);

to this:

stringOne +=  String(mfrc522.uid.uidByte[i], HEX);

This will concatenate the new string to the end of the original string, as opposed to overwriting the original string with the new string.

TRex, thanks for the suggestion. I gave it a try and it did concatenate, however it just kept appending the full line output to the end of the last full line, going on until it eventually maxes out.

I think that right now it is a question of how to get stringOne out of this for statement and so that it can be used by the rest of the sketch.

for(byte i = 0; i < mfrc522.uid.size; i++) {
        stringOne =  String(mfrc522.uid.uidByte[i], HEX); //How do I get this to update the global variable?
       Serial.print(stringOne);
       }

The attached screenshot shows that the for statement above is outputting the string in the correct format. I just can't pass the string beyond the for statement.

FULL CODE

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.
String stringTwo =  "4041821f2381";
String stringOne =  "";
void setup() {
	Serial.begin(9600);	// Initialize serial communications with the PC
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();	// Init MFRC522 card
	Serial.println("Scan PICC to see UID and type...");
}

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

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
  return;
}
       for(byte i = 0; i < mfrc522.uid.size; i++) {
        stringOne =  String(mfrc522.uid.uidByte[i], HEX); //How do I get this to update the global variable?
       Serial.print(stringOne);
       }
   Serial.println (); 
        if(stringOne==stringTwo){ //The problem is here. The stringOne variable is not being updated above
          Serial.print("Welcome to Wonderland.");
        }
        else {
          Serial.print("Denied.");
          //Serial.print(stringOne);
         
}
}

Why mess around with Strings?
A simple "sprintf" with a bunch of "%02X" formats would do the trick.

Edit: Why mess around with sprintf and strings? You're just comparing two arrays. Use "memcmp" or "memcmp_P"

You need to reset the string (i.e. stringOne = "") somewhere along the line.
If the string match, you can reset it.
If you know that the code received is always a specific length, you could reset it when it hits that length, however, this is not reliable. Usually there would be some kind of termination character (e.g. a newline or '\n') to indicate the end of a string. If this is not present, then another alternative is to check the time since the last character received. If you haven't received any characters after a timeout period (e.g. 500 ms) then reset the string.