Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement: Detection of tag removal #352

Closed
metamorphious opened this issue Dec 18, 2017 · 13 comments
Closed

Improvement: Detection of tag removal #352

metamorphious opened this issue Dec 18, 2017 · 13 comments

Comments

@metamorphious
Copy link

Not sure where to post.. but here is my solution for detection of a removed RFID tag. May not be the optimal solution but works for me. Maybe it helps someone or can be added to the library somehow.

Step 1: Describe your environment

  • OS version: Win 10
  • Arduino IDE version: 1.8.1
  • MFRC522 Library version: 1.3.6
  • Arduino device: Arduino nano
  • MFRC522 device: RFID-RC522

Relevant Code:

  #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

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

bool rfid_tag_present_prev = false;
bool rfid_tag_present = false;
int _rfid_error_counter = 0;
bool _tag_found = false;

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
}

void loop() {
  rfid_tag_present_prev = rfid_tag_present;

  _rfid_error_counter += 1;
  if(_rfid_error_counter > 2){
    _tag_found = false;
  }

  // Detect Tag without looking for collisions
  byte bufferATQA[2];
  byte bufferSize = sizeof(bufferATQA);

  // Reset baud rates
  mfrc522.PCD_WriteRegister(mfrc522.TxModeReg, 0x00);
  mfrc522.PCD_WriteRegister(mfrc522.RxModeReg, 0x00);
  // Reset ModWidthReg
  mfrc522.PCD_WriteRegister(mfrc522.ModWidthReg, 0x26);

  MFRC522::StatusCode result = mfrc522.PICC_RequestA(bufferATQA, &bufferSize);

  if(result == mfrc522.STATUS_OK){
    if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue   
      return;
    }
    _rfid_error_counter = 0;
    _tag_found = true;        
  }
  
  rfid_tag_present = _tag_found;
  
  // rising edge
  if (rfid_tag_present && !rfid_tag_present_prev){
    Serial.println("Tag found");
  }
  
  // falling edge
  if (!rfid_tag_present && rfid_tag_present_prev){
    Serial.println("Tag gone");
  }
}
@Rotzbua
Copy link
Collaborator

Rotzbua commented Dec 18, 2017

Good point. In theory we have a wiki. It would be good if we can collect such code snippets there. I would prefer the wiki over a new example because your code do not have serial output where you can interactively "see" the code "working". And we already have a lot of examples ;).

I created a new page for useful code snippets: https://github.com/miguelbalboa/rfid/wiki/Useful-code-snippets

I moved your code here:
https://github.com/miguelbalboa/rfid/wiki/Useful-code-snippets#detection-of-tag-removal

@metamorphious Ok for you or should I revert it?

@metamorphious
Copy link
Author

Thats fine. Just wanted to share my solution if others have the same problem.

@Shogun1978
Copy link

Great solution! Exactly what I need! But I have a short question: I am new to Arduino programming and testing with a nodeMCU. I would like to build some kind of switch. If a NFC/RFID tag or phone (with NFC) is on the sensor, it should send an "on" signal in MQTT. When the tag/phone is removed, it should send an "off" signal via MQTT. Do I need to put the code in the original code from omersiar? And which parts do I need to exchange? It would be great to have some kind of setting in the web interface, what and when a signal will be send. I want to realize a "switch" at the bed. If the phone is placed near the bed, my smart home will be set in sleep/night mode.

@metamorphious
Copy link
Author

I tried to post a complete example. So the code above should be enough. Just add your MQTT code inside the corresponding if-statements where the presence of a tag is printed.

@Shogun1978
Copy link

Thank you for the example. I am really new to Arduino programing but figured out a solution and it's already working. Right now it works with RFID tags and NFC in smartphones. The smartphone I tested with changes it's code every minute, so I get a off/on every minute when the smartphone is still placed on the reader. I try to find a solution for that. When everything is ready and working I can share the complete set here (no user logging etc.).

