2013/02/09

複数枚のNFCタグ重ね

Fukuoka NFC Hack 7で、「複数枚のNFCタグを重ねたらどうなる?」という質問があった。
うっ、痛いところを・・・。

NFCの規格の痛いところ、ではなく、私の知識がないという点で痛いところなのだ。


これについては、CQ出版のInterface誌2012年4月号が詳しい。

 

まず、無線、という視点で。
無線は、ほとんど同時に届く。
少なくとも、NFC程度の距離であれば同時と考えていいだろう。

無線を出す方、リーダライタを「イニシエーター(initiator)」と呼んでいる(NFCだけ?)。
無線を受ける方、カードを「ターゲット(target)」と呼ぶ。
NFCの通信は、イニシエーター主導で行われ、イニシエーターの無線送信に対してターゲットが返信をする動作が基本になっている(NBM、Normal Balance Modeと呼んでいる)。

よって、リーダライタが出した無線コマンドを、カードは同時に受信する。
何も考えなければ、そのままカードは返信をする。
同時に受信するので、全カードは同時に返信する。

無線の特徴として、波形は足し算ではなく掛け算になる、ということがある。
データが同じ1になれば波形が大きくなるが、片方でも0があると0になってしまう、ということだろう(済まん、細かいところは知らないのだ)。
大ざっぱに言えば、同じタイミングで複数のカードが返信すると、無線が重なってデータが化け化けになってしまうのだ。
つまり、誰かが勝つのではなく、全員が負ける(読まれない)。

無線のプロトコルを考えるときは、無線が重なった場合の動作も含めて方式を考えておかなくてはならない。
重なったままでもいいようにするか、なるべく重ならないようにするか。
NFCも例外ではなく、無線が衝突したときのことを考えている。
(アンチコリージョン、と呼ばれる。)


特定のカードがわかっている場合、例えばFeliCaであればIDmが既にわかっている場合、IDmを指定して無線を送信して、IDmが一致したカードだけが返信する、というしくみにしておけば返信が重なることはない(IDmは、もともと複数のカードをかざしたときの対策だと思っておいた方がいいだろう)。

しかし、「カードの有無を探す」というような場合には、相手を特定できない。
どういうカードがいるかわからないから「みんな応えて!」というコマンドを出すからだ。

では、どう回避するか?
これはNFC-A, B, Fで異なる。
以下、Interface誌を読みながら書いていく(詳細は、買って確認しましょう)。

 

NFC-A

リーダライタからの要求に対して、カードはUIDを返す。
それを受信したリーダライタは、どうやら同じビットデータを返したときにはわかるらしい。
そのときは衝突したことがわかるだけでなく、衝突したビットがわかるらしい。
そういうときには、リトライをする。するときには「衝突ビット」という情報があり、衝突ビットが「0」となっているカードだけが返信する、というしくみになっているそうだ。

これを繰り返し、全部が衝突しないようになったらおしまい。
このやり方を「ビット・コリジョン方式」と呼ぶそうだ。

NFC-B

読んだが、よくわからん・・・。
「スロット・マーカ方式」という方法だそうだ。

まず、リーダライタが要求したとき、各カードは乱数を発生させ、それをスロットマーカ番号として保持する。
リーダライタもスロットマーカ番号を生成し、それをカードに通知している。
その番号がリーダライタの番号と一致したカードだけが返信する、というしくみになっている。
そうやって返信したものが衝突した場合は、やりなおす。

つまり、じゃんけんして、あいこだった人が一人OKだけど、あいこの人が複数いた場合にはやり直す、ということかな。

NFC-F

NFC-Fはよく使うので、だいたいわかっているつもりだ。

まず、リーダライタから「ポーリング」というコマンドを出す。
このときに、反応してほしいカードの指示をする(システムコード)のだが、それと同時に「この時間の範囲内で適当に返信しろ」という値も指定する。
ポーリングコマンドの説明で「00 FF FF 00 00」というものが多いと思うが、最後の「00」がそれだ。
ここが「00」の場合は、返信時間が0なので、ランダムではなく即時返す。
だから、複数枚のカードがあると返信が衝突する。

この値を増やすと(指定できる値はパターンが決められている)、返信できる時間に余裕ができるので、衝突する確率は減る。
減るが、応答性はその分悪くなる(返信がランダムなので)。

応答性を取るならば値を小さくしたいが、複数枚を区別したいなら大きくすることになるだろう。

しかし、やり方を見てもわかるように、どれも「同時に読み取る」ための方式ではない。
無線は、同じ周波数で複数のデータを返すことはできないのだ。
いわゆる「ブロードバンド」というのは、この周波数帯を複数持つことで、複数のデータを同時に伝えることができるようにしているだけだろう(データバスが、シリアルかパラレルか、みたいなものか)。

同じように、同一周波数の無線を送信しながら受信する、というような芸当はできない。
やったら、自分が送信したデータを自分で受信するだけだ(のはず。いっぺんやらかしたので)。

このように、無線の通信というのは偶発的な要素が非常に多い。
多いので、システム的に回避する手段をかなり考え込んでおかないと、テスト段階では大丈夫でも運用中に失敗する。
有線の方は詳しくないが、無線については既存の安定した方式が既にあるのならば、実装が面倒であってもそれに従うのが最終的には楽だと思っている。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。