PN5180 Deepsleep

Ich meine mein Problem mit dem PN5180 auf die Implementierung zurückführen zu können, daher hätte ich hier einige Fragen, wo mir diese nicht ganz klar ist.

Zuerst einmal ganz allgemein: Woher kommt die Einschränkung, dass nur ISO-14443 Tags zum Aufwecken verwendet werden können? Bei mir löst eine andere Karte auch zuverlässig den Interrupt aus, könnte ich diese nicht auch ganz normal lesen?

Zur Implementierung:

Es gibt zwei Funktionen die den ESP32 in den Tiefschlaf versetzen und vorher LPCD aktivieren. Das ist einmal Rfid_EnableLpcd(), welches aufgerufen wird nachdem der ESPuino normal an war. Dann gibt es noch Rfid_WakeupCheck(). Dieses schaut ob der RFID den ESP geweckt hat und geht wieder in den Deepsleep wenn keine Karte aufliegt.

  1. static PN5180 nfc(...); vs static PN5180ISO14443 nfc14443(...);
    Hier wird einmal speziell 14443 verwendet und einmal die generische Version. Wacht deshalb mein ESP zuverlässig auch bei anderen Karten auf oder hat das keine Bedeutung?
  2. esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ALL_LOW);
    esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH);
    Der Wakeup wird einmal auf All_LOW und auf ANY_HIGH eingestellt. Der Reader sollte ja auf active low eingestellt sein, wacht er dann nicht natürlich immer auf?
  3. Im WakeupCheck wird der interrupt für den Button nicht neu gesetzt, weil Button_Init() erst nach RFID_Init() ausgeführt wird. Daher klappt das Aufwecken mittels Button dann auch nicht mehr.
  4. Andere, kleine Unterschiede, wie z.B. dass nfc.prepareLPCD(); nur in einer Funktion aufgerufen wird

Hier nochmal als Referenz der Code

Rfid_EnableLpcd()
    // Handles activation of LPCD (while shutdown is in progress)
    void Rfid_EnableLpcd(void) {
        // goto low power card detection mode
        #ifdef PN5180_ENABLE_LPCD
            static PN5180 nfc(RFID_CS, RFID_BUSY, RFID_RST);
            nfc.begin();
            // show PN5180 reader version
            uint8_t firmwareVersion[2];
            nfc.readEEprom(FIRMWARE_VERSION, firmwareVersion, sizeof(firmwareVersion));
            Serial.print(F("Firmware version="));
            Serial.print(firmwareVersion[1]);
            Serial.print(".");
            Serial.println(firmwareVersion[0]);
            // check firmware version: PN5180 firmware < 4.0 has several bugs preventing the LPCD mode
            // you can flash latest firmware with this project: https://github.com/abidxraihan/PN5180_Updater_ESP32
            if (firmwareVersion[1] < 4) {
                Serial.println(F("This PN5180 firmware does not work with LPCD! use firmware >= 4.0"));
                return;
            }
            Serial.println(F("prepare low power card detection..."));
            uint8_t irqConfig = 0b0000000; // Set IRQ active low + clear IRQ-register
            nfc.writeEEprom(IRQ_PIN_CONFIG, &irqConfig, 1);
            /*nfc.readEEprom(IRQ_PIN_CONFIG, &irqConfig, 1);
            Serial.print(F("IRQ_PIN_CONFIG=0x"));
            Serial.println(irqConfig, HEX);*/
            nfc.prepareLPCD();
            Serial.print(F("PN5180 IRQ PIN: "));
            Serial.println(Port_Read(RFID_IRQ));
            // turn on LPCD
            uint16_t wakeupCounterInMs = 0x3FF; //  must be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms.
            if (nfc.switchToLPCD(wakeupCounterInMs)) {
                Serial.println(F("switch to low power card detection: success"));
                // configure wakeup pin for deep-sleep wake-up, use ext1
                #if (RFID_IRQ >= 0 && RFID_IRQ <= 39)
                    esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ALL_LOW);
                #endif
                // freeze pin states in deep sleep
                gpio_hold_en(gpio_num_t(RFID_CS));  // CS/NSS
                gpio_hold_en(gpio_num_t(RFID_RST)); // RST
                gpio_deep_sleep_hold_en();
            } else {
                Serial.println(F("switchToLPCD failed"));
            }
        #endif
    }
