🪪

Raspberry PiでPN532を使うメモ

に公開

使ったもの

  • Raspberry Pi Zero W
  • PN532 NFC MODULE V3(本体に書いてあった)

Raspberry Piのセットアップ

ここではPythonのライブラリであるnfcpyを使うので公式ドキュメントに従ってインストールします。
Python3やpipなどは前回と同じなのでそちらを参照して入れてください。
https://zenn.dev/ichidomisssuru/articles/9b1abbd47839c3

nfcpyをインストールする

nfcpyをインストールします。

bash
~$ pip install -U nfcpy

ひとまず、呪文も入れておきます。

bash
~$ sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"02e1\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'
~$ sudo udevadm control -R # then re-attach device

raspi-configを変更する

raspi-configでシリアル通信をオンにします。

bash
sudo raspi-config

3 Interface OptionsI6 Serial Port
Would you like a login shell to be accessible over serial?と聞かれますがNoを選択
そのあとにWould you like the serial port hardware to be enabled?を聞かれるのでYesを選択
最後にOKを選択してEscで脱出します。

シリアル通信をしているインターフェースを確認する

とりあえず、dialoutグループに今ログインしているユーザーを追加します。

bash
~$ sudo usermod -a -G dialout $USER

シリアル通信しているインターフェースを確認します。

bash
~$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 7 Apr 29 15:15 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 Apr 29 15:15 /dev/serial1 -> ttyS0

ttyAMA0があることを確認します。
これはPN532とUARTを使ってシリアル通信するためのインターフェースです。

BluetoothとUARTが衝突しないようにBluetooth機能をオフにします。

bash
~$ sudo nano /boot/config.txt

[all]の下に以下の文を追加します。

/boot/config.txt
[all]
enable_uart=1
dtoverlay=pi3-disable-bt

PN532を接続する

PN532を接続するためにシャットダウンします。

bash
sudo shutdown -h now

画像のようにPN532のDIPスイッチをすべて下げます。
PN532の写真
HSU(High Speed Uart)になるようにしてください。
そしてリストのように配線します。
GPIOの配置は画像を参照してください。

Raspi PN532
5V 5V
GND GND
TXD(GPIO14) RXD(SCL)
RXD(GPIO15) TXD(SDA)

Raspberry Pi GPIO配置
このようにTXD RXDがそれぞれ対になるようにツイストで配線します。

nfcpyでテスト

正しく通信できるかテストします。

bash
~$ python3 -m nfc --search-tty
This is the 1.0.4 version of nfcpy run in Python 3.9.2
on Linux-6.1.21+-armv6l-with-glibc2.31
I'm now searching your system for contactless devices
** found PN532v1.6 at /dev/ttyAMA0

ttyAMA0のインターフェースを使ってPN532と通信できたようです。
配線ミスをするとERROR:nfc.clf:no reader available on path tty:AMA0が返されます。

nfcpyでカード情報を取得する

python3でプログラムを組んで実行してみます。

card_dump.py
import nfc

def on_connect(tag):
    print(tag)
    print(('  \n  '.join(tag.dump())))
    
    return True  # 1枚だけ読み取って終了

def main():
    try:
        clf = nfc.ContactlessFrontend('tty:AMA0')  #環境によってtty:S0 などに変更
        clf.connect(rdwr={'on-connect': on_connect})
    finally:
        if clf:
            clf.close()

if __name__ == "__main__":
    main()

モバイルsuicaを読み取ると次のような感じに

bash
~$ python3 card_dump.py
Type4ATag MIU=253 FWT=0.038664

情報が少なくて寂しいですが問題なく読み取れました。

余談

ほかのqiitaなどにあるコードを使用するとエラーが多発しました。

err_card_dump.py
import nfc

clf = nfc.ContactlessFrontend("tty:AMA0")
tag = clf.connect(rdwr={'on-connect': lambda tag: False})
print(tag)
print(('  \n  '.join(tag.dump())))

タイミング等の何か理由があるんでしょうがよくわからないので使うことは避けたほうがいいでしょう。

Discussion