Add PN532 self recovery to door firmware

This commit is contained in:
Dorian
2026-05-20 15:14:39 -05:00
parent fcf98b9dbf
commit d4ae422067

View File

@@ -13,8 +13,18 @@
Adafruit_PN532 nfc(PN532_IRQ_PIN, PN532_RESET_PIN, &Wire); Adafruit_PN532 nfc(PN532_IRQ_PIN, PN532_RESET_PIN, &Wire);
static unsigned long lastReadAt = 0; static unsigned long lastReadAt = 0;
static unsigned long lastWifiAttemptAt = 0;
static unsigned long lastPn532InitAt = 0;
static unsigned long lastPn532HealthAt = 0;
static String lastCredential = ""; static String lastCredential = "";
static bool wifiScanPrinted = false; 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 bytesToHex(const uint8_t *data, uint8_t length) {
String out; String out;
@@ -114,6 +124,10 @@ void printWifiScan() {
void connectWifi() { void connectWifi() {
if (WiFi.status() == WL_CONNECTED) return; if (WiFi.status() == WL_CONNECTED) return;
unsigned long now = millis();
if (lastWifiAttemptAt && now - lastWifiAttemptAt < WIFI_RETRY_MS) return;
lastWifiAttemptAt = now;
WiFi.persistent(false); WiFi.persistent(false);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.setSleep(false); 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) { bool readCardUid(uint8_t *uid, uint8_t *uidLength) {
if (!pn532Ready && !initializePn532()) return false;
return nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, uidLength, 350); return nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, uidLength, 350);
} }
@@ -173,7 +239,16 @@ String readMifareSecret(uint8_t *uid, uint8_t uidLength) {
String readCredential() { String readCredential() {
uint8_t uid[7] = { 0 }; uint8_t uid[7] = { 0 };
uint8_t uidLength = 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 #if CARD_MODE == CARD_MODE_MIFARE_CLASSIC_BLOCK
String secret = readMifareSecret(uid, uidLength); String secret = readMifareSecret(uid, uidLength);
@@ -215,20 +290,12 @@ void setup() {
connectWifi(); connectWifi();
Wire.begin(PN532_SDA_PIN, PN532_SCL_PIN); initializePn532(true);
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.");
} }
void loop() { void loop() {
connectWifi(); connectWifi();
maintainPn532();
String credential = readCredential(); String credential = readCredential();
if (!credential.length()) { if (!credential.length()) {