PN532 NFC RFID module を Arduino UNO  で読む

(Felica/Mifare/NFC チャレンジシリーズ) その他の記事はこちら 「Felica/Mifare/NFC でいろいろ実験」
https://qiita.com/nanbuwks/items/1f416d6e45a87250ee0a

-----

「PN532 NFC RFID module について調べる」
https://qiita.com/nanbuwks/items/ac02bb307c9850b5e5c4
で取り上げた基板について､ Arduino UNO に繋いで試してみました。

# 環境

- PN532 NFC RFID module
  - 電解コンデンサ追加加工済
  - cf., 「NFC モジュールの動作安定性を改善する」https://qiita.com/nanbuwks/items/a9217ba2e8f206b899b1
- Arduino 1.8.10 Linux版 (ポータブル化済)
- Arduino UNO

# 配線

PN532 NFC RFID module は I2C/SPI/高速シリアルで接続できます｡
今回は Arduino UNO に SPI で接続することにしました｡
以下のように配線しています｡

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/465492c7-9192-210f-b01b-9c40d72390a7.png)

|Arduino UNO|PN532 NFC Module |
|---|---|
|5V|VCC|
|(NC)|RSTQ|
|GND|GND|
|(NC)|IRQ|
|11|MISO|
|12|MOSI|
|13|SCK |
|10|SS|



なお、
「PN532 NFC RFID module について調べる」
https://qiita.com/nanbuwks/items/ac02bb307c9850b5e5c4
> SPI インターフェースでは保護抵抗がついているだけで5Vレベルの信号は避けたほうが良さそうです。

と考察しています。
今回はそのまま接続して実験していますが、長時間使う場合はレベルシフタなどを使う必要があるかも知れません｡

# ドライバ

NXP PN532 を Arduino で使う場合のライブラリは以下のようなものが開発されています。

- https://github.com/adafruit/Adafruit-PN532
- https://github.com/Seeed-Studio/PN532
- https://github.com/Seeed-Studio/Seeed_Arduino_NFC
- https://github.com/elechouse/PN532


2022/3/13時点でのスクリーンキャプチャーです。
adafruit/Adafruit-PN532
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/910d1327-62ad-a4d2-8ed1-e30678470375.png)
Seeed-Studio/PN532
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b089d88a-a07b-6661-15c0-74d800f73a3f.png)
下記のelechouseとも関係があるらしいですね。
Seeed-Studio/Seeed_Arduino_NFC
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/bef2f90b-be05-37f8-6366-8717c0c784bc.png)
elechouse/PN532
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/45c7ac9d-dd36-4be4-c775-17fc6a47a07a.png)
これは古そうです

この3つをインストールして試してみました｡

## 競合の注意
なお、この3つは相互によく似ていて競合を起こすようです。
 elechouse/PN532 をインストールしていると adafruit/Adafruit-PN532 で作ったものがボード認識しない状態になりました。



## Adafruit PN532 by Adafruit 

まずはこれから試してみます。

PN532 NFC/RFID controller breakout board - v1.6
https://www.adafruit.com/product/364

用のライブラリですが、 PN532 NFC RFID module とほぼ構成は同じで、ソフトウェア的には区別なく使用できるはずです。

### インストール

ライブラリマネージャから、
Adafruit PN532 by Adafruit をインストールします。

インストール時に下記の表示が出るので「Install all」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4b821da4-34e4-87bc-7559-61a34f88c28e.png)

「ファイル」-「スケッチ例」- 「カスタムライブラリのスケッチ例」-「Adafruit PN532」-「readMifareClassic」
 を出します。

配線接続にあわせて設定を変更します｡
以下の箇所

