こんにちは、イシイです。

NFCタグを使うと、それぞれ物体などを個別に判別できるようになります。そのため、何かのモノにNFCタグを付与しておいて、それを認識して得た情報に応じたアクションをさせる、ということが容易にできるようになります。例えば、社員証を使った入館の仕組みや、モノを置いたらそのモノの情報を表示してくれる、みたいなものがわかりやすいかと思います。
今回は、その仕組みを簡素化して、Arduinoに設置したNFCシールドからNFCタグを読み取り、vvvvでNFCタグ毎に設定した色を描画する、ということを行ってみました。

事前準備

使用するもの

使用するArduinoですが、1つ前のバージョンのブルーのArduino Unoだと、後にインストールするPN532ライブラリ使用時にエラーが出てしまったので、現在のグリーンの方をオススメします。Arduino Megaでも問題なさそうでした。

Arduinoで使う準備

それではまず、NFC Shield V2.0 Wikiに則って、Arduinoの環境を整えます。

1. Arduino IDEを開いていたら、まず閉じておく
2. PN532をGitHubからダウンロード
3. PN532-master内の、PN532, PN532HSU, PN532SPI, PN532_I2CフォルダをArduinoライブラリフォルダにコピー(※NDEFフォルダはコピーしない)
4. NDEFをGitHubからダウンロード
5. NDEF-masterをNDEFにリネーム
6. リネームしたNDEFフォルダをArduinoライブラリフォルダにコピー
7. Arduinoを開き、スケッチのExampleにNDEFとPN532が表示されていることを確認

これで、NFCリーダーとして使用するNFC Shield V2.0の準備ができました。NFC Shield V2.0をArduinoと合体させて、ArduinoとPCをUSBケーブルでつないでおきましょう。

サンプルコードを動かしてみる

では、NFC Shield V2.0 Wiki にあるサンプルコードをいくつか動かしてみます。

タグ情報を表示してみる

read()で、NFCタグの中身をシリアルモニターで見てみます。

#include <SPI.h>
#include "PN532_SPI.h"
#include "PN532.h"
#include "NfcAdapter.h"

PN532_SPI interface(SPI, 10);
NfcAdapter nfc = NfcAdapter(interface);

void setup(void) {

  Serial.begin(115200);
  Serial.println("NDEF Reader");
  nfc.begin();

}

void loop(void) {

  Serial.println("\nScan an NFC tag\n");
  if (nfc.tagPresent()) 
  {
    NfcTag tag = nfc.read();
    tag.print();
  }
  
  delay(500);

}

このスケッチを動かしてNFCタグをリーダーに近づけてみると、タグのタイプとUIDが表示されていることが確認できました。

thumb_1

タグにデータを書き込んでみる

今度はwrite()で、NFCタグにメッセージを書き込んでみます。ちなみにNFCでは、NDEF(NFC Data Exchange Format)というデータ・フォーマットになります。

#include <SPI.h>
#include "PN532_SPI.h"
#include "PN532.h"
#include "NfcAdapter.h"

PN532_SPI interface(SPI, 10);

NfcAdapter nfc = NfcAdapter(interface);

void setup(void) 
{

  Serial.begin(115200);
  Serial.println("NDEF Reader");
  nfc.begin();
  
}

void loop(void) 
{
  
  Serial.println("Place a formatted Mifare Classic NFC tag on the reader.");
  
  if(nfc.tagPresent())
  {
  
    NdefMessage message = NdefMessage();
    message.addUriRecord("Hello, world!");
    message.addUriRecord("How are you today?");

    bool success = nfc.write(message);
    if(success)
    {
      Serial.println("The message was successfully written to the tag.");
    }else{
      Serial.println("Message write failed.");
    }
  }

  delay(5000);
    
}

このスケッチを動かしてNFCタグをリーダーに近づけてみると、メッセージの書き込みができたようです。

thumb_2

ちなみに書き込めるデータ量は、タグによって異なります。

タグに書き込んだデータを見てみる

ではこれから正しくメッセージが書き込まれているのかを確認してみます。NDEFフォーマットで書き込まれたメッセージをread()を使って読んでみます。

#include <SPI.h>
#include "PN532_SPI.h"
#include "PN532.h"
#include "NfcAdapter.h"

PN532_SPI interface(SPI, 10);

NfcAdapter nfc = NfcAdapter(interface);

void setup(void) 
{

  Serial.begin(115200); 
  Serial.println("NDEF Reader");
  nfc.begin(); 
    
}

