最終更新日
記事公開日

NFCチップ(Ntag213)のデータ読み書き【RFID-RC522無線通信ボード&Arduino Pro Mini】

RFID-RC522無線通信ボードとArduino Pro Miniを使って、NFCチップ(Ntag213)のデータ書き込み・読み込みを行う方法について紹介します。

データの書き込み/読み込み方法

RFID-RC522ボードにNFCチップを近づけると、NFCチップに以下のデータが書き込みまれます↓

1ABCDEFG2ABCDEFG3ABCDEFG4ABCDEFG5ABCDEFG6ABCDEFG7ABCDEFG8ABCDEFG9ABCDEFG1ABCDEFG2ABCDEFG3ABCDEFG4ABCDEFG5ABCDEFG6ABCDEFG7ABCDEFG8ABCDEFG9ABCDEFG

その後すぐに、さきほどNFCチップに書き込んだデータを読み込み、シリアルモニタへと表示しています。

使用部品

  1. NFCシール(Ntag213)- AliExpress  
  2. RFID-RC522ボード - AliExpress
  3. Arduino Pro Mini(3.3V・8M) Arduino用 - Amazon

Arduino Pro Miniにプログラムを書き込む際に必要な部品

  1. FTDI USBシリアル変換アダプタ - スイッチサイエンス
  2. USBケーブル(Type-A/Micro-B)

Arduino Pro Miniについて

Arduino Pro Miniを初めて使用する方は、ぜひ下記の記事も参考にしてみて下さい↓

『Arduino Pro Mini』レビュー&使い方

配線写真・回路図

プログラム(Arduino言語)

/*
 * 
 * Arduino Pro Mini
 * 
 * RST            9
 * SPI SS(SDA)   10
 * SPI MOSI      11
 * SPI MISO      12
 * SPI SCK       13
 * 
 * Arduinoのボード種類によって配線するピンが違います。
 * 詳しくは下記を参照して下さい↓
 * https://github.com/miguelbalboa/rfid#pin-layout
 * 
*/

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN          10
#define RST_PIN         9

// MFRC522インスタンスを作成
MFRC522 mfrc522(SS_PIN, RST_PIN);

// チップのステータスを取得するための変数
MFRC522::StatusCode status; 

// データ書き込み用バッファ(最大144バイト)の配列
byte write_buffer[144];

// データ読み込み用バッファ(最大144バイト + CRC用2バイト)の配列
byte read_buffer[146];

// ポインタに使用するために配列サイズを取得
byte read_buffer_size = sizeof(read_buffer);

// ----------------------------------------------
//
//                   SETUP
//
// ----------------------------------------------
void setup() {

  // PCとのシリアル通信を初期化
  Serial.begin(9600);

  // SPIバスを初期化
  SPI.begin();

  // MFRC522カードを初期化
  mfrc522.PCD_Init(); 
  
  // チップに書き込むデータ
  memcpy(write_buffer, "1ABCDEFG2ABCDEFG3ABCDEFG4ABCDEFG5ABCDEFG6ABCDEFG7ABCDEFG8ABCDEFG9ABCDEFG1ABCDEFG2ABCDEFG3ABCDEFG4ABCDEFG5ABCDEFG6ABCDEFG7ABCDEFG8ABCDEFG9ABCDEFG", 144);

  Serial.println();
  Serial.println(F("チップかざして下さい。"));
  Serial.println();
}

