micro:bit RSSI(受信信号強度)を用いた近接検知アプリを作る

はじめに

本記事では2つのmicro:bitを用いて作成した近接検知アプリを紹介します。

micro:bitを持っている人同士の距離が遠い時は、micro:bitのLEDに笑顔が表示され、距離が近くなるとLEDで困り顔が表示された上に、スピーカーからの音声で警告を鳴らし、2人には距離を取ってもらう、そんな使い方が可能です。

前提となる技術

RSSI(電波強度)について

一般的というほど一般的かどうかはわかりませんが、電波強度はRSSI(Received Signal Strength Indication)と呼ばれ、その単位は[dbm]となります。

詳しい説明はしませんが、2つのmicro:bitを真横距離5cm以内に置いた時に、micro:bitで測定されるRSSIは-40[dbm]程度となり、距離を離していくとその数値はどんどん悪くなっていきます。私の感覚では-120[dbm]あたりからはもう無線信号も届かなくてなってくると理解していますが、これは環境によりけりです。

本記事で紹介している近接検知の判定はこのRSSIにて実施していますので、上記をご理解の上ご使用下さい。

過去のデータを保持する仕組み

micro:bitは無線信号の強度を測定することが可能ですが、障害物や別の電波を発信する機器があることにより、micro:bit自体が動かされていなくても値にバラつきが出てしまうことがあります。そのため、このアプリケーションでは過去5回分の信号強度の平均を計算することで、そのバラつきを抑える仕組みとしています。(ご使用される環境によって、これも良し悪しがありますが…)

micro:bitには配列を作成するブロックが用意されていますので、このブロックに過去5回分のデータを格納し、その平均を計算していくようにします。今回はプログラム中、上記を配列名 list で管理します。初期値としては -128を入れておきます。

そして無線データを受信するごとに、そのRSSIの値を配列 list の[0]から順番に格納していきます。

更にデータを受信し続けると、配列 list の中身は以下のように変わっていきます。[4]のlistが更新された後、次に更新されるのは[0]であることがポイントとなります。

こうしてデータ構造を持つことで過去5回分のデータを持ち続けることが可能となります。

プログラムの説明

全体

デバッグ用のブロックを含めると全体で以下のような内容となりました。ここのブロックについて簡単に説明していきます。

最初だけ

「最初だけ」のブロックで実施する内容は以下です。

  • LEDアイコンの表示(笑顔)
  • 無線グループの設定
  • ボリュームの設定
  • 変数、配列の初期値の設定

ずっと

「ずっと」のブロックで実施する内容は以下です。

  • 無線データの送信
  • 平均RSSIの距離に応じた関数の呼び出し(short_distance, middle_distance, long_distance)
  • 500msの処理停止
  • デバッグ用のシリアルデータ送信を行う関数の呼び出し(debug_serial)

変数 average_rssi には過去5回の受信データから測定されるRSSIの平均が格納されています。この値がいくらになっているか、によって呼び出す関数を変更させています。上記の例では-65 以下のRSSIで長距離(long_distance)、-45~-60を中距離(middle_distance)、-45 以上を短距離(short_distance)としていますが、この判定の値は実際に使ってみてから調整して下さい。

「ずっと」の処理の中で呼び出されている short_distance, middle_distance, long_distanceの処理の中身は以下のようになっています。

「ずっと」の処理の中で呼び出されている debug_serial の処理の中身は以下のようになっています。

こちらは機能には必須ではありませんが、目に見えない無線信号の機能開発となりますので、どういったRSSI値となっているかを確認するために、こういった機能を入れることをお勧めします。この処理を入れることで、Teraterm上では以下のように、現在の状態を確認することが可能となります。

無線で受信したとき

「無線で受信したとき」のブロックで実施している内容は以下としています。

  • 受信したデータの信号強度で配列 list を更新する関数の呼び出し(queue_insert)
  • 配列 list の平均値を算出し、average_rssi の変数の格納する関数の呼び出し(calculate_average_rssi)

「無線で受信したとき」の処理の中で呼び出されている関数 queue_insertの中身は以下のようになっています。

  • 配列のcount 番目の要素を、今回受信したデータのRSSIで更新
  • 変数 count を1つ増やす
  • 変数 count が 変数 max_count(配列の要素数)と一致した場合に count を '0’にする

「無線で受信したとき」の処理の中で呼び出されている関数 calculate_average_rssi の中身は以下のようになっています。

  • 変数 temp を '0’ に
  • 配列の要素の0からmax_count-1に格納されている値を合計し、tempに格納
  • temp を max_countで割り、その結果をaverage_rssiとする

作成したプログラムの説明は以上となります。是非、動作を確認してみて下さい。micro:bit同士の距離により、LEDの表示や通知音が変化するかと思います。

さいごに

ラズベリーパイと組み合わせれば、COCOA相当のものも作れるんじゃないか、そんな気持ちから作ったアプリケーションでした。

また、面白いアイデアがあれば形にしてみたいと思います。

おまけ

同じアイデアでmicro:bitを使った宝さがしゲーム、なんてものも出来ますね。