RFIDリーダライタ(YHY630)を使ってみる(2)

本 チュートリアルの内容

はじめに
LEDを点灯させるチュートリアルで、RFIDリーダライターの基本的な仕組みはわかったと思います。次に、実際にタグを読み取ってみましょう。先ほどのチュートリアルとの違いは、次のようになります。
  • タグの読み取りコマンドの送信
  • 受信データからタグデータの解析
今回は、タグデータのうちUIDだけを読み取ってみます。

ページの先頭へ

UIDを読み取ってみよう
では実際にリーダーライターを操作してみましょう。ちなみに、UIDとは今回使用しているISO15693という標準のタグに書き込まれている、タグを一意に識別する識別子です。

・プログラムの開始
まず、VisualStudio2008でプロジェクトを開始します。ここでは、C#のフォームアプリケーションを選択肢、YHY630_02というプロジェクトを作成しました。

次 に、フォームの画面に、ツールボックスから、テキストボックスを2つ配置し、さらに、ボタンを一つ配置します。ここでは、ボタンに実行という名前をつけま した。テキストボックスは、上のテキストボックスには送信コマンド、下のテキストボックスには受信コマンドを表示させます。



次に、同じ画面のままで、ツールボックスから、シリアルポートをドラッグし、フォーム画面上にドロップします。これによって、このアプリケーションでシリアル通信が実現できるようになります。
そ して、シリアルポートの通信パラメーターを同じく、シリアルポートのプロパティーで設定します。今回使用するリーダーライターは、通信速度:115200 ボー(デフォルト)、パリティ:なし、データビット:8ビット、ストップビット:1ビット、フリー制御:なし、となっているので、そのように設定します。 また、使用しているパソコンのコントロールパネルから、デバイスマネージャを選択し、接続したリーダーライターのCOMポートを調べて、PortName の値も同じ値に変更します。
おそらく、変更する必要があるのは、BaudRateとPortNameの二つになると思います。


ここまでで、初期の設定は終了です。
次にプログラムを開始します。

・プログラム作成
それでは、実際のコーディングに入ります。まず、コードを表示します。コードは、「表示」メニューから「コード」を選択して表示します。Formの初期化が行われているコードの箇所に、シリアルポートの使用開始のためのポートオープンを追加します。

        public Form1()
        {
            InitializeComponent();
            serialPort1.Open();
        }

次 に、ボタンを押下した際の動作を記述します。そのためには、デザイン画面に戻って、ボタンをダブルクリックします。すると、コードにボタン押下時の動作を 記述するスタブが追加されます。マニュアルによると、タグIDを読み取る(インベントリーと呼びます)コマンドは、16進数で次の ようになっていることがわかります。

インベントリ:AA BB 05 00 00 00 00 10 10

今回は、このコマンドをそのままシリアルポートから送信するようにします。また、送信したコマンドを送信コマンドボックスに表示するようにしてみましょう。これは、LEDのチュートリアルと同様にバイトを文字列型に変換して、TextBoxに表示すればよいです。

        private void button1_Click(object sender, EventArgs e)
        {
            // インベントリコマンド作成
            byte[] sndCmd = new byte[] { 0xaa, 0xbb, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10 };
            // コマンド送信
            serialPort1.Write(sndCmd, 0, sndCmd.Length);
            // 送信コマンドの表示
            String sndStr = ""; // 送信コマンドの文字列
            foreach (Byte item in sndCmd)
            {
                sndStr += string.Format("{0:X2}", item) + " ";
            }
            textBox1.Text = sndStr; // textBox1に表示する
        }

さて、ここまでで、コマンドを送るところまでのコードが完成しました。

・応答メッセージの表示
で は、次に、応答メッセージがきちんと帰ってきているかどうかを確認してみましょう。シリアル通信の受信を行うためには、シリアルポートのイベント処理を使 用する必要があります。イベント処理は、デザインページに戻って、シリアルポートのアイコンを選択し、プロパティ画面のイベントボタン(雷マーク)を選択 することで追加できます。イベント画面にDatareceivedというイベントが表示されていると思いますので、それをダブルクリックしてください。す ると、画面はコード画面に戻り、イベント処理のスタブが追加されます。


