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

Using serial with the FTDI cable causes the library to hang when a card is read #58

Closed AnasMalas closed 1 year ago

AnasMalas commented 1 year ago

Hello! While im sure there must be a way to do this, I bought the PN532 breakout and an FTDI cable thinking setup would be a breeze. Two days of tinkering later, im pulling my hair (in part due to my inexperience).

The LibNFC part of the official guide is outdated, and I understand why it is. But it seems like this may be the only way to "easily" use the FTDI cable (looking at that project's issue log, im not the only one with issues, and LibNFC seems like it has been abandoned). I was not able to configure it on my raspberry pi to use ttyUSB0, and it no longer supports autoscan. The version used in the guide seems to no longer be compatible with newer OS versions.

To my untrained eye, I think it may not be all too difficult to adapt the simpletest example to talk over the FTDI serial port. My hope is that this would be relatively easy and thus added as an official example without burden, as well as in documentation so that people buying this reader would find it easier than I did.

dhalbert commented 1 year ago

You did not describe in detail what didn't work when you tried using the serial cable. To use serial on a Linux machine, there are a couple of things you might need to do. They are described here:

Add your user to the dialout group to get permission to access /dev/tty*: https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console#setting-permissions-on-linux-3027345

The port might have a different name. If you can't find /dev/ttyUSB0, it might be /dev/ttyAMA0.

Remove modemmanager, if it is present and interferering (I'm not sure this would happen on Raspberry Pi OS): https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console#serial-console-issues-or-delays-on-linux-3105120

AnasMalas commented 1 year ago

Sorry if it wasn't clear. The guide for the PN532 only shows the FTDI cable being used with LibNFC, not circuit python. I will try the above steps to maybe get LibNFC working.

My suggestion was to have an example in circuit python that uses the cable. As I am very new to both python and circuit python I dont know how to implement that (if its even possible). In the simpletest example there are 3 methods to communicate, it would be awesome if USB to serial adapters are added too as a fourth option

AnasMalas commented 1 year ago

After digging into python, I started to understand the picture better, and decided to try to use a PySerial instance instead of a busio UART instance. The module starts successfully and waits for a card. However, when a card is presented, the code hangs fully. No error message, just nothing. Here's my code:

import serial
import serial.tools.list_ports

from adafruit_pn532.uart import PN532_UART

ser = serial.Serial("/dev/ttyUSB0", baudrate=115200)
pn532 = PN532_UART(ser, debug=True)

ic, ver, rev, support = pn532.firmware_version
print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))

# Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration()

print("Initialized. Waiting for RFID/NFC card...")
while True:
    # Check if a card is available to read
    uid = pn532.read_passive_target(timeout=0.5)
    print(".", end="")
    # Try again if no card is available.
    if uid is None:
        continue
    print(uid)
    print("Found card with UID:", [hex(i) for i in uid])

and here's the output. No further output is received after the card is tapped:

Write frame:  ['0x0', '0x0', '0xff', '0x5', '0xfb', '0xd4', '0x14', '0x1', '0x14', '0x1', '0x2', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd5', '0x15', '0x16', '0x0']
Read frame: ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd5', '0x15', '0x16', '0x0']
Write frame:  ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd4', '0x2', '0x2a', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x6', '0xfa', '0xd5', '0x3', '0x32', '0x1', '0x6', '0x7', '0xe8', '0x0']
Read frame: ['0x0', '0x0', '0xff', '0x6', '0xfa', '0xd5', '0x3', '0x32', '0x1', '0x6', '0x7', '0xe8', '0x0']
Write frame:  ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd4', '0x2', '0x2a', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x6', '0xfa', '0xd5', '0x3', '0x32', '0x1', '0x6', '0x7', '0xe8', '0x0']
Read frame: ['0x0', '0x0', '0xff', '0x6', '0xfa', '0xd5', '0x3', '0x32', '0x1', '0x6', '0x7', '0xe8', '0x0']
Found PN532 with firmware version: 1.6
Write frame:  ['0x0', '0x0', '0xff', '0x5', '0xfb', '0xd4', '0x14', '0x1', '0x14', '0x1', '0x2', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd5', '0x15', '0x16', '0x0']
Read frame: ['0x0', '0x0', '0xff', '0x2', '0xfe', '0xd5', '0x15', '0x16', '0x0']
Initialized. Waiting for RFID/NFC card...
Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']

Regarding your suggestions, I tried them but I still get the same output whether for this library or libnfc

AnasMalas commented 1 year ago

It stops returning even None. I changed the loop to

while True:
    # Check if a card is available to read
    uid = pn532.read_passive_target(timeout=0.5)
    print(".", end="")
    print("Found card with UID:", uid)

last lines of output:

.Found card with UID: None
Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
.Found card with UID: None
Write frame:  ['0x0', '0x0', '0xff', '0x4', '0xfc', '0xd4', '0x4a', '0x1', '0x0', '0xe1', '0x0']
Reading:  ['0x0', '0x0', '0xff', '0x0', '0xff', '0x0']
AnasMalas commented 1 year ago

possibly related to #44

caternuson commented 1 year ago

Try changing this:

ser = serial.Serial("/dev/ttyUSB0", baudrate=115200)

to:

ser = serial.Serial("/dev/ttyUSB0", baudrate=115200, timeout=0.1)

pyserial's default timeout is None which means it'll wait forever on the read: https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial

The library may be trying to read more bytes than being returned. So need the serial timeout to prevent blocking forever.

FoamyGuy commented 1 year ago

Resolved by #63