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

2026年6月12日

はじめに

以前からmicro:bitの無線通信機能を使って何か実用的なものを作ってみたいと考えていました。特に気になっていたのが、2台のmicro:bitの距離に応じて何らかのリアクションを起こせないか、という点です。

そこで今回は、2台のmicro:bit間の無線信号強度(RSSI)を測定し、距離が遠い時はLEDに笑顔を表示し、距離が近くなるとLEDで困り顔を表示した上でスピーカーから警告音を鳴らす「近接検知アプリ」を作成しました。同じような仕組みを検討している方の参考になればと思い、実装の流れをまとめます。

距離が遠い時のmicro:bitのLED表示(笑顔アイコン)
距離が近い時のmicro:bitのLED表示(警告アイコン)

RSSI(受信信号強度)を使った近接検知の仕組み

RSSIとは?距離による電波強度の変化

電波強度はRSSI(Received Signal Strength Indication)と呼ばれ、単位は[dbm]で表されます。

詳しい理論には触れませんが、2台のmicro:bitを真横に5cm以内に置いた場合、measured されるRSSIは-40[dbm]程度となり、距離を離すごとに数値はどんどん悪化していきます。筆者の感覚では-120[dbm]あたりからは無線信号がほとんど届かなくなりますが、これは使用環境によって変わります。

本記事で紹介する近接検知の判定は、このRSSIの値をもとに行っています。上記の特性を踏まえた上でご利用ください。

過去5回分のデータを平均化してノイズを抑える仕組み

課題:micro:bitは無線信号の強度を測定できますが、障害物や周囲の電波の影響により、micro:bit自体が動いていなくても値にバラつきが出てしまいます。
解決策:過去5回分の信号強度の平均を計算することで、このバラつきを抑える仕組みにしました(環境によって最適な回数は変わるので、調整の余地があります)。

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

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

過去5回分のRSSIを格納する配列listの初期状態

さらにデータを受信し続けると、配列listの中身は次のように変化していきます。[4]が更新された後、次に更新されるのは[0]に戻る点がポイントです。

データ受信後に更新される配列listの状態遷移

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

micro:bitプログラムで実装した4つの処理

デバッグ用のブロックを含めると、プログラム全体は以下のような構成になりました。ここから各ブロックの内容を順番に説明します。

micro:bitプログラム全体のブロック構成

1. 起動時にLED・無線グループ・変数を初期化する

課題:距離判定や無線通信を始める前に、各種設定や変数を初期状態に揃えておく必要がある。
解決策:「最初だけ」ブロックでまとめて初期化する。

「最初だけ」のブロックで実施している内容は以下のとおりです。

  • LEDアイコンの表示(笑顔)
  • 無線グループの設定
  • ボリュームの設定
  • 変数・配列の初期値の設定
「最初だけ」ブロックの初期設定処理

2. 平均RSSIに応じてLED表示と警告音を切り替える

課題:計算した平均RSSIの値を使って、距離に応じたLED表示や警告音を継続的に切り替えたい。
解決策:「ずっと」ブロックでメインループを構成し、距離に応じた関数を呼び出す。

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

  • 無線データの送信
  • 平均RSSIの距離に応じた関数の呼び出し(short_distancemiddle_distancelong_distance
  • 500msの処理停止
  • デバッグ用のシリアルデータ送信を行う関数の呼び出し(debug_serial
「ずっと」ブロックのメインループ処理

変数average_rssiには、過去5回分の受信データから算出した平均RSSIが格納されています。この値によって呼び出す関数を変更しており、今回の例では-65以下を長距離(long_distance)、-45〜-60を中距離(middle_distance)、-45以上を短距離(short_distance)としています。この判定値は、実際に使ってみてから環境に応じて調整してください。

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

short_distance/middle_distance/long_distance関数の処理内容

3. 受信データを配列に格納し平均RSSIを再計算する

課題:無線データを受信するたびに、過去5回分の配列を更新し、最新の平均RSSIを計算し直す必要がある。
解決策:「無線で受信したとき」ブロックでqueue_insertcalculate_average_rssiの2つの関数を呼び出す。

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

  • 受信したデータの信号強度で配列listを更新する関数の呼び出し(queue_insert
  • 配列listの平均値を算出し、average_rssiに格納する関数の呼び出し(calculate_average_rssi
「無線で受信したとき」ブロックの処理内容

queue_insert関数の中身は以下のようになっています。

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

calculate_average_rssi関数の中身は以下のようになっています。

  • 変数tempを0にする
  • 配列の0からmax_count-1に格納されている値を合計し、tempに格納
  • tempmax_countで割り、その結果をaverage_rssiとする
calculate_average_rssi関数による平均値算出処理

4. デバッグ用にシリアル出力でRSSI値を確認する

課題:目に見えない無線信号を扱う開発のため、現在のRSSI値がどう変化しているかを確認したい。
解決策:debug_serial関数でシリアル出力を行い、Tera Termで値を確認できるようにする。

「ずっと」の処理の中で呼び出されるdebug_serial関数の中身は以下のようになっています。機能としては必須ではありませんが、動作確認のためにこういった処理を入れておくことをお勧めします。

debug_serial関数によるシリアル出力処理

この処理を入れることで、Tera Term上では以下のように現在の状態を確認できます。

Tera Termで確認したRSSIデバッグ出力の画面

プログラムの説明は以上です。ぜひ動作を確認してみてください。micro:bit同士の距離に応じて、LEDの表示や通知音が変化するはずです。

まとめ:RSSIによる近接検知アプリ実装のポイント

今回の記事で紹介したポイントをまとめます。

  • RSSI(受信信号強度)を使うと、2台のmicro:bit間のおおよその距離を判定できる
  • RSSIの値は環境によってばらつくため、過去5回分の配列で平均化するとノイズを抑えられる
  • 平均RSSIの値をしきい値で分け、距離に応じてLED表示や警告音を切り替えられる
  • シリアル出力で現在のRSSI値を確認しながら開発すると、しきい値の調整がしやすい

ラズベリーパイと組み合わせれば、ソーシャルディスタンスを促す通知アプリのようなものも作れそうです。また、同じ仕組みを応用すれば、micro:bitを使った宝探しゲームのように、近づくほどヒントが得られるゲームも作れます。面白いアイデアがあれば、また形にしてみたいと思います。

同じ仕組みを応用したmicro:bit宝探しゲームのイメージ