@Shogun1978
Copy link

Update: made it work. It is possible to use the RFID reader in switch and touch mode.
Switch: sends "ON" over MQTT when tag is placed on the reader and "OFF" when it is removed
Touch: sends "ON" when a tag is placed and removed for the first time and "OFF" at the second time.
I will try to share the code as official branch, but I'm very new to Github. So I need some assistance, how to correctly place the code here.
Thank you for the snippet, it helped me solve my problem.

@mpbejo
Copy link

mpbejo commented Oct 18, 2018

Hi everybody,
from several days I try to find a solution to detect if a card is present or not, and when is detected I need to read a block after the authentication.
With your sample i see that when a card is present the
if(result == mfrc522.STATUS_OK) is 0 and 3 alternatively.
but when i add my istructions to read the sector only the firdt time i have 0 after the read sector i have always 3 so the card result gone.
Really I do not understand how to solve below my Sketch.
Thank You very much
Best Regards
Marco

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

#define RST_PIN         22          // Configurable, see typical pin layout above
#define SS_PIN          5         // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
MFRC522::MIFARE_Key key;

bool rfid_tag_present_prev = false;
bool rfid_tag_present = false;
int _rfid_error_counter = 0;
bool _tag_found = false;

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
  // Prepare the key (used both as key A and as key B)
    // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
    for (byte i = 0; i < 6; i++) {
        key.keyByte[i] = 0xFF;
    }
}

void loop() {
  
  delay(1000);
  rfid_tag_present_prev = rfid_tag_present;

  _rfid_error_counter += 1;
  if(_rfid_error_counter > 2){
    _tag_found = false;
  }

  // Detect Tag without looking for collisions
  byte bufferATQA[2];
  byte bufferSize = sizeof(bufferATQA);

  // Reset baud rates
  mfrc522.PCD_WriteRegister(mfrc522.TxModeReg, 0x00);
  mfrc522.PCD_WriteRegister(mfrc522.RxModeReg, 0x00);
  // Reset ModWidthReg
  mfrc522.PCD_WriteRegister(mfrc522.ModWidthReg, 0x26);

  MFRC522::StatusCode result = mfrc522.PICC_RequestA(bufferATQA, &bufferSize);
  Serial.print("result: ");
  Serial.println(result);
  if(result == mfrc522.STATUS_OK){
    if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue   
      return;
    }
    _rfid_error_counter = 0;
    _tag_found = true;        
  }
  
  rfid_tag_present = _tag_found;
  
  // rising edge
  if (rfid_tag_present && !rfid_tag_present_prev){
    Serial.println("Tag found");
   
    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."));
        return;
    }
    */
      byte sector         = 1;
      byte blockAddr      = 4;
      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   = 7;
      byte buffer[18];
      byte size = sizeof(buffer);

    // Authenticate using key A
    Serial.println(F("Authenticating using key A..."));
    
    result = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
    if (result != MFRC522::STATUS_OK) 
    {
        Serial.print(F("PCD_Authenticate() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(result));
    }
    
    result = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
    if (result != MFRC522::STATUS_OK) {
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(result));
    }
    Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
    dump_byte_array(buffer, 16); Serial.println();
    Serial.println();

     // Halt PICC
    mfrc522.PICC_HaltA();
    // Stop encryption on PCD
    mfrc522.PCD_StopCrypto1();
  }
  
  // falling edge
  if (!rfid_tag_present && rfid_tag_present_prev){
    Serial.println("Tag gone");
  }
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

@mpbejo
Copy link

mpbejo commented Oct 18, 2018

Well, I have found a workaround for now, I don't like it but it works!
After the istruction mfrc522.PCD_StopCrypto1();
mfrc522.PCD_Reset();
delay(100);
mfrc522.PCD_Init(); // Init MFRC522

I hope somebody find a better solution without a reset.

@Quarx64
Copy link

Quarx64 commented Jan 24, 2019