// ----------------------------------------------
//
//                   LOOP
//
// ----------------------------------------------
void loop() {
  
  // 新しいカードを探す
  if (!mfrc522.PICC_IsNewCardPresent())
    return;

  // 一つのカードを選択
  if (!mfrc522.PICC_ReadCardSerial())
    return;

  // --------------------------------------------
  //           チップ情報を表示
  // --------------------------------------------
  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid));
  Serial.println();

  // --------------------------------------------
  //               データの書き込み
  // --------------------------------------------
  for (int i = 4; i < 40; i++) {  // block[4] ~ block[39]までがデータを書き込むことができるメモリ領域
    
    // i:書き込む位置
    // &write_buffer[(i-4)*4]:書き込むデータをポインタで指定
    // 4:書き込むデータサイズ(4バイト)
    status = (MFRC522::StatusCode)mfrc522.MIFARE_Ultralight_Write(i, &write_buffer[(i-4)*4], 4);

    // エラー
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("書き込み失敗:"));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }
  }
  Serial.println(F("書き込み成功!"));
  Serial.println();

  // --------------------------------------------
  //               データの読み取り
  // --------------------------------------------
  Serial.println(F("データ読み取り中 ... "));
  Serial.println();

  // block[4] ~ block[39]までのデータを読み込む
  for (int n = 4; n < 40; n++) {  

    // n:読み込む位置
    // read_buffer:読み取ったデータを格納する配列
    // &read_buffer_size:読み取ったデータのサイズを格納するポインタ
    status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(n, read_buffer, &read_buffer_size);

    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("読み込み失敗:"));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }

    Serial.print(F("Block"));
    Serial.print(n);
    Serial.print(F(": "));
    
    // 1バイトずつ表示
    for (byte m = 0; m < 4; m++) {
      Serial.write(read_buffer[m]);
    }

    Serial.println();
  }
  Serial.println();

  // 通信終了
  mfrc522.PICC_HaltA();
}

※MFRC522ライブラリを使用しています。

プログラムを書き込む前に以下の手順に従って、Arduino IDEへMFRC522ライブラリをダウンロードしておいてください↓

MFRC522ライブラリのダウンロード手順

1.Arduino IDEを開き、上部メニューから[スケッチ]-[ライブラリをインクルード]-[ライブラリを管理]を選択します。

2.検索フォームに「MFRC522」と入力して表示された[MFRC522 by GithubCommunity]をインストールしてください。

注意点

MFRC522ライブラリのサンプルスケッチは、MRCRFID-RC522ボードに付属しているカードの規格(MIFARE Classic 1KB)に読み書きするためのコードです。

Ntag213とはメモリ構造が違います。

サンプルスケッチではNtag213にデータを読み書きできないので、ご注意ください。

今回のプログラムは、「Ntag213」の類似品である「MIFARE Ultralight C」へ書き込む関数(MIFARE_Ultralight_Write)を使用しています。

技術解説

NFCチップ(Ntag213)のメモリ構造は以下の通りとなっています↓

NTAG213データシート(PDF)

[0]~[3]Page・[40]~[44]Pageはチップ情報が格納されているので、データを書き込むことはできません。

無理に書き込むと、データが壊れてチップへの読み書きができなくなってしまいます。

ユーザー側でデータを書き込みできる領域は「144バイト」

文字半角英数文字であれば、144文字分を保存することができます。

実際に上記のプログラムをNtag213に書き込み、実行して、シリアルモニタに表示された結果が以下となります↓

基本編[その2]UID(シリアルナンバー)認証

プログラムの中に書いてある認証UIDと一致するNFCチップをかざすと、LEDランプが点灯します。

認証されないNFCチップをかざしても、LEDは点灯しません。

使用部品

  1. NFCシール(Ntag213)- AliExpress  
  2. RFID-RC522ボード - AliExpress
  3. Arduino Pro Mini(3.3V・8M) Arduino用 - Amazon
  4. LED(抵抗内蔵タイプ)- 秋月電子

配線写真・回路図

プログラム(Arduino言語)

/*
 * 
 * Arduino Pro Mini
 * 
 * RST            9
 * SPI SS(SDA)   10
 * SPI MOSI      11
 * SPI MISO      12
 * SPI SCK       13
 * 
 * Arduinoのボード種類によって配線するピンが違います。
 * 詳しくは下記を参照して下さい↓
 * https://github.com/miguelbalboa/rfid#pin-layout
 * 
*/

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN          10
#define RST_PIN         9

// MFRC522インスタンスを作成
MFRC522 mfrc522(SS_PIN, RST_PIN);

// チップのステータスを取得するための変数
MFRC522::StatusCode status; 

// LEDに使用するPin
#define LED_PIN       2 

// ----------------------------------------------
//                 認証UID
// ----------------------------------------------
byte targetUID[] = {0x53, 0x0D, 0x98, 0x52, 0x61, 0x00, 0x01};

