2019年8月21日水曜日

光るタグを作成してみる

今から11年ほども前なんですが、光るタグで遊んでいました。
http://www.hayato.info/home/report_hikarutag.htm

これは試作機をお借りして遊んでいたのですが、残念ながら商品化には至らず今も販売はしておりません。

しかしながらこのページからの問い合わせが今でもぽちぽちあって、やっぱり需要あるよなー光りたいよなーということで作成してみることにしました。

UHFを使った光るタグとしては、farsens社の製品があります。
http://www.shenghero.co.jp/product/farsens/stella.html

こういうのができるとカッコいいんですがまぁ無理ですね(笑。あとこういう製品でも高出力のリーダで数mの距離まで近づかないと光らないのでもう少し距離が欲しいところでもあります。

距離ということで言うと捜し物を見つけるBLEタグが世の中にいろいろ出ていますね。ただなんとなく操作が面倒(アプリで登録してゴニョゴニョ)な気がします。

要望をまとめますと、

・昔やってた光るタグと同じようなものを作りたい(登録が簡単にできて、かざすと光るみたいな誰でも使える単純なやつ)
・できれば離れた距離でも光らせたい

ということでとりあえず光るBLEタグを作って、紐付けしたタグをかざすと光るみたいな感じで行きたいと思います。

まずは光るタグ。最近はBLE搭載のマイコンとか出ててすごいです。たまたま手元にあったESP32マイコンを使って作ります。このマイコン、WifiとBluetoothがついて技適まで取れてるのに市販価格600円くらいとかありえないような製品です。今回はBluetoothしか使わないしESP32は消費電力も比較的大きいので製品として組み込むには別のマイコンがよいとは思いますがまぁ、手元にこれしか無いし、実験だし、でこれ使います。

通信仕様ですが、BLEで接続してゴニョゴニョが面倒だったので、BLEタグ側は受信状態にしておいてコントローラからアドバタイズが来たらそれに反応するようにします。受信状態というのがまた電力食うんですが休み休み受信しておいて、コントローラはMAXでアドバタイズばんばん出すということにします。アドバタイズパケット内に光らせたいBLEタグのMACアドレスを入れておいて、BLE側で受信したときに自分のMACアドレスだったら光るということでどうでしょうか。

上記内容でESPちゃんを動かします。開発はなんとArduino IDEでできちゃいます。なんて素晴らしい世の中になったんでしょうか。コードはこちら
#include "BLEDevice.h"

BLEScan* pBLEScan;
int led_count = 0;
byte my_ble_address[ESP_BD_ADDR_LEN];

void setup() {
  pinMode(4, OUTPUT);  // pin4 を出力に設定
  Serial.begin(115200);

  BLEDevice::init(""); 
  pBLEScan = BLEDevice::getScan(); 
  pBLEScan->setActiveScan(true);
  memcpy(my_ble_address, BLEDevice::getAddress().getNative(), 
          ESP_BD_ADDR_LEN); // 自分のBLEアドレスを取得
  Serial.printf("My BTADDR %s\n", 
          BLEDevice::getAddress().toString().c_str());
}

void loop() {
  BLEScanResults foundDevices = pBLEScan->start(1);  // 1秒間スキャンする
  int count = foundDevices.getCount();
  for (int i = 0; i < count; i++) { 
    BLEAdvertisedDevice d = foundDevices.getDevice(i);
    if (d.haveManufacturerData()) { 
      std::string data = d.getManufacturerData();
      if (data[0] == 0xff && data[1] == 0xff) {  // デモなので0xFFFFを使う
        if (memcmp(my_ble_address, &data[2], ESP_BD_ADDR_LEN) == 0) // 自分が呼ばれたら
          led_count = 1;
      }
    }
  }
  if (led_count-- > 0) {
    digitalWrite(4, HIGH);
  } else {
    digitalWrite(4, LOW);
    delay(2000);  // 呼び出しがないときは2秒スリープ
  }
}
ばーん。こんだけです。うはー、こんだけでいいの?って感じですね。いろいろ例外処理を省いてるので短いというのもありますがそれにしてもスゴイ!

ESPちゃんにLEDを実装したのがこれ


あーもう、お手軽すぎて笑っちゃいますね。何でタグが貼ってあるかは後ででてきます。

次はコントローラ側です。ラズパイあたりでやろうかと思ったんですがスマホでよくね?ということでスマホのアプリを作ります。まずコントローラのやることは、BLEタグとかざすカードとの紐付けになります。特定のカードをかざしたら対応したBLEタグのMACアドレスをアドバタイズするという動きになりますので正確にはBLEタグのMACアドレスとかざすカードのUIDを紐付けます。

カードのUIDはまぁスマホでかざせば取れますが、BLEタグのMACアドレスはどうしようということで少し手間ですが事前にMACアドレスをタグに書き込んでおいてBLEタグに貼り、それをスマホで読み取ることでMACアドレスを取得します。こうすることでBLEタグもなんとなくRFIDタグっぽくなって、えー、これただのBLEタグじゃん、ってならないで済むしこれはもう光るRFIDタグと言っても過言では無いのではないかという妄想で喜ぶという路線でお願いします。

Android側のコーディングもとても簡単です。
    BluetoothManager manager = 
          (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    BluetoothAdapter adapter = manager.getAdapter();
    mBluetoothLeAdvertiser = adapter.getBluetoothLeAdvertiser();

    AdvertiseSettings.Builder asBuilder = new AdvertiseSettings.Builder();
    asBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY);
    asBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
    asBuilder.setTimeout(0);
    asBuilder.setConnectable(false);
    mAdvertiseSettings = asBuilder.build();
パワーMAXばんばん発信設定でアドバタイズ設定を用意しておいて
    AdvertiseData.Builder mAdvertiseDataBuilder = 
          new AdvertiseData.Builder();
    mAdvertiseDataBuilder.addManufacturerData(0xFFFF, 
          BLEタグのMACアドレス);
    mBluetoothLeAdvertiser.startAdvertising(mAdvertiseSettings, 
          mAdvertiseDataBuilder.build(), mAdvertiseCallback);
あとはスタートするだけです。こんだけでいいなんて、昔BREWのBluetoothいじるのにあんなに苦労していたのは一体何だったのか。

それでは動かしてみます。BLEタグとカードの紐付けは、まずBLEタグのタグを読んでからカードを読むことで完了です。

BLEタグのNFCタグを読んで
紐付けするカードを読む

これで登録完了。

この状態で登録したカードを読ませると


光ったー
同じようなものができました。これなら製品化も簡単ですね(大変だけど)。

このデモセットは来月ビッグサイトで開催される自動認識総合展でもこっそり出展しますので遊んで見たい方はぜひご来場ください。