You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Arduino RC522 RFID读卡器故障:使用一段时间后无法读取标签

解决你的Arduino户外灯光系统RFID失效问题

嘿,作为刚入门编程的新手,能搭建出这套户外灯光系统已经超棒啦!咱们一步步来搞定RFID失效的问题,顺便把代码优化得更清爽~

先搞懂你疑惑的两个RFID函数

你提到的rfid.PICC_HaltA()rfid.PCD_StopCrypto1()其实是RFID通信里至关重要的收尾操作:

  • rfid.PICC_HaltA():让当前被读取的RFID标签进入休眠模式,这样读卡器就不会一直和这个标签保持连接,能及时响应新的标签。
  • rfid.PCD_StopCrypto1():终止读卡器和标签之间的加密会话,重置加密状态,确保下一次读卡时是全新的通信环境,避免残留的加密状态导致后续读卡失败。

分析RFID失效的核心原因

看你的代码,最大的问题是使用了阻塞式的delay()

  • 当识别到合法标签后,你用delay(15000)让灯亮15秒,这15秒内Arduino完全卡住,没法执行任何其他操作——包括RFID模块的状态维护、甚至没法响应新的读卡请求。长时间阻塞会让RC522模块进入异常状态,最终导致读卡功能失效,必须重启才能恢复。
  • 另外,当前的UID匹配逻辑写得太繁琐,虽然功能没问题,但维护起来很麻烦,也容易出错。

解决方案:用非阻塞延时重构代码

我们把delay()换成millis()来实现非阻塞延时,这样程序在等待灯熄灭的过程中,依然能正常处理RFID读卡和门状态检测。同时优化UID匹配的逻辑:

完整修改后的代码

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

// 把所有合法UID放进二维数组,方便循环匹配
const byte validUIDs[6][4] = {
  {0xA7, 0x8C, 0x24, 0xD9}, // 黑色标签1
  {0x10, 0x84, 0xD2, 0x2A}, // 黑色标签2
  {0xDC, 0x46, 0xB6, 0x91}, // 黑色标签3
  {0xB0, 0xE8, 0xC4, 0x2A}, // 黑色标签4
  {0x9E, 0xC8, 0xEA, 0xB3}, // 红色标签1
  {0xFE, 0xA5, 0xF7, 0xB3}  // 红色标签2
};
const int validUIDCount = sizeof(validUIDs) / sizeof(validUIDs[0]);

MFRC522 rfid(10, 9);
int in1 = 7;          // 灯光控制引脚
int dooropen = 8;     // 霍尔传感器引脚
int doorState = 0;    // 当前门状态
int tester = 0;       // 门打开标记
unsigned long lastLightOnTime = 0; // 记录灯光点亮的时间
const long doorOffDelay = 6000;    // 关门后灯光保持时间
const long rfidLightDelay = 15000; // RFID触发后灯光保持时间
int lightMode = 0;    // 灯光模式:0=正常门控,1=RFID触发

void setup() {
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();
  pinMode(in1, OUTPUT);
  pinMode(dooropen, INPUT);
  digitalWrite(in1, LOW);
}

void loop() {
  doorState = digitalRead(dooropen);
  unsigned long currentMillis = millis();

  // 处理门控逻辑
  if (doorState == HIGH) {
    // 门打开:点亮灯光,重置所有延时标记
    digitalWrite(in1, HIGH);
    tester = 1;
    lightMode = 0;
    lastLightOnTime = currentMillis;
  } else {
    if (tester == 1) {
      // 门刚关上,进入关门延时模式
      lightMode = 0;
      if (currentMillis - lastLightOnTime >= doorOffDelay) {
        digitalWrite(in1, LOW);
        tester = 0;
      }
    } else {
      // 门保持关闭状态,处理RFID逻辑
      if (lightMode == 0) {
        // 只有在正常门控模式下,才检测RFID
        if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
          // 检查当前UID是否在合法列表中
          bool isUIDValid = false;
          for (int i = 0; i < validUIDCount; i++) {
            if (memcmp(rfid.uid.uidByte, validUIDs[i], 4) == 0) {
              isUIDValid = true;
              break;
            }
          }

          if (isUIDValid) {
            // 合法标签:点亮灯光,进入RFID延时模式
            digitalWrite(in1, HIGH);
            lightMode = 1;
            lastLightOnTime = currentMillis;
          }

          // 必须执行的收尾操作,确保读卡器状态正常
          rfid.PICC_HaltA();
          rfid.PCD_StopCrypto1();
        }
      } else {
        // RFID触发后的延时逻辑
        if (currentMillis - lastLightOnTime >= rfidLightDelay) {
          digitalWrite(in1, LOW);
          lightMode = 0;
        }
      }
    }
  }

  // 可选:定期检查读卡器状态,异常时重新初始化
  if (!rfid.PCD_IsAlive()) {
    Serial.println("RFID模块异常,重新初始化...");
    rfid.PCD_Init();
  }
}

代码关键改进点

  1. 非阻塞延时:用millis()替代delay(),程序全程不会卡住,RFID模块能持续正常工作。
  2. 优化UID匹配:把所有合法UID放进二维数组,用memcmp()循环比较,代码更简洁,后续添加新标签只需在数组里加一行即可。
  3. 状态管理:新增lightMode变量区分不同的灯光触发模式,逻辑更清晰。
  4. 读卡器健康检查:添加rfid.PCD_IsAlive()定期检查模块状态,异常时自动重新初始化,提升稳定性。

额外硬件建议

因为是户外使用,这些细节也能提升系统稳定性:

  • 给RC522模块加防水外壳,避免雨水、湿气损坏电路。
  • 检查供电:Arduino Nano如果用USB供电,户外可能电压不稳,建议用5V/1A的稳压电源供电,确保模块有足够的电力。
  • 接线加固:所有接线用热缩管或者接线端子固定,避免风吹日晒导致松动接触不良。

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

火山引擎 最新活动