// ----------------------------------------------
//
//                   SETUP
//
// ----------------------------------------------
void setup() {

  // LEDピン設定
  pinMode(LED_PIN, OUTPUT);

  // PCとのシリアル通信を初期化
  Serial.begin(9600);

  // SPIバスを初期化
  SPI.begin();

  // MFRC522カードを初期化
  mfrc522.PCD_Init(); 
  
  Serial.println();
  Serial.println(F("チップかざして下さい。"));
  Serial.println();
}

// ----------------------------------------------
//
//                   LOOP
//
// ----------------------------------------------
void loop() {
  
  // 新しいカードを探す
  if (!mfrc522.PICC_IsNewCardPresent())
    return;

  // 一つのカードを選択
  if (!mfrc522.PICC_ReadCardSerial())
    return;

  // --------------------------------------------
  //           チップ情報を表示
  // --------------------------------------------
  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid));
  Serial.println();

  // --------------------------------------------
  //             UIDの一致を検証
  // --------------------------------------------
  if (memcmp(mfrc522.uid.uidByte, targetUID, mfrc522.uid.size) == 0) {
    
    Serial.println(F("UIDが一致しました。LEDを点灯します。"));
    digitalWrite(LED_PIN, HIGH);
    delay(1000);
    digitalWrite(LED_PIN, LOW);
  } 
  else {
    Serial.println(F("UIDが一致しません。"));
  }
  Serial.println();

  // 通信終了
  mfrc522.PICC_HaltA();
}

※認証UID(targetUID)は、ご使用のチップNFCに合わせて必ず変更してください。

実際に上記のプログラムをNtag213に書き込み、実行して、シリアルモニタに表示された結果が以下となります↓

応用編(UID認証後、データ値でサーボモーター制御)

NFCチップを張り付けた物体をRFID-RC522ボードに近づけ、UID認証が通ると、NFCチップに書き込んであるデータ量に応じてサーボ-モータが動きます。

使用部品

  1. NFCシール(Ntag213)- AliExpress  
  2. RFID-RC522ボード - AliExpress
  3. Arduino Pro Mini(3.3V・8M) Arduino用 - Amazon
  4. LED(抵抗内蔵タイプ)- 秋月電子
  5. 三端子レギュレーター(LM317)- 秋月電子
  6. カーボン抵抗(1W100Ω)※合成50Ω用 - 秋月電子
  7. カーボン抵抗(1/2W120Ω)
  8. カーボン抵抗(1/2W200Ω)
  9. 積層セラミックコンデンサ(0.1μF)
  10. 積層セラミックコンデンサ(1μF)
  11. サーボモーター(SG92R)- 秋月電子
  12. モバイルバッテリー(エレコム DE-M09-5000WH)- Amazon

配線写真・回路図

モバイルバッテリー(5V)と50Ω抵抗について

サーボモーター(SG92R)を動かすには4.8Vが必要なので、モバイルバッテリー(5V)を使用しています。

近くに置いてある50Ωは、モバイルバッテリーから常時電流を供給し続けるためのものです。

これがないと、数秒でモバイルバッテリーは止まってしまいます。

詳しくは下記の記事をご覧ください↓

モバイルバッテリーのオートパワーオフ回避方法

Arduino Pro Miniへの3.3V電源供給について

Arduino Pro Miniの電源にモバイルバッテリーを使用する場合は、5V→3.3Vへ電圧を落とす必要があります。

そこで、三端子レギュレーター(LM317)を使用しています。

LM317は抵抗値によって出力電圧を調整できるので、付近に置いてある120Ω・200Ω抵抗で5V→3.3Vへ落とす調整を行っています。

0.1μF・1μFは動作を安定させるためのものです。

プログラム(Arduino言語)

/*
 * 
 * Arduino Pro Mini
 * 
 * RST            9
 * SPI SS(SDA)   10
 * SPI MOSI      11
 * SPI MISO      12
 * SPI SCK       13
 * 
 * Arduinoのボード種類によって配線するピンが違います。
 * 詳しくは下記を参照して下さい↓
 * https://github.com/miguelbalboa/rfid#pin-layout
 * 
*/

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

// サーボモーター制御Pin
#define SERVO_PIN 9

// servoクラスのインスタンス作成
Servo servo1; 

// MFRC522インスタンスを作成
#define SS_PIN  7
#define RST_PIN 8
MFRC522 mfrc522(SS_PIN, RST_PIN);

