Teensy 3.2 and RFID

Status
Not open for further replies.

SteveSFX

Well-known member
Hello all

I am playing around with RFID for the first time... struggling a little bit. Got an RC522 set up and reading correctly.

Using the library MFRC522.h, and here is the read personal data code

Code:
#include <SPI.h>
#include <MFRC522.h>

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

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

//*****************************************************************************************//
void setup() {
  Serial.begin(9600);                                           // Initialize serial communications with the PC
  SPI.begin();                                                  // Init SPI bus
  mfrc522.PCD_Init();                                              // Init MFRC522 card
  Serial.println(F("Read personal data on a MIFARE PICC:"));    //shows in serial that it is ready to read
}

//*****************************************************************************************//
void loop() {

  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  //some variables we need
  byte block;
  byte len;
  MFRC522::StatusCode status;

  //-------------------------------------------

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

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

  Serial.println(F("**Card Detected:**"));

  //-------------------------------------------

  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex

  //-------------------------------------------

  Serial.print(F("Name: "));

  byte buffer1[18];

  block = 4;
  len = 18;

  //------------------------------------------- GET FIRST NAME
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  status = mfrc522.MIFARE_Read(block, buffer1, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  //PRINT FIRST NAME
  for (uint8_t i = 0; i < 16; i++)
  {
    if (buffer1[i] != 32)
    {
      Serial.write(buffer1[i]);
    }
  }
  Serial.print(" ");

  //---------------------------------------- GET LAST NAME

  byte buffer2[18];
  block = 1;

  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  status = mfrc522.MIFARE_Read(block, buffer2, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  //PRINT LAST NAME
  for (uint8_t i = 0; i < 16; i++) {
    Serial.write(buffer2[i] );
  }


  //----------------------------------------

  Serial.println(F("\n**End Reading**\n"));

  delay(1000); //change value if you want to read cards faster

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}
//*****************************************************************************************//

My problem is this.

This routine basically sits in the main loop, waiting for a card to be presented.

I however, want to move this out to a sub-routine, so that a flag is set when a valid card is read, then it returns to the main loop. I would use the IRQ pin on the RC522.... but apparently it doesn't work (useful!)

But, it really doesn't seem to like being moved about. I get timeout errors and all sorts.

The line if (mfrc522.PICC_IsNewCardPresent() or mfrc522.PICC_ReadCardSerial()) {Read_RFID();} seems to work to branch out from the main loop upon a card being presented, but then you need to remove those commands from being repeated in the sub-routine. Otherwise it hangs.

But, then you get card timeout errors.

I have read the README file with the library and got my head around the blocks etc, but I don't understand what each of the library components do E.G. mfrc522.PICC_IsNewCardPresent() or mfrc522.GetStatusCodeName(status) etc

I wish they commented them better!

Earlier, after extensive Googling, I found another segment of code for reading cards.. but it had errors and after 2 hours, I have returned to this library.

Any suggestions or other library recommendations?
 
Hi
Not sure if this is of help. But I initialize the same as you in setup.
Code:
SPI.begin();        // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card

then in loop I call a function to read data from the card as below (that I write in a different code). This reads from sectors and blocks where the address is currently hard coded in the function.
I use a flag so that the card is only read when first presented.
Apologies for my very poor coding (i have not updated all the comments or annotated etc).
Code:
uint8_t getCard()
{
	uint8_t failed = 0;
    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

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

    // Show some details of the PICC (that is: the tag/card)
    Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println();
    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));

    // Check for compatibility
    if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println(F("This sample only works with MIFARE Classic cards."));
		failed = 0;
        return;
    }

    // In this sample we use the second sector,
    // that is: sector #1, covering block #4 up to and including block #7
    byte sector         = 5;
    byte blockAddr      = 20;
    byte dataBlock[]    = {
        0x01, 0x02, 0x03, 0x04, //  1,  2,   3,  4,
        0x05, 0x06, 0x07, 0x08, //  5,  6,   7,  8,
        0x09, 0x0a, 0xff, 0x0b, //  9, 10, 255, 11,
        0x0c, 0x0d, 0x0e, 0x0f  // 12, 13, 14, 15
    };
    byte trailerBlock   = 23;
    MFRC522::StatusCode status;
    byte buffer[18];
    byte size = sizeof(buffer);

	
    // Authenticate using key A
    Serial.println(F("Authenticating using key A..."));
    status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
    if (status != MFRC522::STATUS_OK) {
        Serial.print(F("PCD_Authenticate() failed: "));
		vga_command("f,4"); //11JULY19
		Serial1.println(F("PCD_Authenticate() failed: "));//11JULY19
        Serial.println(mfrc522.GetStatusCodeName(status));//11JULY19 
		Serial1.println(mfrc522.GetStatusCodeName(status));
		failed = 0;
        return ;
    }

    // Show the whole sector as it currently is
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();

    // Read data from the block
    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
    Serial.println(F(" ..."));
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
		vga_command("f,4"); //11JULY19
		Serial1.println(F("MIFARE_Read() failed: "));//11JULY19
		Serial1.println(mfrc522.GetStatusCodeName(status));//11JULY19
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
		failed = 0;
        return;
    }
    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
    dump_byte_array(buffer, 16); Serial.println();
    Serial.println();
	//get the crands**************************************************************
	for(int z = 0; z<16; z++)
	{
		pdata[0].crand[z] = buffer[z];
		tBuff[z] = buffer[z];
	}
	Serial1.print("crand 1 = :");
	//Serial1.println(tBuff);
	
	//get the crand fin**********************************************************
	sector         = 5;
    blockAddr      = 21;
	trailerBlock   = 23;
	    // Show the whole sector as it currently is
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();

    // Read data from the block
    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
    Serial.println(F(" ..."));
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
		vga_command("f,4"); //11JULY19
		Serial1.println(F("MIFARE_Read() failed: "));//11JULY19
		Serial1.println(mfrc522.GetStatusCodeName(status));//11JULY19
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
		failed = 0;
        return;
    }
    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
    dump_byte_array(buffer, 16); Serial.println();
    Serial.println();
	//get the crands**************************************************************
	for(int z = 0; z<16; z++)
	{
		pdata[1].crand[z] = buffer[z];
		tBuff[z] = buffer[z];
	}
	Serial1.print("crand 1 = :");
	//Serial1.println(tBuff);
	
	//get the crand fin**********************************************************
	sector         = 5;
    blockAddr      = 22;
	trailerBlock   = 23;
	    // Show the whole sector as it currently is
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();

    // Read data from the block
    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
    Serial.println(F(" ..."));
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
		vga_command("f,4"); //11JULY19
		Serial1.println(F("MIFARE_Read() failed: "));//11JULY19
		Serial1.println(mfrc522.GetStatusCodeName(status));//11JULY19
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
		failed = 0;
        return ;
    }
    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
    dump_byte_array(buffer, 16); Serial.println();
    Serial.println();
	//get the crands**************************************************************
	for(int z = 0; z<16; z++)
	{
		pdata[2].crand[z] = buffer[z];
		tBuff[z] = buffer[z];
	}
	Serial1.print("crand 1 = :");
	//Serial1.println(tBuff);
	
	//get the crand fin**********************************************************
	sector         = 7;
    blockAddr      = 28;
	trailerBlock   = 31;
	    // Show the whole sector as it currently is
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();

    // Read data from the block
    Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
    Serial.println(F(" ..."));
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
		vga_command("f,4"); //11JULY19
		Serial1.println(F("MIFARE_Read() failed: "));//11JULY19
		Serial1.println(mfrc522.GetStatusCodeName(status));//11JULY19
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
		failed = 0;
        return;
    }
	else
	{
		pwStat =1; //passwords read.
		if(screenStat == 0)
		{bootScreen(); bpreviousMillis = millis(); screenStat = 1;}
		vga_command("f,3");               // Set Window4 as focus       
        Serial1.println("Card Read OK"); 
	}
    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
    dump_byte_array(buffer, 16); Serial.println();
    Serial.println();
		//get the crands**************************************************************
	for(int z = 0; z<16; z++)
	{
		pdata[3].crand[z] = buffer[z];
		tBuff[z] = buffer[z];
	}
	Serial1.print("crand 1 = :");
	
    // Dump the sector data
    Serial.println(F("Current data in sector:"));
    mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
    Serial.println();

    // Halt PICC
    mfrc522.PICC_HaltA();
    // Stop encryption on PCD
    mfrc522.PCD_StopCrypto1();

    return 	failed ;
}
 
