You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ESP32准确测量NFC标签在RC522阅读器上的停留时长

问题:ESP32 + RC522 无法正确测量NFC标签停留时长

我用ESP32搭配RC522阅读器,想测量NFC标签的停留时长,使用MFRC522库操作模块。接线无误,能正常读取标签信息,但时长测量始终不符合预期。

原代码:

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

#define SS_PIN 5    // ESP32 pin GPIO5
#define RST_PIN 27  // ESP32 pin GPIO27

MFRC522 rfid(SS_PIN, RST_PIN);

unsigned long timeStart = 0;
unsigned long timeEnd = 0;
bool tagPresent = false;


void setup() {
  Serial.begin(9600);
  SPI.begin();      // init SPI bus
  rfid.PCD_Init();  // init MFRC522
  Serial.println("Use an RFID tag");
}

void loop() {
  if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    if (!tagPresent) {  // if tagPresent = false, then the tag has just "arrived"
      tagPresent = true;
      timeStart = millis();
    }

    // Removing the next 2 function calls doesn't solve the problem but 
    // it seems to halve the time read in the duration variable

    rfid.PICC_HaltA();  
    rfid.PCD_StopCrypto1();

  } else {
    if (tagPresent) {  //at some point there was a tag, but it's gone now
      Serial.print("\n");
      timeEnd = millis();
      unsigned long duration = timeEnd - timeStart;
      Serial.print("Tag NFC stayed for ");
      Serial.print(duration);
      Serial.println(" ms");
      // noted the last tag's time, reset
      tagPresent = false;
    }
  }
}

原输出:

Tag NFC stayed for 51 ms
Tag NFC stayed for 51 ms    
Tag NFC stayed for 51 ms    
Tag NFC stayed for 51 ms    
...

当前问题:标签刚放上阅读器就立刻输出时长,即使一直停留也不再输出;拿起再放下会重复输出短时长。期望标签停留10秒后移除时,能输出Tag NFC stayed for 10000 ms这样的正确结果。


解决方案

问题出在两个关键点:

  1. PICC_IsNewCardPresent()仅检测首次出现的新卡片,后续循环不会再识别到同一卡片;
  2. PICC_HaltA()会强制卡片进入休眠状态,导致阅读器下一次循环就检测不到卡片,直接触发时长计算。

修改后的代码:

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

#define SS_PIN 5    // ESP32 pin GPIO5
#define RST_PIN 27  // ESP32 pin GPIO27

MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::Uid currentUid; // 可选:用于识别特定标签

unsigned long timeStart = 0;
bool tagPresent = false;

void setup() {
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();
  Serial.println("Place RFID tag on reader...");
}

void loop() {
  // 持续检测是否有卡片在场
  bool cardDetected = rfid.PICC_IsCardPresent();

  if (cardDetected) {
    if (!tagPresent) {
      // 卡片刚放置,记录开始时间
      tagPresent = true;
      timeStart = millis();
      // 可选:读取当前卡片UID,用于限定特定标签
      if (rfid.PICC_ReadCardSerial()) {
        currentUid = rfid.uid;
        rfid.PCD_StopCrypto1(); // 结束加密会话,不要让卡片休眠
      }
      Serial.println("Tag detected");
    }
  } else {
    if (tagPresent) {
      // 卡片被移除,计算并输出停留时长
      unsigned long duration = millis() - timeStart;
      Serial.print("Tag stayed for ");
      Serial.print(duration);
      Serial.println(" ms");
      tagPresent = false;
    }
  }

  // 延迟降低循环频率,提升稳定性
  delay(50);
}

关键修改说明:

  • 替换检测函数:用PICC_IsCardPresent()替代原检测逻辑,该函数会持续判断当前是否有卡片在阅读器感应范围内,而非仅检测新卡片;
  • 移除PICC_HaltA():这个函数会让卡片进入休眠,导致阅读器立刻"丢失"卡片,直接触发错误的时长计算;
  • 添加循环延迟:delay(50)减少SPI通信频率,避免资源过度占用,同时让检测状态更稳定;
  • 可选特定标签支持:如果需要只统计某张标签的停留时长,可以在卡片放置时读取UID,后续对比UID再执行计时逻辑。

修改后,卡片放置时启动计时,移除时输出准确的总停留时长,完全符合预期需求。


内容的提问来源于stack exchange,提问作者Arzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:22:51