void loop(void) 
{

  Serial.println("\nScan an NFC tag\n");
  
  if (nfc.tagPresent()) 
  {
    
    NfcTag tag = nfc.read();
    
    if(tag.hasNdefMessage())
    {
      
      NdefMessage message = tag.getNdefMessage();
      
      for(int i=0;i<message.getRecordCount();i++)
      {
        
        NdefRecord record = message.getRecord(i);
        int payloadLength = record.getPayloadLength();
        byte payload[payloadLength];
        record.getPayload(payload);
        Serial.write(payload,payloadLength);
       }
    
    }

  }
  
  delay(500); 
 
} 

このスケッチを動かして、先程メッセージを書き込んだNFCタグをリーダーに近づけてみると、書き込んだメッセージ「Hello, world!How are you today?」がシリアルモニターに表示されました。

thumb_3

タグに書き込んだデータを消してみる

erase()を使って、先程書き込んだメッセージを消してみます。

#include <SPI.h>
#include "PN532_SPI.h"
#include "PN532.h"
#include "NfcAdapter.h"

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

void setup(void) {
  
  Serial.begin(115200);
  Serial.println("NFC Tag Eraser");
  nfc.begin();

}

void loop(void) {

  Serial.println("\nPlace a tag on the NFC reader to erase.");

  if (nfc.tagPresent()) {

    bool success = nfc.erase();
    if (success) {
      Serial.println("\nSuccess, tag contains an empty record.");        
    } else {
      Serial.println("\nUnable to erase tag.");
    }

  }
  
  delay(5000);
  
}

このスケッチを動かして、先程メッセージを書き込んだNFCタグをリーダーに近づけてみると、データの内容が消されたようです。

thumb_4

試しにread()をしてみると、データが空になっているのがわかると思います。

NFCタグのUIDをvvvvで使ってみる

ここまで、サンプルコードを試しながら、NFC Shield V2.0を使ってNFCタグでどんなことができるのかを軽く触れてみました。ここからはvvvvとつなぎこんでみます。

vvvvに認識したNFCタグのUIDを送る方法

vvvvとArduinoのデータ連携では、USBケーブルを使ったシリアル通信を使ってみます。実は今回、NFC Shield V2.0を選んだ理由の一番のポイントがここです。Arduinoで使用できるNFCリーダーは他にもたくさんあるのですが、元々のライブラリなどがハードウェアシリアルを使うものになっていて、それらをソフトウェアシリアルに変更してしまうとうまく動かなくなる、という事例がいくつか見受けられたので、今回はArduinoとNFCリーダーの通信にSPIやI2Cを使ったものを探していました。NFC Shield V2.0ではSPIとI2Cのいずれでも通信を行えるライブラリが提供されており、かつシールド形状なので安易にArduinoと結合ができ、認識の最大有効範囲が5cmあるということで、これを利用しました。

Arduinoから読み取ったUIDを送る

まずはNFCタグを認識してUIDをvvvvに送る部分をArduinoで作ります。read()を使って読み取ったNFCタグのUIDを、シリアル通信で送るシンプルなスケッチを作ります。

#include <SPI.h>
#include "PN532_SPI.h"
#include "PN532.h"
#include "NfcAdapter.h"

PN532_SPI interface(SPI, 10);
NfcAdapter nfc = NfcAdapter(interface);

void setup(void) {

  Serial.begin(115200);
  nfc.begin();

}

void loop(void) {

  if (nfc.tagPresent()) 
  {
    NfcTag tag = nfc.read(); 
    String scannedUID = tag.getUidString(); 
    Serial.println(scannedUID);

  }
  
  delay(2000);
    
} 

vvvvの実装

次に、UIDを取得してNFCタグ毎に設定した色で描画するvvvv側の実装です。vvvvではシリアル通信でデータを取得するようにしたので、RS232ノードを使います。また、予め反応させたいUIDを取得してリスト化し、それと対になるカラーリストも作っておきました。この辺りは変更しやすいように外部ファイルにしたり、ネットワーク経由から取得できるようにしておいたり、あるいはNFCタグにデータを書き込んでその中のデータに応じた処理にしておくと、もう少し拡張性が出ると思います。OnOpenはパッチ起動時に1回だけBangを送ってくれるノードで、これを使って起動時にRS232をEnableにしています。
あとは、RS232から取得できたUIDが、今回の対象UIDかどうかをマッチさせ、リストの中のいずれかのUIDに該当したときにはUID毎に設定したカラーリストの色に応じて描画するようにしています。実装したパッチはこのような感じです。

thumb_5

連携の様子

実際に動かしたときの様子がこちらです。

今回はNFCタグのUIDに応じて異なる色で描画するだけのシンプルな機能までしか実装していませんが、おおまかにはNFCタグの読み込み→アプリケーション側でNFCタグに紐付いた情報に応じたアクションを行うという流れができたので、あとは機能や演出の方向や深さを掘っていくことで、色々な使い方ができそうです。