RFID tag value matching - Solved #13

I am using a MFRC 522 Reader to get RFID tag which is like 8C62B0F8.

Based on the read value I need to pull out a matching record from a data base stored on SD card.

I am unable to figure out how to do the matching. The function below shows my problem. Where am I going wrong ??

// FUNCTION TO SEARCH DATABASE in SD Card TO LOCATE THE RECORD MATCHING SCANNED RFID.

boolean findMatchRec() {

  String readString;
  String recRFID;
  boolean matchFound = false;
  byte actRFID[4] = {0x12, 0x34, 0x56, 0x78};                   // Dummy tag to check code.

  File dataFile = SD.open("GRPLAN.CSV", FILE_READ);             // Open the file
  if (dataFile) {
    while ( dataFile.available()) {
      char letter = dataFile.read();
      if ( letter == '>' ) {                                   // Read the first record till End Marker 
        nextRecPos = dataFile.position();                      // Save position for next record search to global variable
        recRFID = readString.substring (7, 15);                // Get the RFID tag value for chosen record..
      }
      else {
        readString += letter;                                  // Build the full record string..
      }
    }
  }
  dataFile.close();
  Serial.println( recRFID);                                    // Prints "12345678"
  String myString = (char*)actRFID;                            // Convert the byte array to string
  Serial.println ( myString);                                  // Prints garbage like  4Vx‚A 
  if ( recRFID == myString ) Serial.println( "Success!!");

}

You are using a strategy that simply does not work.

You use String in the most abusive way I have ever seen (concatenating the whole file byte-wise).

You did not describe the format of your 'records' enough to give more constructive hints.

You did not describe the format of your 'records' enough to give more constructive hints.

I was expecting to be pulled up for using the String !! Anyway I am using a Mega 2560 and my code is just 10% of the flash and the SRAM is about 2k size. So right now its kind of a quick proto that I am aiming at as many things are still fluid in the project.

Anyway I attach a sample screen shot of the Data Base file and the RFID is the Second column after serial number..

Thanks for your help..

The findMatchRec() function does not compare anything, so how do you expect it to find something?

You set recRFID to the id of the first record, regardless which record you are reading currently.
That is because you keep the whole file (without the '>'s) in the variable.

I must have been more clear .. sorry.

Yes as it is it will now read only the first record. Actually if you look at the function there is a global variable where I store the starting point of the next record (nextRecPos ).

Once I am successful in this comparison on the first record I will then modify the function to take the position of the next record as an argument and search one after another record from another function.

If you look , after I close the dataFile I do try to check if the tag values match.

My current issue is to bring both tag values - as read by the reader and as extracted from the SD card to a common base to carry out a comparison.

Then change one of the two compared values to the correct format. This would be worth a try:

byte actRFID[] = "12345678";

Hmmm... moved away from String object and tried this with string array. Changed the function suitably. Still no luck. Its always "Success" even if the scanned tag and record tag do not match. So what is wrong now ?

// FUNCTION TO FIND IF A RECORD ON SD CARD MATCHES WITH THE RFID TAG

boolean chkTagMatch() {

  char rowData[100];
  char recRFID[9];
  byte actRFID[4] = {0x12, 0x35, 0x56, 0x78};                   // Dummy tag to check code - intentionally a wrong one....

  File dataFile = SD.open("GRPLAN.CSV", FILE_READ);             // Open the file
  if (dataFile) {
    while ( dataFile.available()) {
      char letter = dataFile.read();
      for ( int i = 0; i < 94; i++ ) {                          
        rowData[i] = letter;
        if ( i > 5 && i < 13) recRFID[i] = letter ;             // Save the RFID value from the SD card..
      }
      nexRecPos = dataFile.position();                          // Save the position to continue the search if required
    }
  }
  dataFile.close();
  
  if (strcmp((char*)actRFID, recRFID)) {                       // Compare the RFID tag with the RFID in the current row..          
  Serial.println( "Success!!");
  return 1;
  }
  else {
    Serial.println("Failure !");
    return 0;
  }
}
      char letter = dataFile.read();
      for ( int i = 0; i < 94; i++ ) {                         
        rowData[i] = letter;
        if ( i > 5 && i < 13) recRFID[i] = letter ;             // Save the RFID value from the SD card..
      }

Read one letter. Store it in 94 places in the rowData array. That makes no sense to me.