```

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>

// If using the breakout with SPI, define the pins for SPI communication.
#define PN532_SCK  (2)
#define PN532_MOSI (3)
#define PN532_SS   (4)
#define PN532_MISO (5)

// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines.  Use the values below (2, 3) for the shield!
#define PN532_IRQ   (2)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:

// Use this line for a breakout with a SPI connection:
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

// Use this line for a breakout with a hardware SPI connection.  Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins.  On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12.  The SS line can be any digital IO pin.
//Adafruit_PN532 nfc(PN532_SS);

// Or use this line for a breakout or shield with an I2C connection:
//Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

```

を以下のように変更します｡

```

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>

// If using the breakout with SPI, define the pins for SPI communication.
#define PN532_SCK  (2)
#define PN532_MOSI (3)
#define PN532_SS   (10)
#define PN532_MISO (5)

// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines.  Use the values below (2, 3) for the shield!
#define PN532_IRQ   (2)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:

// Use this line for a breakout with a SPI connection:
//Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);

// Use this line for a breakout with a hardware SPI connection.  Note that
// the PN532 SCK, MOSI, and MISO pins need to be connected to the Arduino's
// hardware SPI SCK, MOSI, and MISO pins.  On an Arduino Uno these are
// SCK = 13, MOSI = 11, MISO = 12.  The SS line can be any digital IO pin.
Adafruit_PN532 nfc(PN532_SS);

// Or use this line for a breakout or shield with an I2C connection:
//Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);
```
実行結果です。


```

Hello!
Found chip PN532
Firmware ver. 1.6
Waiting for an ISO14443A Card ...
Found an ISO14443A card
  UID Length: 4 bytes
  UID Value: 0x3C 0x64 0x36 0x63
Seems to be a Mifare Classic card #1013200483

Found an ISO14443A card
  UID Length: 4 bytes
  UID Value: 0x3C 0x64 0x36 0x63
Seems to be a Mifare Classic card #1013200483

Found an ISO14443A card
  UID Length: 4 bytes
  UID Value: 0x3C 0x64 0x36 0x63
Seems to be a Mifare Classic card #1013200483.
.
.
.

```
## Seeed-Studio/PN532 NFC library

### インストール

- https://github.com/don/NDEF から Zip ファイルをダウンロード
- https://github.com/Seeed-Studio/PN532 から Zip ファイルをダウンロード
- 上2つを解凍してできた NDEF-master , PN532, PN532_HSU  , PN532_I2C,   PN532_SPI,  PN532_SWHSU を librariesフォルダに移動 
   - portable   化しているので

### サンプルプログラム
「ファイル」-「スケッチ例」-「カスタムライブラリのスケッチ例」-「NDEF」-「ReadTag」を選びます
```

#if 0
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
#include <NfcAdapter.h>

PN532_SPI pn532spi(SPI, 10);
NfcAdapter nfc = NfcAdapter(pn532spi);
#else

#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
#endif
```
の

```
#if 0
```
を
```
#if 1
```

に変更する

### コンパイル失敗

No such file or directory
 #include "PN532Interface.h"
というエラーが出る。

## Seeed-Studio/Seeed_Arduino_NFC library

Seeedstudio NFC Shild などで使われているライブラリです。
https://wiki.seeedstudio.com/NFC_Shield_V2.0/

Seeedstudio NFC Shild も、PN532 NFC RFID module と基本的な構成は同じとなり、ソフトウェア的には同じものに見えるはずです｡


### インストール


を参考にして、

- Seeed_Arduino_NFC ページ https://github.com/Seeed-Studio/Seeed_Arduino_NFC から ZIP をダウンロード
- 「スケッチ」-「ライブラリをインクルード」-「.ZIP形式のライブラリをインストール」でダウンロードしたZIPファイルを選択する
- ライブラリフォルダ中に Seeed_Arduino_NFC-master ができる。今回は portable 化けるしていたので、 portable/sketchbook/libraries/Seeed_Arduino_NFC-master ができていた。

さて、このようにしてできた Seeed_Arduino_NFC-master の中に src/PN532 フォルダができている。
この中に Seeed-Studio/PN532 NFC library ライブラリ相当のものが収録されているようだ。


