diff --git a/firmware/esp32-pn532-door/src/main.cpp b/firmware/esp32-pn532-door/src/main.cpp index b928d2b..c90069a 100644 --- a/firmware/esp32-pn532-door/src/main.cpp +++ b/firmware/esp32-pn532-door/src/main.cpp @@ -13,8 +13,18 @@ Adafruit_PN532 nfc(PN532_IRQ_PIN, PN532_RESET_PIN, &Wire); static unsigned long lastReadAt = 0; +static unsigned long lastWifiAttemptAt = 0; +static unsigned long lastPn532InitAt = 0; +static unsigned long lastPn532HealthAt = 0; static String lastCredential = ""; static bool wifiScanPrinted = false; +static bool pn532Ready = false; +static uint16_t emptyReadCount = 0; + +const unsigned long WIFI_RETRY_MS = 15000; +const unsigned long PN532_INIT_RETRY_MS = 5000; +const unsigned long PN532_HEALTH_CHECK_MS = 120000; +const uint16_t PN532_EMPTY_READ_REINIT_COUNT = 300; String bytesToHex(const uint8_t *data, uint8_t length) { String out; @@ -114,6 +124,10 @@ void printWifiScan() { void connectWifi() { if (WiFi.status() == WL_CONNECTED) return; + unsigned long now = millis(); + if (lastWifiAttemptAt && now - lastWifiAttemptAt < WIFI_RETRY_MS) return; + lastWifiAttemptAt = now; + WiFi.persistent(false); WiFi.mode(WIFI_STA); WiFi.setSleep(false); @@ -140,7 +154,59 @@ void connectWifi() { } } +bool initializePn532(bool force = false) { + unsigned long now = millis(); + if (!force && lastPn532InitAt && now - lastPn532InitAt < PN532_INIT_RETRY_MS) return pn532Ready; + lastPn532InitAt = now; + pn532Ready = false; + + Serial.println("Initializing PN532..."); + pinMode(PN532_RESET_PIN, OUTPUT); + digitalWrite(PN532_RESET_PIN, LOW); + delay(25); + digitalWrite(PN532_RESET_PIN, HIGH); + delay(120); + + Wire.end(); + delay(25); + Wire.begin(PN532_SDA_PIN, PN532_SCL_PIN); + Wire.setClock(100000); + Wire.setTimeOut(60); + + nfc.begin(); + uint32_t version = nfc.getFirmwareVersion(); + if (!version) { + Serial.println("PN532 not found. Will retry without stopping controller."); + return false; + } + + nfc.SAMConfig(); + emptyReadCount = 0; + lastPn532HealthAt = now; + pn532Ready = true; + Serial.println("PN532 ready."); + return true; +} + +void maintainPn532() { + unsigned long now = millis(); + if (!pn532Ready) { + initializePn532(); + return; + } + + if (now - lastPn532HealthAt < PN532_HEALTH_CHECK_MS) return; + lastPn532HealthAt = now; + + uint32_t version = nfc.getFirmwareVersion(); + if (!version) { + Serial.println("PN532 health check failed; reinitializing."); + initializePn532(true); + } +} + bool readCardUid(uint8_t *uid, uint8_t *uidLength) { + if (!pn532Ready && !initializePn532()) return false; return nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, uidLength, 350); } @@ -173,7 +239,16 @@ String readMifareSecret(uint8_t *uid, uint8_t uidLength) { String readCredential() { uint8_t uid[7] = { 0 }; uint8_t uidLength = 0; - if (!readCardUid(uid, &uidLength)) return ""; + if (!readCardUid(uid, &uidLength)) { + emptyReadCount++; + if (emptyReadCount >= PN532_EMPTY_READ_REINIT_COUNT) { + Serial.println("PN532 idle/read timeout threshold reached; reinitializing."); + initializePn532(true); + } + return ""; + } + + emptyReadCount = 0; #if CARD_MODE == CARD_MODE_MIFARE_CLASSIC_BLOCK String secret = readMifareSecret(uid, uidLength); @@ -215,20 +290,12 @@ void setup() { connectWifi(); - Wire.begin(PN532_SDA_PIN, PN532_SCL_PIN); - nfc.begin(); - uint32_t version = nfc.getFirmwareVersion(); - if (!version) { - Serial.println("PN532 not found. Check wiring and mode switches."); - while (true) delay(1000); - } - - nfc.SAMConfig(); - Serial.println("PN532 ready."); + initializePn532(true); } void loop() { connectWifi(); + maintainPn532(); String credential = readCredential(); if (!credential.length()) {