nfcpy / nfcpy

A Python module to read/write NFC tags or communicate with another NFC device.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PN532: Powerdown command on shutdown prevents further communication

matthijskooijman opened this issue · comments

I'm using this library with a PN532 device, communicating over HSU. However, when I properly close down the library, using clf.close(), I can no longer start communication afterwards (I get a communication timeout).

I highly suspect that this might be a firmware issue in the PN532 chip, but I wondered if anyone else has been seeing the same.

The problem seems to be caused by the powerdown command that is sent as the last command here:

self.chipset.power_down(wakeup_enable=("I2C", "SPI", "HSU"))

It does specify that it should allow wakeup on HSU, but it seems it does not. When I remove that powerdown command, everything works as expected. I tried removing all other code from that close function (i.e. the extra ACK, delay and baudrate change), leaving just the powerdown and I also tried replacing that other code with a 1 second delay (after reading this post of someone having a problem when powerdown was issued shortly after another command), but in both cases the problems persisted.

I also checked the UART lines using a logic analyzer, and confirmed that the communication looks as expected: The last command is the powerdown command, with the right bits set, which is confirmed with a response with status=0. Then, trying to restart my application, I see the get version command with a bunch of leading zeroes as a preamble transmitted correctly, but no reply is sent.

Note that I've modified the library slightly to not change the baudrate (to make it easier to restart when communication is interrupted), but I do not believe this is relevant here.

So, now I wonder:

  • Are others seeing the same issue with the PN532? Or is this working for everyone else?
  • If this is indeed broken in the firmware, should nfcpy maybe not send the powerdown command? Or maybe make it optional at least?

I also tried changing the powerdown command to:

 self.chipset.power_down(wakeup_enable=("HSU",)) 

Just in case wakeup on the other sources somehow confused the firmware, but that did not help either.

Hello!
Might help others, but I found a very simple workaround that works in this case, just trying again haha. It's in .NET but same process can be translated for python, I guess they have same functions.

     public void PowerDown() {
         while(_Pn532.PowerDown(WakeUpEnable.I2c)) {
             Console.WriteLine("Could not power down PN532. Trying again...");
             Thread.Sleep(500);
         }
         Console.WriteLine("PN532 successfully powered down.");
     }

@jeremielalanne Thanks for your comment. But my issue was that the powerdown did (I guess - cannot remember if there was some kind of ACK or not) succesful, it's just that it would not respond to further commands after that - i.e. it would not wake up. Or are you seeing the same if you try powerdown only once and that command is not succesful? And then trying the powerdown again until it does get an ACK does allow it to powerup again?

@jeremielalanne Thanks for your comment. But my issue was that the powerdown did (I guess - cannot remember if there was some kind of ACK or not) succesful, it's just that it would not respond to further commands after that - i.e. it would not wake up. Or are you seeing the same if you try powerdown only once and that command is not succesful? And then trying the powerdown again until it does get an ACK does allow it to powerup again?

Yes I understand your issue, I was having the same :) When for example I would soft reboot, or restart the app, I couldn't communicate with it anymore, it wouldn't respond, because the communication did not end correctly at first. But adding a retry process made it work. It almost always failed at first try, but now it succeeds at second. i tried to restart my app few times, soft reboot, worked each time :) it surely isn't a perfect solution, but a workaround. Some kind of cancellation token should be added to it to avoid infinite loop.