
前回は 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 );
}
}

