Carglglz / NFC_PN532_SPI

Partial Port of Adafruit CircuitPython to Micropython of PN532 NFC/RFID control library (SPI)
MIT License
41 stars 8 forks source link

read_passive_target() not recognizing tags not present from the start #1

Closed dracode closed 4 years ago

dracode commented 4 years ago

Hello,

I'm running your library on an ESP32. In my testing, if the tag is present at the reader when I call read_passive_target(), things work as expected. But if I present the tag to the reader after the call has already been made, but before the timeout period (left at default, 1 second) has expired, I get no response.

Expected behavior: a tag presented before the timeout expiration would be returned.

Am I misunderstanding something or is this not working as intended?

Thanks for porting this code!

Carglglz commented 4 years ago

Hi @dracode (I've just tested this library with an ESP8266 but I think there should not be any difference.)

Expected behavior: a tag presented before the timeout expiration would be returned.

This is not how it works, read_passive_target() sends a signal once (at the beginning) and then waits up to "timeout" seconds to receive a response.

From the docstring of the "call_function"

Send specified command to the PN532 and expect up to response_length bytes back in a response. Note that less than the expected bytes might be returned! Params can optionally specify an array of bytes to send as parameters to the function call. Will wait up to timeout seconds for a response and return a bytearray of response bytes, or None if no response is available within the timeout.

What I use is a timer interrupt with a timeout of 500 ms, and the timeout of the read_passive_target()of 100 ms. This will work as your expected behaviour.

I nicer way to do this is maybe to use a hardware interrupt with a IR/motion detector that triggers the scan 👍

dracode commented 4 years ago

Thanks for your reply!

I've been looking at the PN532 User Manual as well to try to understand this better.

It looks to me like the SAM_configuration() is setting up a 1 second timeout for the PN532 itself but the timer is actually ignored in "Normal mode" per page 89 of the above PDF, so we can disregard that.

But in the InListPassiveTarget section (page 115) says that the PN532 is actually doing the card-detection thing up to MxRtyPassiveActivation times (page 103) -- which appears to default to infinite (0xFF). So it seems likely that the PN532 could be detecting the card, we just aren't seeing the event at the host.

I'm attempting to replicate what's happening with the "Hot Wheels ID" toy where the sensor detects an NFC on a car as it speeds past the sensor. So even 100ms of "missed time" between polls results in detection failing most of the time.

Carglglz commented 4 years ago

@dracode , you are welcome!

My use case was for "check-in" into a place so there was no need for that speed. However if you tweak the code at call_function and _wait_ready you could get a 20 ms loop I think.

The thing is how to make the NFC car not to miss the scan signal while passing by, you may need to send the scan signal and wait as little as possible to receive a response, then scan again and so on, or you may need to send multiple scan signals one after another and then poll once.

Hard to say without the proper setup and doing some experiments, dig deep into the documentation so you can fine-tune the code and make it work in the range of the NFC car speeds. 👍

dracode commented 4 years ago

Found the bug and submitted pull request. Now it will respond any time during the timeout period.

Also found a fun trick:

read_passive_target(timeout=float('inf'))

This will effectively block forever until a card is presented, then return nearly immediately.

Carglglz commented 4 years ago

@dracode Thanks for this 🥇 , I see now that it was in fact a bug made while porting the code :( I can't test the code now, but as soon as a I can I will tell.

pd: I've already merged the pull request, thanks again! 👍