なお､
https://wiki.seeedstudio.com/Grove_NFC/
には以下のようにインストール作業が示されている｡

> Step 1. Download Seeed Arduino NFC Library.
> Step 2. Refer to How to install library to install Seeed Arduino NFC library for Arduino.
> Step 3. Download PN532 Library and put it under C:\Program Files (x86)\Arduino\libraries\Seeed_Arduino_NFC-master\src.
> Step 4. Open “ReadTag” code via the path: File → Examples → ReadTag.


ここまででやったのは Step.2 まで｡ Step 3. ではhttps://github.com/Seeed-Studio/PN532 の内容で上書きするように示されている｡実際､タイムスタンプが https://github.com/Seeed-Studio/PN532 にあるもののほうが新しい｡しかしながらそのように作業をするとコンパイル時にエラーが出た｡パス設定がミスマッチしているようだ。今回はStep 2. までの作業をして実験。

### サンプルプログラム

「ファイル」-「スケッチ例」-「カスタムライブラリのスケッチ例」-「Seeed_Arduino_NFC」-「ReadTag」を選びます。
```

#include <NfcAdapter.h>
#include <PN532/PN532/PN532.h>

#if 0 // use SPI
    #include <SPI.h>
    #include <PN532/PN532_SPI/PN532_SPI.h>
    PN532_SPI pn532spi(SPI, 9);
    NfcAdapter nfc = NfcAdapter(pn532spi);
#elif 1 // use hardware serial

    #include <PN532/PN532_HSU/PN532_HSU.h>
    PN532_HSU pn532hsu(Serial1);
    NfcAdapter nfc(pn532hsu);
#elif 0  // use software serial

    #include <PN532/PN532_SWHSU/PN532_SWHSU.h>
    #include "SoftwareSerial.h"
    SoftwareSerial SWSerial(2, 3);
    PN532_SWHSU pn532swhsu(SWSerial);
    NfcAdapter nfc(pn532swhsu);
#else //use I2C

    #include <Wire.h>
    #include <PN532/PN532_I2C/PN532_I2C.h>

    PN532_I2C pn532_i2c(Wire);
    NfcAdapter nfc = NfcAdapter(pn532_i2c);
#endif
```

これを

```

#include <NfcAdapter.h>
#include <PN532/PN532/PN532.h>

#if 1 // use SPI
    #include <SPI.h>
    #include <PN532/PN532_SPI/PN532_SPI.h>
    PN532_SPI pn532spi(SPI, 10);
    NfcAdapter nfc = NfcAdapter(pn532spi);
#elif  // use hardware serial

    #include <PN532/PN532_HSU/PN532_HSU.h>
    PN532_HSU pn532hsu(Serial1);
    NfcAdapter nfc(pn532hsu);
#elif 0  // use software serial

    #include <PN532/PN532_SWHSU/PN532_SWHSU.h>
    #include "SoftwareSerial.h"
    SoftwareSerial SWSerial(2, 3);
    PN532_SWHSU pn532swhsu(SWSerial);
    NfcAdapter nfc(pn532swhsu);
#else //use I2C

    #include <Wire.h>
    #include <PN532/PN532_I2C/PN532_I2C.h>

    PN532_I2C pn532_i2c(Wire);
    NfcAdapter nfc = NfcAdapter(pn532_i2c);
#endif

```

とします。

```
NDEF Reader
Found chip PN532
Firmware ver. 1.6

Scan a NFC tag


Scan a NFC tag

Tag is not NDEF formatted.
NFC Tag - Mifare Classic
UID 3C 64 36 63

No NDEF Message

Scan a NFC tag

```
となりました
かなり反応が悪いです。



## elechouse PN532 library

https://github.com/elechouse/PN532

対応しているボード

- Elechouse NFC Module
- Seeed Studio NFC Shield
- Xadow NFC
- Adafruit PN532 N


### インストール

