前回は BBC micro:bitのbluetooth led serviceというものを走らせ、スマートフォンからDroidScriptで点灯制御してみました。今回は、複数のservicesをmicro:bit上で共存させ、その機能をスマホから使ってみたいと思います。しかし今回、micro:bit v2を購入できていないのが、ボディーブローのように効いてきました。
※「ブロックを積みながら」投稿順 index はこちら
ぶっちゃけ、結論を最初に申し上げると、以下のようです。
- BBC micro:bit 上で複数の Bluetooth serviceを同時に利用することはできる
- ただし、メモリの制限でエラーになることがある。(micro:bit v1.5)
まず、MakeCodeブロックエディタから呼び出して使える Bluetooth service(UART除く)は以下のようなものがあります。このうち前回は bluetooth led serviceだけを”on start”ブロック内に置いて走らせました。この際、
全部の service を “on start” ブロックに置いてしまえばいいんじゃね
そのようにいたしたくなるのは、MakeCodeエディタで micro:bit のフラッシュにプログラムを書きこむ度に、例の面倒な「ペアリング」をしなければならないためであります。全部のサービスを起動しておけば、micro:bitのフラッシュを書き換える必要はないのでペアリングは不要。スマホ側の「アプリ」の修正だけで全てのサービスを利用することができる筈、と考えました。
しかし、ズボラな悪だくみは成功しません。全ての service を”on start”に入れ込むとHEXファイルを書きこみ終了するなり
020
なるエラーが出ます(micro:bitのledマトリックス上では、02という数字が流れた後に「泣き顔」みたいなフェイスマークが現れるのでエラーと分かります。)以下に micro:bit のエラー・コードの一覧ページへのリンクを置きます。
上記のページからエラーコード 020 の説明文を引用させていただきます。
020 There is no free memory on the micro:bit. Your program might be too complex or contain a lot of large variables. Try reducing your code by making functions out of large sections.
メモリ(RAM)が足らないみたいです。手元の micro:bit v1.5は16KBしかなく、以前も MicroPythonの動作の制約になっていたのを思い出しました。在庫0で買えないでいる micro:bit v2が手元にあればな!v2なら確かRAMは128KBある筈。残念。
仕方がないので、テキトーにサービスの数を削って行くことにいたしました。全てのサービスが同じだけメモリを食う分けではないでしょうから、ちゃんと調べるには6個からn個とる組み合わせをシラミツブシに調べるべきでしょうが、手間が膨大。とりあえずスマホアプリが一応できている led service は残し、他にいくつかサービスを加えてみます。
4個のサービスを同時に入れてみました。HEXファイルの書き込み終了後も 020 エラーは出ません。そこで面倒な「ペアリング」をやってから、スマホアプリを起動、コネクト!
コネクトした直後に 020 エラー再発
であります。4個も駄目。3個にしてみました。また駄目でした。ledの隣にね、buttonが2つある。他のサービスよりbuttonの状態を読むのは簡単そうだから led + button でどう?
動きました、万歳
簡単なサービスの追加ですが、一応、2個のサービスが並存しています。念のため、今回使用した「スマホアプリ」のJavaScriptコード(DroidScript)全文を末尾に掲げますが、前回のものの「チョイ直し」です。動作させたスマホ画面の上半分はこんな感じ。
Button入力対応になった「スマホアプリ」の画面
micro:bitのボタンを押したことがちゃんとスマホに伝わっています。
さてねえ、残りのBLEサービスを何個かづつ「消化」していくか。しかし面倒。それに別件のマクドナルドのBLEテーブルロケータで、ちょっとそっち方面に興味が湧いてきました。micro:bit v1.5の小さいメモリでもBLEビーコン的なものは出来そうなので、まずそっちをやりますか。v2買えたらまたペアリングして使うサービスに戻って来たいですが。いつもながらの行き当たりばったり。
ブロックを積みながら(9) BLE LED service、スマホアプリ作成 に戻る
ブロックを積みながら(11) micro:bit、EddystoneでBLE Beaconを へ進む
前回のDroidscriptによるスマホアプリをButton対応に拡張したもの
app.LoadPlugin("MicroBit"); var btnArray = []; function OnStart() { lay = app.CreateLayout( "linear", "Vertical" ); txtButtonA = app.CreateText("Button A = ...", 1.0, 0.07, "Bottom" ); lay.AddChild(txtButtonA); txtButtonB = app.CreateText("Button B = ...", 1.0, 0.07, "Bottom" ); lay.AddChild(txtButtonB); txt0 = app.CreateText("Send String to LED:", 1.0, 0.1, "Bottom" ); lay.AddChild(txt0); lay0 = app.CreateLayout( "linear", "Horizontal, FillXY" ); edt = app.CreateTextEdit("", 0.5, 0.07 ) edt.SetTextSize( 16 ); lay0.AddChild( edt ); btnSend = app.CreateButton( "Send", 0.25, 0.07 ); btnSend.SetOnTouch( btnSend_OnTouch ); lay0.AddChild( btnSend ); lay.AddChild(lay0); lay.AddChild(ledButtonLayout()); btnMatrix = app.CreateButton( "Matrix", 1.0, 0.07 ); btnMatrix.SetOnTouch( btnMatrix_OnTouch ); lay.AddChild(btnMatrix); app.AddLayout( lay ); microbit = app.CreateMicroBit(); microbit.SetOnConnect( OnConnect ); microbit.SetOnButton( OnButton ); microbit.Scan(); } function btnSend_OnTouch() { var txt = edt.GetText() microbit.ScrollText(txt); } function ledButtonLayout() { layLB = app.CreateLayout( "linear", "Vertical" ); for (let yidx = 0; yidx < 5; yidx++) { layLB0 = app.CreateLayout( "linear", "Horizontal"); for (let xidx =0; xidx < 5; xidx++) { btnArray[yidx*5 + xidx] = app.CreateButton( "0", 0.15, 0.07 ); btnArray[yidx*5 + xidx].SetStyle("Black"); btnArray[yidx*5 + xidx].SetOnTouch( toggleColor ); layLB0.AddChild(btnArray[yidx*5 + xidx]); } layLB.AddChild(layLB0); } function toggleColor() { if (this.GetText() == "0") { this.SetStyle("#22aa22"); this.SetText("1"); } else { this.SetStyle("Black"); this.SetText("0"); } } function btnMatrix_OnTouch() { var workArray = []; for (let idx = 0; idx < 24; idx++) { if (btnArray[idx].GetText() == "0") { workArray[idx] = 0 } else { workArray[idx] = 1 } } microbit.SetLEDs(workArray); } function OnConnect() { app.ShowPopup("Connected!"); } function OnButton( name, stat ) { var status; if (stat == "1") { status = "ON"; } else { status = "OFF"; } if (name == "A") { txtButtonA.SetText( "Button A = " + status ); } else { txtButtonB.SetText( "Button B = " + status ); } }