// チップのステータスを取得するための変数
MFRC522::StatusCode status; 

// データ書き込み用バッファ(最大144バイト)の配列
byte write_buffer[144];

// データ読み込み用バッファ(最大144バイト + CRC用2バイト)の配列
byte read_buffer[146];

// ポインタに使用するために配列サイズを取得
byte read_buffer_size = sizeof(read_buffer);

// LEDに使用するPin
#define LED_PIN 2 

// ----------------------------------------------
//                 認証UID
// ----------------------------------------------
byte targetUID[] = {0x53, 0x0D, 0x98, 0x52, 0x61, 0x00, 0x01};

// ----------------------------------------------
//
//                   SETUP
//
// ----------------------------------------------
void setup() {

  // サーボモーターPin設定
  servo1.attach(SERVO_PIN);

  // サーボモーターの初期位置
  servo1.write(0);
 
  // LEDピン設定
  pinMode(LED_PIN, OUTPUT);

  // PCとのシリアル通信を初期化
  Serial.begin(9600);

  // SPIバスを初期化
  SPI.begin();

  // MFRC522カードを初期化
  mfrc522.PCD_Init(); 
  
  // チップに書き込むデータ([4]と[5]という2のデータを書き込む)
  memcpy(write_buffer, "45", 144);

  Serial.println();
  Serial.println(F("チップかざして下さい。"));
  Serial.println();
}

// ----------------------------------------------
//
//                   LOOP
//
// ----------------------------------------------
void loop() {
  
  // 新しいカードを探す
  if (!mfrc522.PICC_IsNewCardPresent())
    return;

  // 一つのカードを選択
  if (!mfrc522.PICC_ReadCardSerial())
    return;

  // --------------------------------------------
  //           チップ情報を表示
  // --------------------------------------------
  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid));
  Serial.println();

  // --------------------------------------------
  //               データの書き込み
  // --------------------------------------------
  
  // block4の位置にwrite_buffer[0]から4バイトのデータを書き込む
  status = (MFRC522::StatusCode)mfrc522.MIFARE_Ultralight_Write(4, &write_buffer[0], 4);

  // エラー
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("書き込み失敗:"));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  
  // --------------------------------------------
  //             UIDの一致を検証
  // --------------------------------------------
  if (memcmp(mfrc522.uid.uidByte, targetUID, mfrc522.uid.size) == 0) {
    
    Serial.println(F("UIDが一致しました。LEDを点灯します。"));


    // block4を読み込み、read_bufferへデータを格納し、メソッドに渡すためのデータサイズを取得する
    status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(4, read_buffer, &read_buffer_size);
    
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("読み込み失敗:"));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }

    // データを2文字の整数に変換
    int read_value = 0;
    for (int i = 0; i < 2; i++) {
      if (isdigit(read_buffer[i])) {
        read_value = read_value * 10 + (read_buffer[i] - '0');
      }
    }
    Serial.println(read_value);

    // LED点灯
    digitalWrite(LED_PIN, HIGH);

    // サーバモーターを45度の位置に動かす
    servo1.write(read_value);

    // 1秒待機
    delay(1000);

    // LED消灯
    digitalWrite(LED_PIN, LOW);

    // サーバモーターを0度の位置に戻す
    servo1.write(0);

    // 1秒待機
    delay(1000);
    
  } 
  else {
    Serial.println(F("UIDが一致しません。"));
  }
  Serial.println();

  // 通信終了
  mfrc522.PICC_HaltA();
}

※認証UID(targetUID)は、ご使用のチップNFCに合わせて必ず変更してください。

このプログラムでは、NFCチップをかざしたときに「4」と「5」というデータをNFCチップに書き込んでいます。

その後、UIDを認証。

指定したものと一致したら、さきほどデータを書き込んだNFCチップの中から「4」と「5」というデータを取り出します。

「4」と「5」というデータを「45」という数値に変換して、サーボモーターへ「45度」の位置まで動く指示に使用しています。

関連情報

運営者プロフィール
コダマ

職業はIT系フリーランス。過去、電子配線業務の経験が10年ある為、はんだづけも得意です。宮崎県在住、30代・2児の父親。

プロが教える!イチからわかるハンダ付けのコツ(工学社)の著者です。

カテゴリー