Rfid_WakeupCheck()
    // wake up from LPCD, check card is present. This works only for ISO-14443 compatible cards
    void Rfid_WakeupCheck(void) {
        #ifdef PN5180_ENABLE_LPCD
            // disable pin hold from deep sleep
            gpio_deep_sleep_hold_dis();
            gpio_hold_dis(gpio_num_t(RFID_CS));  // NSS
            gpio_hold_dis(gpio_num_t(RFID_RST)); // RST
            #if (RFID_IRQ >= 0 && RFID_IRQ <= 39)
                pinMode(RFID_IRQ, INPUT);
            #endif
            static PN5180ISO14443 nfc14443(RFID_CS, RFID_BUSY, RFID_RST);
            nfc14443.begin();
            nfc14443.reset();
            // enable RF field
            nfc14443.setupRF();
            if (!nfc14443.isCardPresent()) {
                nfc14443.reset();
                uint16_t wakeupCounterInMs = 0x3FF; //  needs to be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms.
                if (nfc14443.switchToLPCD(wakeupCounterInMs)) {
                    Log_Println((char *) FPSTR(lowPowerCardSuccess), LOGLEVEL_INFO);
                    // configure wakeup pin for deep-sleep wake-up, use ext1
                    esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH);
                    // freeze pin states in deep sleep
                    gpio_hold_en(gpio_num_t(RFID_CS));  // CS/NSS
                    gpio_hold_en(gpio_num_t(RFID_RST)); // RST
                    gpio_deep_sleep_hold_en();
                    Log_Println((char *) FPSTR(wakeUpRfidNoIso14443), LOGLEVEL_ERROR);
                    esp_deep_sleep_start();
                } else {
                    Serial.println(F("switchToLPCD failed"));
                }
            }
            nfc14443.end();
        #endif
    }

Was ist das für eine Karte? Soweit ich weiß kann LPCD nur für ISO-14443 Karten verwendet werden. Eine ISO-15693 Karte oder Tonie funktioniert bei mir jedenfalls nicht. Der Leser wird ja im LPCD Modus mit einem bestimmten RF-Protokoll initialisiert und kann nur einen Kartentyp erkennen. Hier gibt es die technische Beschreibung: „11.8.10 Low-Power Card Detection (LPCD)

1: Macht keinen Unterschied. Nur wenn eine ISO-14443 Karte gelesen werden soll benötigt man auch die Klasse dazu. Für LPCD Initialisierung reicht die generische PN5180 Klasse.
2. @biologist benötigte für den Port-Expander die umgekehrte IRQ Logik, das wurde vor ca. 2 Wochen umgebaut. Ich habe hier den Eindruck das dort noch ein kleiner Bug schlummert, mein ESP wacht alle 2/3 Sek. auf und legt sich dann wieder schlafen. Das war vor dem Umbau nicht so.
3. Kann das bestätigen, ist ein Bug: Vor dem deep-sleep muss der Button als Wake-Up source registriert werden…
4. ? Was meinst Du genau damit?

ISO-15693 lösen bei mir halt immer den IRQ aus, bin mir nicht sicher wie das mit dem lesen ist, aber wenn der ESP32 eh schon wach ist kann er ja die Karte auch im Wachzustand lesen. Vielleicht ist mein Lesegerät auch nur besonders empfindlich :smiley:

Ich bin mir jetzt recht sicher, dass 2. auch ein Bug ist. Wenn ich beides mal ESP_EXT1_WAKEUP_ALL_LOW setze, funktioniert bei mir eigentlich alles. Ich hätte gesagt, dass bei mir öfter als 2-3 Sekunden (vll. jede Sekunde) das Aufwachen ausgelöst wird. Schau mal ob dein Problem weg ist wenn du das ANY_HIGH zu ALL_LOW änderst.

Naja, prepareLPCD() hört sich wichtig an, wird aber im Wakeupcheck nicht aufgerufen.

Also wenn bei Dir der Leser bei einer ISO-15693 Karte einen IRQ auslöst könnte der ESPuino auch damit aufgeweckt werden und Musik abspielen. Es müsste dann im WakeUp-Check auf beide Kartentypen geprüft werden, genauso wie jetzt in der RFID-Schleife. Idealerweise für die Kartenprüfung nur eine einzige Routine.

Jetzt ist aber so das für LPCD viel Aufwand betrieben wurde und der Nutzen eher klein ist (Man kann ja auch den Knopf drücken zum Aufwecken). @biologist verdreht schon die Augen bei dem bisherigen Aufwand :wink:

Ich würde vorschlagen zunächst die Bugs zu fixen und das erst im nächsten Schritt zu erweitern. @SZenglein wollen wir das gemeinsam machen und dann einen PR erstellen um Torsten an dieser Baustelle zu entlasten?

2: Ja definitiv ein Bug: Der ESP schläft normalerweise ewig bis dem PN5180 etwas vor die Birne kommt. Jetzt kommt der IRQ alle 3 Sek… Das ist genau wakeupCounterInMs So nicht richtig…
4: prepareLPCD() setzt die LPCD Werte im EEProm des PN5180. Das muss im WakeUpCheck nicht erneut gemacht werden. Alle Werte bleiben so. Sehe hier kein Problem…

Ah okay, dann sollte es ja eigentlich ausreichen, die eine Zeile zum Interrupt zu ändern. (+ Button init)

Bin dabei einen Pull zu erstellen der bei uns beiden klappt, dann muss Torsten das nicht mehr testen.

Das wäre sehr cool - danke :+1:.
Ich teste das dann im Anschluss einfach auch mit Port-Expander.

@SZenglein Ich habe deinen Fix mittels Port-Expander getestet. Funktioniert fein :+1:
Daher habe ich es auch gleich gemergt. Vielen Dank!