上記のページの記述
> Download zip file and extract the three folders(PN532, PN532_SPI, PN532_HSU and PN532_I2C) into libraries of Arduino.
> Downlaod Don's NDEF library and extract it into libraries of Arduino's into a new folder called "NDEF" (Note if you leave this folder as NDEF-Master Arduino will not be able to use it as a library)
> Follow the examples of the PN532 library

の通りにしてみます。

- https://github.com/elechouse/PN532 ページからZIPファイルをダウンロードして解凍
- PN532, PN532_SPI, PN532_HSU, PN532_I2C フォルダを libraries フォルダに移動
  - 今回は portable 化していたので、 libraries フォルダ内に格納
- https://github.com/don/NDEFページからZIPファイルをダウンロードして解凍
- NDEF フォルダを libraries フォルダ内に作り、解凍したものを格納

### サンプルプログラム


「ファイル」-「スケッチ例」-「カスタムライブラリのスケッチ例」-「PN532」-「ReadMifare」を選びます。
```

#if 0
  #include <SPI.h>
  #include <PN532_SPI.h>
  #include "PN532.h"

  PN532_SPI pn532spi(SPI, 10);
  PN532 nfc(pn532spi);
#elif 1
  #include <PN532_HSU.h>
  #include <PN532.h>
      
  PN532_HSU pn532hsu(Serial1);
  PN532 nfc(pn532hsu);
#else 
  #include <Wire.h>
  #include <PN532_I2C.h>
  #include <PN532.h>
  PN532_I2C pn532i2c(Wire);
  PN532 nfc(pn532i2c);	
#endif
```
を以下に変更します

```

#if 1
  #include <SPI.h>
  #include <PN532_SPI.h>
  #include "PN532.h"

  PN532_SPI pn532spi(SPI, 10);
  PN532 nfc(pn532spi);
#elif 0
  #include <PN532_HSU.h>
  #include <PN532.h>
      
  PN532_HSU pn532hsu(Serial1);
  PN532 nfc(pn532hsu);
#else 
  #include <Wire.h>
  #include <PN532_I2C.h>
  #include <PN532.h>
  PN532_I2C pn532i2c(Wire);
  PN532 nfc(pn532i2c);	
#endif
```
### 実行結果
```

Waiting for an ISO14443A Card ...
Hello!
Found chip PN532
Firmware ver. 1.6
Waiting for an ISO14443A Card ...
Found an ISO14443A card
  UID Length: 4 bytes
  UID Value:  C5 B2 0F AD

Seems to be a Mifare Classic card (4 byte UID)
Trying to authenticate block 4 with default KEYA value
Sector 1 (Blocks 4..7) has been authenticated
Reading Block 4:
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

```

# Felica対応

今までのテストは MiFare カードを認識するかどうかで試していました。PN532はFeliCaも対応していますが、ライブラリでの対応は
elechouse/PN532 のみのようです。

Adafruit-PN532 ライブラリでがんばっている方もおられますが自前で作り込まないといけない感じです。
http://lantaukwcounter.blogspot.com/2015/11/reading-octopus-card-ids-felica-with.html
https://stackoverflow.com/questions/58697049/pn532-trying-to-obtain-model-number-of-device-from-felica-tags


elechouse/PN532 には必要な機能が備わっているようです。


# 考察


- https://github.com/adafruit/Adafruit-PN532
- https://github.com/Seeed-Studio/PN532
- https://github.com/Seeed-Studio/Seeed_Arduino_NFC
- https://github.com/elechouse/PN532

この4つを試してみましたが、Seeed-Studio の2つは調子が悪い感じでした。

Adafruit と elechouse は Mifare でチェックする限りでは快調そうです。

レポジトリの更新頻度的には adafruit が良いですが、FeliCa を使う場合は  elechouse  一択のようです。

elechouse のライブラリでは、いくつか問題が報告されているようですが下記については現在解決しているかどうかは不明です。
https://forum.nfcring.com/topic/55/elechouse-pn532-nfc-module-v3-for-arduino-etc/113