ブロックを積みながら(9) BLE LED service、スマホアプリ作成

Joseph Halfmoon

前回、micro:bit上でサポートされるBLEのサービスの一つであるLED serviceを走らせ、スマホから操作してみました。しかしスマホ側のアプリが「ショボい」上に LED serviceの「売り」である任意のパターンをマトリックスLED上に表示させる機能に対応していませんでした。今回はスマホアプリの方にてこ入れをしてマトリックスLEDに対応させます。

※「ブロックを積みながら」投稿順 index はこちら

(使用したソース全文は末尾に掲げてあります)

まず最初にお断りですが「ブロックを積みながら」と言いながら今回はブロックは積みません。前回述べましたとおり、micro:bit側で Bluetooth service を走らせる場合、UARTサービスを除けば「ブロック1個置くだけ」でサービスが利用可能となるためです。micro:bit側で走らせているプログラムは前回とまったく同じもの。Flashを書き換えていないので、スマホとの再ペアリングも不要であります。

さて DroidScript上で簡単に利用できる Bluetooth serviceの機能は以下のページを見るとハッキリします。

DroidScript – MicroBit Plugin

このうち以下に引用する2つの機能を利用する「スマホアプリ」を自力で作ろうと思います。

Draw pictures on the LEDs
Send scrolling text to the LEDs

なお、上記のページを見ると、今回やろうとしているMatrix LEDのパターンを表示するデモの動画(以下の例よりカッコいいやつ)が見つかります。そのプログラムの在りかは不明、かつ、あったとしてもコピペしたのでは勉強にならないので自力更生であります。

作ろうとしているスマホアプリの機能は実際のスマホ画面のスクリーンショットを見ていただくのが手っ取り早いかと思われます。

bleLEDserviceAPP上の方に “Send String to LED:”とある下のText編集ボックスに適当な文字(英数字)を入れ、右横の “Send” ボタンを押すと、入力した文字列が micro:bit に送られ MatrixLED 上を流れます。これは前回既に機能的には出来ていた部分ですが、あまりにUIが間延びしていたので改めたものです。

下の5x5個のボタンが並んでいる方が今回新たに実装した機能です。黒っぽいボタンの時0と表示されていますが、そこをタッチすると表示は1に変わり緑色になります。再タッチするとトグルして黒の0に戻ります。この機能を使って任意の表示パターンを「描いた後」、下にある Matrix ボタンを押すとそのパターンが micro:bit に送信されて表示される、と。その時の様子を先頭のアイキャッチ画像に示しました。

以上の処理を行う「スマホアプリ」のコードは末尾に添付しましたが、高々70行ばかりです。私は JavaScript 不得意なので上手な人が書けばもっと簡潔になるとおもいます。やっていることはGUI部品を並べているのがほとんどで、結局、BLE通信そのものは、以下の3メソッドにつきています。

  • microbit.Scan()でペアリング済のmicro:bitとconnect
  • microbit.ScrollText(文字列)で、文字列を送ってスクロール表示させる
  • microbit.SetLEDs(パターン配列)で、matrixLEDをパターンで点灯させる

DroidScriptとMicrobitプラグインのお陰であります。他にもサポートされている service があるので、次回は MakeCodeエディタでサービスを追加し、端から使用する「スマホアプリ」を作成して行きたいと思います。でもね、GUI作るのメンドイ。あまり好きじゃないんだこれが。。。

ブロックを積みながら(8) micro:bitのBluetooth serviceの使用 へ戻る

ブロックを積みながら(10) micro:bit、複数BLE serviceの共存の限界 へ進む

LEDservice用スマホアプリ(DroidScript用JavaScriptのソース)
app.LoadPlugin("MicroBit");

var btnArray = [];

function OnStart()
{
    lay = app.CreateLayout( "linear", "Vertical" );
    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.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);
    }
    layLB.SetPadding( 0.05, 0.05, 0.05, 0.05);
    return layLB;
}

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);
}