micro:bit 二人羽織作戦!　(BluetoothでNeoPixel制御)

これは、[microbit Advent Calendar 2017](https://qiita.com/advent-calendar/2017/microbit)の20日目の差し替え版です。

差し替え前の記事は[240個/4m NeoPixel tapeを光らせてみました (HSL指定)](https://qiita.com/nakatafu/items/792afe6fdaff5e8a0c59)となります。

# neopixel と bluetoothパッケージは 共存できない！ので...
micro:bitでNeoPixelを光らせることができますが...
次に、スマホからBluetoothで制御したいと思ったのですが、残念ながらneopixelパッケージを使った状態でbluetoothパッケージを有効にしようすると、
<img width="75%" alt="「bluetooth」といパッケージを追加できません。" src="http://drive.google.com/uc?export=view&id=1bRW2C-xUvoHppslXRQvsBddkkB7BHjsR">
と表示されて組み込むことができません。

実際のところ、nRF51822(micro:bitで使用されているSoC)のようにソフトウェアでBluetoothの制御を行うデバイスでは、頻繁に通信用の割り込み処理が入るため、NeoPixelのようなタイミングにシビアなデバイスの制御はできないのでしょう。

(なお、「無線」ライブラリはNeoPixelライブラリと共存できるので、micro:bit間通信を使ったNeoPixelのリモート制御は出来るんじゃないかな...)

これを無理矢理実現するために、micro:bitを2つ用意してシリアルで相互に通信させみればどうだろうと考えて作ってみたものが今日の内容となります。

以下が、作品を動かしている様子となります。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/vmdadWVW5co/0.jpg)](http://www.youtube.com/watch?v=vmdadWVW5co)

micro:bitを2台用意して下さい。１つはBluetooth通信用、もう１つはNeoPixel制御用に使います。
2つを組み合わせるのは、それぞれにファームウェアを書き込んで動作確認してからです。
本記事ではAndroidスマートフォン(Huawei P9)を使いました。

# Bluetooth通信用
まず、Bluetooth通信用のmicro:bitにファームウェアを書き込んで行きます。
プログラムは[こちら](https://makecode.microbit.org/_MD4cV91vpggb)となります。
[Adding Bluetooth Remote Control To :MOVE mini](https://www.kitronik.co.uk/blog/adding-bluetooth-remote-control-move-mini/)を参考に作成しました。

<a href="https://makecode.microbit.org/_MD4cV91vpggb">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1vh2_3NOi8Eaqr8OEOPq6tuXXfvNbT92I">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1qmqFckbg-eqZ182kRutVVuHcx6UjUFua">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1gEfcKiHlXcu68mUk0u0ML4OlOAQJo0Vb">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1DtoZFd1PbpUDg3TOGkSZXEiOQ9lmyngd">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1UpbfQQKl9JPVlN9o_YdK9ylirKiy_zoi">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1Lu7M0zYc7H_wiQJPQN80jOhqRr82pfiY">
</a>

スマートフォン側には、あらかじめをmicro:bitアプリをインストール。
[Mobile Apps for micro:bit](http://microbit.org/ja/guide/mobile/)を参考に、各デバイス用の公式アプリをインストール。そしてデバイスとペアリングしておきます。

続いて、リモコン用のアプリのインストール。
今日は、Android用の[Kitronik Move](https://play.google.com/store/apps/details?id=com.kitronik.kitronikmove&rdid=com.kitronik.kitronikmove)を使いました。
iOSでは[bitty controller](http://www.bittysoftware.com/apps/bitty_controller.html)が使えるようです。

以下の要領で単体テストを行いました。
1．スマホのmicro:bitアプリからmicro:bitのペアリングを行う。([Mobile Apps for micro:bit](http://microbit.org/ja/guide/mobile/)を参考に)
2. Kitronik Moveを起動し、左上の設定アイコン(三)からConnect to microbitを実行する
3. [SCAN FOR MICRO:BIT(S)]ボタンを押す
4. ペアリングしたmicro:bitを選択する(micro:bitのLEDがスマイルに変化する)<img width="300" alt="" src="http://drive.google.com/uc?export=view&id=1-xsjN6XAORVLMVr517AtdtnCbj4Yf8M8"><img width="200" alt="" src="http://drive.google.com/uc?export=view&id=1zMkOZZ2buhdw3dUhHvCYzX_Tqn_ZPfDr">
5. 左上の設定アイコン(三)からGame Padを実行する
<img width="300" alt="" src="http://drive.google.com/uc?export=view&id=1ituk3gVFRDv2nuTSV47BewXOvb4Avwdk">
6. 表示されたパッド(左右どちらも使用可能)を押すと、押した方向に合わせた矢印がmicro:bitのLEDに表示されます。離すとスマイルマークに表示が戻ります。
<img width="200" alt="" src="http://drive.google.com/uc?export=view&id=1dNhYKMsHAuWnnZpIyKBDEHjJVbsSflvi"><img width="200" alt="" src="http://drive.google.com/uc?export=view&id=1BT90F0U-R3OG7T-69SU_lPXapUp-pyXp"><img width="200" alt="" src="http://drive.google.com/uc?export=view&id=1zrdEeTl5N206saFg7vZqZmOJGPWuXa0R"><img width="200" alt="" src="http://drive.google.com/uc?export=view&id=1bXnxjfrGJLE1OOmC2bjRAJVieDggX4MF">
この矢印がちゃんと表示されるようであれば、送信側のmicro:bitは正常に動いていると思います。


それでも心配な方は、シリアルポートの初期化ブロック
<img width="100" alt="" src="http://drive.google.com/uc?export=view&id=1ex6nIHNIDuMMAbDBekOgeGVy7PR76ypk">
を削除して、PCとmicro:bit間でシリアル通信をして確認して下さい。パッドを押していない間は文字列"stop"が連続して、パッドを押したときは方向に対応した文字列（"up","down","left","right"）が連続して送信されていることが確認できます。
(PCとmicro:bit間のシリアル通信については、[オフィシャルサイトのドキュメントのシリアル通信のページ](https://makecode.microbit.org/device/serial)が参考になります。Windows PCによるTeraterm等を使った例が[chibi:bit（micro:bit）とWindowsでシリアル通信する](https://studio.beatnix.co.jp/kids-it/hardware/chibi-bit/serial-communication-win/)に出ています。)

<b>ここで注意点</b>
- ファームウェアを更新した場合は、再ペアリングが必要なようです。Androidの場合は設定メニューからパエリング解除を行い、micro:bitアプリによるペアリング(Connect)をやり直してください。
- この時、Kitronik Moveアプリも一旦完全に停止してからでないと、うまく再接続できないようです。

# Neopixel制御用
次に、NeoPixel制御用のmicro:bitを作っていきます。

回路、HSL制御の関数追加等についての詳細は[240個/4m NeoPixel tapeを光らせてみました (HSL指定)](https://qiita.com/nakatafu/items/792afe6fdaff5e8a0c59)を流用します。

プログラムは[こちら](https://makecode.microbit.org/_1iafsFTrdVsJ)となります。
シリアルポートの受信指定がP0になっていることに注意してください。
また、NeoPixelは[流用元](https://qiita.com/nakatafu/items/792afe6fdaff5e8a0c59P1)ではP0に接続していましたが、P0をボード間のシリアル通信で使う予定であるため、P1に変更しています。接続もそれに合わせて変更して下さい。

<a href="https://makecode.microbit.org/_1iafsFTrdVsJ">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=182AMErqqvTfCtVzkcWJV4kd1vqbXcDVv">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1ahi2sjOw4Xee2yPdEEs1_vM5R1l2b-8x">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1xsibFkZmKWqhbJyiuSkGNi_c9iMP5aPb">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1IOtMNC6g0HKf8P5OIOFt-P5D2hnfWT9g">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1A6Gk0s70HCOfz7jqcbOg3EeJ8WEIldf6">
<img width="420" alt="" src="http://drive.google.com/uc?export=view&id=1z4BIptCdjraw4njlWcuA-j_cnhREZXOS">
</a>

こちらも、シリアルポートの初期化ブロック
<img width="100" alt="" src="http://drive.google.com/uc?export=view&id=1ex6nIHNIDuMMAbDBekOgeGVy7PR76ypk">
を削除して、PCとmicro:bit間でシリアル通信をして動作確認することができます。

enter抜きで"up.", "down.", "right.", "left." 等をタイプすると、micro:bitのLED画面に矢印が現れ、NeoPixelの表示が動きます。私のNeoPixelは一周17個ずつで巻き上げているため、動きはそれに合わせています。ボタンに対応した動きは各自で工夫して下さい。

# 両ボードの接続
両ボードをM3のネジ、スペーサ、ナットを使って組み合わせていきます。
P0, 3V, GNDの3端子は両ボードを連結します。
また、ミノムシクリップが接続しやすいようにNeoPixel制御シグナル送信用のP1について、単体でネジを立てています。

私が作ったものは以下のようになりました。(上がNeoPixel制御用、下がBlueTooth通信用となります。)
<img width="45%" alt="" src="http://drive.google.com/uc?export=view&id=1v548JiC3SZijBjyRuR2Q3BnSQmMRklmr"><img width="45%" alt="" src="http://drive.google.com/uc?export=view&id=1xBXBmex7bDzfWIyr-nscC3OPTpERGoY4">

そして、NeoPixelをつないでいきます。
<img width="45%" alt="" src="http://drive.google.com/uc?export=view&id=13ceUXK6-e_gduBJxh-4mu7aKLtDR7MAp">

そして、電源をどれか１つのmicro:bitに供給します。方法はUSBケーブル、電源コネクタ、エッジコネクタどれを使ってもOKです。(ただしNeoPixel制御に十分な電圧が供給されるように注意してください。)

<FONT COLOR="RED"><B>ここで、注意があります。絶対に両ボードに同時に電源を供給したり、USBケーブルを接続しないでください。</B></FONT>
どうしても同時に供給したい場合は、3V端子を切り離してください。

うまく行くと、[こちらの動画
<img width="45%" alt="" src="http://drive.google.com/uc?export=view&id=1zE7j2ZUH77D2WglovvSSDmpwhJjqEfxp">](https://www.youtube.com/watch?v=EJFYFsGQYgU)
のように、Kitronik MOveのパッドを押すとNeoPixelの点灯がその方向にシフトします。

# NeoPixel制御用micro:bit改良
実は、上で作ったNeoPixel制御用micro:bitのファームウェアは、NeoPixel制御と本体のLED点灯を同時に行うのが結構つらいらしく、BlueToothリモコン操作時の応答が悪いです。

そこで、上記で動作確認が取れたのち、[本体のLED制御処理を削除した版](https://makecode.microbit.org/_TTWbvuVhq30C)を作成しました。

これにより、かなりスムーズに応答するようになりました。
[動画はこちらになります](https://youtu.be/vmdadWVW5co)

# はまりどころまとめ
- serial同士通信させる場合、1行書き出しで書き出したものが1行読み込みできない。どうも書き出しの方は行末が0x0dのみであるのに対し、読み込みの方は0x0aを要求している様子。今回は1行書き出し/読み込みを使わずに、"."を区切りとして使うことで回避
- 上にも書きましたが、Bluetooth側のfirmwareを書き換えるたびに再ペアリングしないとうまくつながらない。二人羽織にするとボタンが押しにくいので、結構めんどくさかったです...
- kitronik moveアプリが再接続に失敗する現象が多発。アプリをしっかり停止してから再接続すれば良いと気づくまで、結構時間を無駄にしました。