micro:bitで作ったラジコンを、スマートフォンで操作する。

ねえパパ、ラジコン作りたい。

数年前のクリスマス少し前、息子（当時小1）のこの言葉からはじまったラジコン作り。[前回、ついにラジコンが完成した！](https://qiita.com/secile/items/25e83a5d4d591ba0674e)これでよし！。これでもいいんだけど、本体用のmicro:bitとは別に、リモコン用にジョイスティックとmicro:bitがもう1台必要。お金がかかる。

🤔「でも、やっぱり、もう１つmicro:bitを購入するのは、ちょっと...」
😑「ジョイスティックなしで、なるべく安くコントローラーをつくりたいよ...」

そこで、スマートフォンからmicro:bitを操作できるようにするアプリを開発しました。

# スマホをコントローラーにする仕組み。

micro:bitはBLE(Bluetooth Low Energy)に対応しており、スマホと無線で通信を行うことができます。最近のスマホのブラウザは、「Web Bluetooth API」に対応しており、JavaScriptでWebアプリを構築すれば、**~~iPhone/Androidに両対応した~~**、BLE通信でmicro:bitを操作するアプリを作成することができるのです。

<font color="DeepPink">**追記：iPhone/iPadなどのiOSでは、標準ブラウザのSafariではWeb Bluetooth APIには対応してないということです。App Storeから「[Bluefy](https://apps.apple.com/jp/app/bluefy-web-ble-browser/id1492822055)」というブラウザをインストールすれば利用できる、ということです。私の認識違いでした。お詫びして訂正したします。**

作成したプログラムはgithubで公開しています。アプリの名前は「micropad」です。
index.htmlをダウンロードしてブラウザで開けば実行することができます。

https://github.com/secile/micropad

または以下のURLを開けば、そのまま実行することができます。
https://secile.github.io/micropad/

画面はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/d6773c00-9c57-2fc6-f7fd-1597f488dbe7.png)

# 使い方。
- 「🚩」ボタンを押すと、周囲のmicro:bitを検索して接続することができます
- 「🛑」ボタンを押すと、micro:bitと切断します 
- 目玉のような丸が二つありますが、これはアナログスティックです
- その他、「X」「Y」とかかれたボタンと、スライダーがあります。

アナログスティックは指で操作することができます。これでラジコンを操作できるようにします。

![AnalogStick.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/bfab8371-693c-9628-fc6f-449ef765f02b.gif)

このアナログスティックを操作すると、BLEでmicro:bitにメッセージを送信します。送信するメッセージはコントロールの種類ごとに異なりますが、カンマ区切りで3つのパラメータを送信します。

アナログスティックのフォーマットは次の通りです。

```
‘Control ID, Angle, Power‘ （例：'a1, 3.14, 0.5'など）
```

|名前 |意味 |例 |
|---|---|---|
|Control ID |左スティックは'a1'、右スティックは'a2'を表します。 |a1 |
|Angle |スティックが入力された角度です。X軸(右側)を原点に時計周りのラジアン角です。少数第二位までの値を取ります。 |3.14 |
|Power |スティックの中心からの距離を0.0～1.0範囲です。 |0.5 |

AngleとPowerについてもう少し詳しく説明します。Angleはラジアン角で0～360度の代わりに、0～2πを使います。あまりなじみがないかもしれませんが、プログラミングではよく出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/591be5d5-deb2-0057-f6ea-a41c35b7a7d8.png)

AngleもPowerもあまり細かすぎると、送信するデータが膨大になり処理が追いつきませんので、Angleは8方向、Powerは3段階（1.0、0.5、0.0）に制限しています。

ボタンやスライダーのフォーマットについては、上記[githubページ](https://github.com/secile/micropad)を参照ください。

# micro:bit側のプログラム。

このmicropadに対応した、micro:bit側のプログラムの作成方法について説明します。

- まずプログラムの作成前に、「拡張機能」から「bluetooth」の追加が必要です。拡張機能の検索窓に「bluetooth」で検索し、見つかった「bluetooth」サービスをプロジェクトに追加します。
- その際、「radioと同時に使用できません。radioを削除しますか？」と聞かれるので、「追加する」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/7446e035-2392-ff65-86c0-19a016ae3374.png)

- もう１つ。プロジェクトの設定から「No Pairing Required」を選択して「保存」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/018269b2-4cdb-3bd5-6662-e361a1e00d4f.png)

- いよいよブロックプログラムを行っていきます。
- まず「最初だけ」ブロックに「Bluetooth UARTサービス」を追加します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/81d8d3ac-8518-0393-98de-b7f5036292fb.png)

- 「Bluetoothデータを受信したとき」ブロックで、micro:bitから受信したメッセージを3つのパラメータに分解して、Control ID, Value1, Value2変数に格納します。
- 新たに「受信した」関数を作成し、それを呼び出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/7c876f90-c649-e453-383d-e5fb7fb1e62d.png)

- 「受信した関数」ブロックでは、Control IDによって分岐し、Value1やValue2を使って処理を行います
- Value1には「Angle」が、Value2には「Power」が代入されています。AngleやPowerからもとのスティックのX成分とY成分を取り出すには、以下の演算を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/53007282-a47f-6478-ad6b-441215f10ab7.png)

- micropadの動作確認用のサンプルとして、アナログスティックとボタンとスライダーを使った例を示します。
    - [MakeCodeプロジェクトへのリンク](https://makecode.microbit.org/S40580-83171-35160-56493)
- 左右のアナログスティックでHeroを操作し、XボタンとYボタンでLEDにそれぞれ'X'と'Y'を表示します。スライダーはLEDの明るさを調節します。
- これを実行するには「最初だけ」ブロックに「スプライトを作成」を追加する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/a2927f85-ccbf-b1b7-b85d-6132c741d2da.png)

# いざ、ラジコンをコントロール。
この仕組みをつかって、ラジコンを操作するためのプログラムを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245196/b776a322-0aea-fe9a-0ba7-426fc022d5fe.png)

- ControlIDが'a1'(左スティック)の場合、X成分(-1～+1まで)を40から140にマップして、角度モーターを動かします。
- ControlIDが'a2'(右スティック)の場合、Y成分(-1～+1まで)を100から-100にマップして、回転モーターの速度を変更します。
- 今回はアナログスティックのみ使用します。ボタンやスライダーは使用してないので、クラクション(効果音再生)やライト点灯(全LED点灯)などに使うと、おもしろいかもしれません。

このプログラムをmicro:bitに書き込んで、無事、スマホからラジコンを操作することができました。使った感触はジョイスティックでラジコンを操作している時とそれほど遜色ありません。

# 最後にまとめ。

息子がラジコンを作りたいと言い出してから早数年。小学校高学年になりました。息子はその後、段ボールと割りばし、輪ゴムで銃を作ることにハマり、電子工作にハマることはありませんでした。それでもたまに、モーターやスイッチなどをつかって、工作をすることがあります。「ねぇパパ。これどうやって作るん？」と聞かれた時に、色々教えてあげられる存在でいたいと思います。

今回作成したアプリは、ラジコン操作だけでなく、他のmicro:bitを利用した装置を操作する方法として、利用することができます。プログラムを少し改造すれば、ボタンを追加したり、スライダーを複数にすることも難しくありません。ぜひ皆さんにも利用してもらえたら、これ以上の幸せはありません。

おしまい。