Store the same letter in recRFID, in positions 5 thru 13, even though the valid range of indices is 0 to 8. That makes no sense to me.

  if (strcmp((char*)actRFID, recRFID)) {                       // Compare the RFID tag with the RFID in the current row..         
  Serial.println( "Success!!");

strcmp() returns 0 if the records match. You are printing Success!! if they do not match. That makes no sense to me.

Yes Pual. You can say that again. When things don't go the way as expected, stupid mistakes are plenty and then nothing makes sense.

Of course shall correct the errors but hope the approach is atleast correct. Will work and get back. Thanks for the nudge !

I have now corrected all the errors pointed out by Paul but still not reached the solution. I am missing something big time.

The problem boils down to this :

  • I have a byte array in the form { 0x12345678} from the RFID reader.
  • I have the matching value to be picked up from the SD card data base.
  • I can read the data base and store the RFID value in a char array or a String obj.
  • And finally I need to bring the byte array to either one of the above data types to compare.

Tried various methods and ended up getting various error messages from the compiler.

I am sure this is a very common requirement to read somethin from the SD card and compare with a byte array. How does one convert the different data types to a single type and compare ? Thanks for any help.

I have now corrected all the errors pointed out

So, where is that code?

OK so here is the code . Pointed out errors removed but still not doing what is expected. I think the real problem is the Byte array to Char array conversion . Why is the conversion failing ??

// FUNCTION TO CHECK IF THE CHOSEN RFID IN DATABASE ON SD CARD MATCHES THE SCANNED RFID.

boolean chkTagMatch() {

  char recRFID[9];
  int result = -1;
  byte actRFID[4] = {0x12, 0x34, 0x56, 0x78};                  // Dummy tag to check code.
  char letter ;

  File dataFile = SD.open("GRPLAN.CSV", FILE_READ);           // Open the file
  if (dataFile) {
    dataFile.seek(7);                                         // Move to the position of start of RFID reference
    for ( int i = 0; i < 8; i++ )  {                          // Read the eight positions of RFID reference
      letter = dataFile.read();
      recRFID[i] = letter;
    }
  }
  dataFile.close();
  recRFID[8] = '\0';                                           // Null Terminate the string
  Serial.println( recRFID);                                    // Prints "12345678"
  Serial.println ((char*)actRFID);                             // Prints garbage. This byte array to char conversion is the problem... :-(
  result = strcmp (recRFID, (char*)actRFID);
  if (result == 0 ) Serial.println( "SUCCESS!!");
  else Serial.println ( "FAILURE");                
}

I fail to see how an 8 byte RFID tag, read from the file, is EVER going to match a 4 byte tag.

EXACTLY what are you reading from the file? If the file contains the TEXT "12345678", that will NOT match the 4 bytes 0x12, 0x34, 0x56, 0x78.

Success at last !! Thanks Paul... your remark on the number of bytes was bugging me from the beginning and it took some time to understand how Serial print works and then decided to do it from scratch.

I am not sure if the code below is elegant ...compact or professional ... but it seems to work and that is a relief. Any comments to improve welcome !! I have also attached the Serial Capture for checking. Seems OK . To me :slight_smile:

// FUNCTION TO CHECK IF THE CHOSEN RFID IN DATABASE ON SD CARD MATCHES THE SCANNED RFID.

boolean chkTagMatch() {

  char rec_char_RFID[9];
  char act_char_RFID[9];
  int result = -1;
  byte actRFID[4] = {0x12, 0x34, 0x56, 0x78};                  // Dummy tag to check code.
  byte * bytePtr = actRFID;
  char letter ;

  File dataFile = SD.open("GRPLAN.CSV", FILE_READ);           // Open the file
  if (dataFile) {
    dataFile.seek(7);                                         // Move to the position of start of RFID reference
    for ( int i = 0; i < 8; i++ )  {                          // Read the eight positions of RFID reference
      letter = dataFile.read();
      rec_char_RFID[i] = letter;
      Serial.println( letter, BIN);
    }
  }
  dataFile.close();
  rec_char_RFID[8] = '\0';                                    // Null Terminate the string
  Serial.println( rec_char_RFID);                             // Prints "12345678
  act_char_RFID[8] = '\0';
  RFID_To_Char (bytePtr, act_char_RFID, 4);
  Serial.println( act_char_RFID);                             // Prints "12345678
  result = strcmp (rec_char_RFID, act_char_RFID);
  if (result == 0 ) {
    Serial.println( "SUCCESS!!");
  }
  else {
    Serial.println ( "FAILURE");
  }
}

// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&


void RFID_To_Char (byte* byteArray, char* charArray, int ByteArraySize) {
  int byteCount ;
  int charCount ;
  for ( byteCount = 0; byteCount < ByteArraySize; byteCount++ ) {
    charArray[charCount] = (byteArray[byteCount] >> (4)) | 0x30 ;
    Serial.println(charArray[charCount], BIN);
    charArray[charCount + 1] = (byteArray[byteCount] & 0x0f ) | 0x30;
    Serial.println(charArray[charCount + 1], BIN);
    charCount += 2;
  }
}
  int charCount ;
  for ( byteCount = 0; byteCount < ByteArraySize; byteCount++ ) {
    charArray[charCount] = (byteArray[byteCount] >> (4)) | 0x30 ;

The charCount variable is not initialized, so you can not rely on it having any particular value.

It could have been far simpler to convert the characters read from the file to bytes, and compare two 4 byte arrays.

>> The charCount variable is not initialized, so you can not rely on it having any particular value.

Thanks for highlighting the trap.