Hmm.... I just get

RFID_Demo_v2:37: warning: unused variable 'dataBlock'
byte dataBlock[] = {

^
'mfrc522' was not declared in this scope


When I run that. Will have a look later
 
The library I am using is https://github.com/miguelbalboa/rfid

I started with the read and write example which seems to work ok to read/write to specific blocks.
The code in uint8_t getCard() is straight form the example, just with some code to store the data from the blocks in some local structures
I dont confess to understand all the setup functions, but I only need to able to write once to a number blocks and then be able to read back multiple times.
 
I am finding these libraries hard work actually. Working out what each part does it difficult for someone without the required knowledge.

I have the following code so far, made up of various 'bits'...

Code:
void Read_RFID(){                                                                                                       // Check the RFID module   

  if ( ! mfrc522.PICC_ReadCardSerial()) {return;}                                                                       // Read the card

  Serial.print("Tag:");                                                                                                 // Get the tag address
  String content= "";
  //for (byte i = 0; i < mfrc522.uid.size; i++) {
  for (byte i = 0; i < 4; i++) {                                                                                        // Read the 4 byte UID code
 
  Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
  Serial.print(mfrc522.uid.uidByte[i], HEX);

  content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));                                                   // Create a string with that data
  content.concat(String(mfrc522.uid.uidByte[i], HEX)); 
  }
  Serial.println(" ");
  
  content.toUpperCase();
  content = content.substring(1);


  if(content == "39 24 00 5D"){                                                                                         // Check it matches previous tag addresses
       Serial.println("VALID TAG");
       Tag_valid=true;
     }else{
       Serial.print("INVALID TAG");
       Tag_valid=false;
     }

  delay(200);

}

This sub-routine reads the card and gets the card address. It was asking for the address length, but I have commented that out, as I believe that all my standard tags here are 4x byte addresses. It now retrieves 4x bytes each time.

My aim, is to compare that 4x byte address to a stored address in EEPROM.

This code is assembling a string with commands such as 'concat' that I totally don't understand (even after Google).

I don't understand what the function < 0x10 ? " 0" : " " does either.
My guess, is that it adds a second zero to any value under 10? and also spaces them out with a " ".

I don't really need to assemble a string. Surely I can simply read the cards 4x byte address and compare those to 4x EEPROM byte variables.

Any guidance gratefully received!
 
Status
Not open for further replies.
Back
Top