ここでは、データの受信及び、受信したデータの表示を行います。受信については、受信するデータを格納するバイト配列を定義し、その配列に受信バッファのデータを取り込みます。

            // シリアルデータの受信
            byte[] recByte = new Byte[serialPort1.BytesToRead];// シリアルから受け取るデータ
            serialPort1.Read(recByte, 0, recByte.GetLength(0)); // シリアルからデータを受け取る

次に、配列に格納した受信データを表示できるように文字列方に変換し、その結果をメッセージボックスで表示するようにします。

            // 受信メッセージの表示
            String rcvdStr = ""; // 受信データの文字列
            foreach (Byte item in recByte)
            {
                rcvdStr += string.Format("{0:X2}", item) + " ";
            }
            MessageBox.Show(rcvdStr);

これらのコードをprivate void serialPort1_DataReceivedの中に書き込みます。インベントリコマンドが成功したときの応答メッセージは以下のようになっているはずです。

受信メッセージ(タグなし):AA BB 06 00 00 00 07 01 00 06
受信メッセージ(タグあり):AA BB 0F 00 00 00 00 10 00 00 9D AD A3 4E 00 01 04 E0 28
(ただし、UIDの値は)

では、実際動作させて見ましょう。以下のように表示され、実際に、リーダーらーたーのLEDが制御できれば完成です。







・TextBoxへの表示
では、MessageBoxへ読み取り結果を表示するのではなく、TextBoxに表示してみましょう。表示するためには、以下の書き換えをすればよいはずです。

(変更前)MessageBox.show(rcvdStr);
(変更後)textBox2.Text=rcvdStr;

しかし、実際に動かしてみるとエラーが出て動きません。

こ れは、フォームを別のスレッド(シリアルの受信処理)から操作しようとするから発生します。そこで、これを回避するために、Invokeメソッドとデリ ゲートを使用します。Invokeを利用することで、デリゲートで定義したメソッドを呼び出すことができるようになります。

定義するメソッド:
        private void RcvdData(String str)
        {
            textBox2.Text = ""; // テキストボックスの初期化
            textBox2.Text = str;
        }

デリゲートの定義:
   private delegate void RcvdDataDelegate(String str);

これらは、private void serialPort1_DataReceivedの外側に定義します。そして、これまで、MessageBoxがあったところに、デリゲートのインスタンスとInvokeを記述します。

            // デリゲート
            RcvdDataDelegate rcvdData = new RcvdDataDelegate(RcvdData);
            Invoke(rcvdData,rcvdStr);

これらは、private void serialPort1_DataReceivedの中に書き込みます。
では、改めて、この状態でUIDを読み取ってみましょう。


読み取り結果が表示されたでしょうか。

・UIDの取り出し
読 み取り結果は表示されましたが、実は、この結果は、UIDではありません。UID以外に、このリーダーライターの通信上のパラメータが入っています。例え ば上記の図の場合、AA BBの箇所はヘッダになります。次の0Fは受信データのサイズ(の一部分)、その次の00はリザーブエリア、といった具合です。マニュアルによると以下の ようになっているようです。



応答メッセージのヘッダ部分を切り取って、残りの部分の長さから、応答したタグの枚数を計算して、あとは、その枚数分文字列を切り取っていくという方法をとります。(バイト列を使用すればもっときれいな方法があるとは思いますが…)

        private void RcvdData(String str)
        {
            textBox2.Text = ""; // テキストボックスの初期化
            String dispStr = ""; // 表示用の文字列
            // タグ数の取得
            int numTag = (str.Length - 10 * 3) / (8 * 3); // 応答したタグ枚数

            String[] uidStr = new String[numTag];// UIDの文字列配列

            // UIDを受信した文字列から切り取る
            for (int i = 0; i < numTag; i++)
            {
                uidStr[i] = str.Substring(30+i * 24 + i * 3, 24);
            }
            // 切り取った文字列を表示用に並べ替える
            for (int i = 0; i < numTag; i++)
            {
                dispStr = dispStr + "UID"+i.ToString() +":" +uidStr[i] + "\r\n";
            }
            // テキストエリアに表示
            textBox2.Text = dispStr;
        }

以下が、1枚、2枚、3枚タグがあるときのそれぞれの実行結果になります。




ページの先頭へ


応用問題に挑戦してみよう

応用問題として次のものに挑戦してみよう。

メッセージのパリティチェックを実装してみよう。(メッセージの最後の1バイトはチェックサムになっています。)