Good workaround,
the reader hangs no more after a CRC Error.

@oliviereising
Copy link

Hey your code almost works perfectly for me, the only issue i'm having now is the following:
When i'm reading the first NFC tag it reads this tag and serial prints hydro, after I remove it it prints Tag gone but when I place the second NFC tag on top of the reader it still prints "hydro" only after I remove the second tag and place it on top of the reader again it serial prints "bio". It's the same problem other way around.

Do you have a clue whats going on here and why it's not serial printing the sentence associated with that specific tag at the first "read out"

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

#define RST_PIN         5          // Configurable, see typical pin layout above
#define SS_PIN          4         // Configurable, see typical pin layout above

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

bool rfid_tag_present_prev = false;
bool rfid_tag_present = false;
int _rfid_error_counter = 0;
bool _tag_found = false;

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
}

void loop() {
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {

    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();

  rfid_tag_present_prev = rfid_tag_present;

  _rfid_error_counter += 1;
  if (_rfid_error_counter > 2) {
    _tag_found = false;
  }

  // Detect Tag without looking for collisions
  byte bufferATQA[2];
  byte bufferSize = sizeof(bufferATQA);

  // Reset baud rates
  mfrc522.PCD_WriteRegister(mfrc522.TxModeReg, 0x00);
  mfrc522.PCD_WriteRegister(mfrc522.RxModeReg, 0x00);
  // Reset ModWidthReg
  mfrc522.PCD_WriteRegister(mfrc522.ModWidthReg, 0x26);

  MFRC522::StatusCode result = mfrc522.PICC_RequestA(bufferATQA, &bufferSize);

  if (result == mfrc522.STATUS_OK) {
    if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
      return;
    }
    _rfid_error_counter = 0;
    _tag_found = true;
  }

  rfid_tag_present = _tag_found;

  // rising edge
  if (rfid_tag_present && !rfid_tag_present_prev) {
    Serial.println("Tag found");
    if (content.substring(1) == "04 BA 94 C2 A8 64 80") {
      Serial.println("hydro");
    }
    if (content.substring(1) == "04 C2 94 C2 A8 64 80") {
      Serial.println("bio");
    }
    
  }

  // falling edge
  if (!rfid_tag_present && rfid_tag_present_prev) {
    Serial.println("Tag gone");
  }
}

@Quarx64
Copy link

Quarx64 commented Jan 25, 2020

@oliviereising
move vour content.concat some lines down

void loop() {
  rfid_tag_present_prev = rfid_tag_present;
  _rfid_error_counter += 1;
  if (_rfid_error_counter > 2) {
    _tag_found = false;
  }

  // Detect Tag without looking for collisions
  byte bufferATQA[2];
  byte bufferSize = sizeof(bufferATQA);

  // Reset baud rates
  mfrc522.PCD_WriteRegister(mfrc522.TxModeReg, 0x00);
  mfrc522.PCD_WriteRegister(mfrc522.RxModeReg, 0x00);
  // Reset ModWidthReg
  mfrc522.PCD_WriteRegister(mfrc522.ModWidthReg, 0x26);

  MFRC522::StatusCode result = mfrc522.PICC_RequestA(bufferATQA, &bufferSize);

  String content = "";

  if (result == mfrc522.STATUS_OK) {
    if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
      return;
    }
    _rfid_error_counter = 0;
    _tag_found = true;

         for (byte i = 0; i < mfrc522.uid.size; i++) {
            content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
            content.concat(String(mfrc522.uid.uidByte[i], HEX));
         }

         content.toUpperCase();

  }
   .
   .
   .

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

@oliviereising
Copy link

Thanks that fixed the issue!

@Martin-Laclaustra
Copy link

Thank you for the contributions in this thread. Inspired in them, and after reviewing the standard, I put together an example that seems to work reliably. You can find it here:
https://github.com/Martin-Laclaustra/MFRC522-examples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants