adafruit / Adafruit_CircuitPython_PN532

CircuitPython driver for the PN532 NFC/RFID Breakout and PN532 NFC/RFID Shield
MIT License
91 stars 47 forks source link

SPI read_passive_target timeout not working correctly #19

Closed BraindeadBZH closed 5 years ago

BraindeadBZH commented 5 years ago

Hi,

When in SPI mode calling read_passive_target with a timeout, a NFC tag is only detect at the very beginning of the poll. This is not the case with i2c which detects tags through all the duration of the timeout.

tgikal commented 5 years ago

The SPI and I2C interfaces use an entirely different backend. The problem looks like it's occurring in adafruit_pn532/spi.py -> _wait_ready.

I believe it's related to the with self._spi as spi: statement calling the class each iteration of the while loop:

def _wait_ready(self, timeout=1):
    """Poll PN532 if status byte is ready, up to `timeout` seconds"""
    status = bytearray([reverse_bit(_SPI_STATREAD), 0])

    timestamp = time.monotonic()
    while (time.monotonic() - timestamp) < timeout:
        with self._spi as spi:
            time.sleep(0.02)   # required
            spi.write_readinto(status, status) #pylint: disable=no-member
        if reverse_bit(status[1]) == 0x01:  # LSB data is read in MSB
            return True      # Not busy anymore!
        else:
            time.sleep(0.01)  # pause a bit till we ask again
    # We timed out!
    return False

Changing the while loop around a bit seems to have corrected it:

def _wait_ready(self, timeout=1):
    """Poll PN532 if status byte is ready, up to `timeout` seconds"""
    status = bytearray([reverse_bit(_SPI_STATREAD), 0])

    timestamp = time.monotonic()
    with self._spi as spi:
        while (time.monotonic() - timestamp) < timeout:
            time.sleep(0.02)   # required
            spi.write_readinto(status, status) #pylint: disable=no-member
            if reverse_bit(status[1]) == 0x01:  # LSB data is read in MSB
                return True      # Not busy anymore!
            else:
                time.sleep(0.1)  # pause a bit till we ask again
    # We timed out!
    return False
caternuson commented 5 years ago

@BraindeadBZH Please try the 2.0.7 version of the library when it becomes available: https://github.com/adafruit/Adafruit_CircuitPython_PN532/releases/tag/2.0.7

BraindeadBZH commented 5 years ago

Thank you for fixing the issue. Unfortunately I don't have access to the hardware to test this at the moment. I will let you know if I have the chance to get back to this.

caternuson commented 5 years ago

OK. Closing for now. We can reopen if you continue to have the same issue.