みかづきブログ・カスタム

基本的にはちょちょいのほいです。

micro:bit(マイクロビット)とGoogle ChromeをWeb Bluetooth APIで繋ぐ 🟦

タイトルの通りです。micro:bitとGoogle ChromeをWeb Bluetooth APIで繋ぎました。
Google Chromeからmicro:bitのLEDマトリクスを制御します。

まず、micro:bitの説明は端折りますが、簡単に説明すればマイコンです。
英国では11〜12歳の子供、全員に無償で配布されてるらしいです。すごい。

当然、日本でも購入できます。僕はスイッチサイエンスで購入しました。

www.switch-science.com

micro:bitにプログラムを書き込む

まずは、micro:bitにプログラムを書き込むを書き込みましょう。
micro:bitとパソコンをUSBで接続し、micro:bitのサイトにアクセスします。

f:id:kimizuka:20211019235237p:plain

「新しいプロジェクト」からプロジェクトを立ち上げます。

f:id:kimizuka:20211019235404p:plain

プロジェクト名を適当に入力します。
また、僕はコードオプションをJavaScriptだけにしていますが、GUIを使ったプログラムやPythonでのプログラムも可能です。

f:id:kimizuka:20211019235539p:plain

プロジェクトを作成するとエディタが開きます。
まずは、Bluetoothを使えるようにする必要がある(デフォルトでは使えない)ので、「高度なブロック」「拡張機能」をクリックします。

f:id:kimizuka:20211019235644p:plain

検索窓に「bluetooth」と打ち込み検索すると、bluetoothが見つかるのでクリックします。

f:id:kimizuka:20211019235722p:plain

bluetoothをONにするとradioがOFFになりますが気にせず追加します。

f:id:kimizuka:20211019235854p:plain

追加したら、コードを打ち込みます。
下記コードを書き込めばOKです。

bluetooth.startLEDService();

bluetooth.onBluetoothConnected(function () {
    basic.showIcon(IconNames.Happy)
});

bluetooth.onBluetoothDisconnected(function () {
    basic.showIcon(IconNames.Sad)
});

コードを書いたら、コードをマイコンに書き込みます。

f:id:kimizuka:20211019235955p:plain

「...」から「Connect Device」をクリックします。

f:id:kimizuka:20211020000039p:plain
f:id:kimizuka:20211020000035p:plain

2回ほど「次へ」をクリックします。

f:id:kimizuka:20211020000200p:plain

「接続」をクリックして、接続します。

f:id:kimizuka:20211020000256p:plain

「完了」をクリックします。これで接続完了です。

f:id:kimizuka:20211020000323p:plain

「ダウンロード」をクリックしてしばらく待ちます。

f:id:kimizuka:20211020000350p:plain

「Downloaded!」になったらマイコンへの書き込み完了です。

f:id:kimizuka:20211020000503p:plain

「🔒」をクリックし、micro:bitの右にある×をクリックしてデバイスの接続を解除します。
micro:bitはリムーバルディスクとして認識されているので、アンマウントしてからパソコンから抜きます。

これでmicro:bit側の準備はOKです。

ウェブサイト側はこんな感じのHTMLを作りました。

<!DOCTYPE html>
<html lang="ja">
  <meta charset="UTF-8" />
  <title>micro:bit</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover, shrink-to-fit=no" />
</head>
<body>
  <button id="connect">接続</button>
  <button id="disconnect">切断</button>
  <script>
    const LED_SERVICE_UUID = 'e95dd91d-251d-470a-a062-fa1922dfa9a8';
    const LED_MATRIX_STATE = 'e95d7b77-251d-470a-a062-fa1922dfa9a8';
    const microBitList = [];
    const ctxList = [];
    const numList = [[
      '01110',
      '01010',
      '01010',
      '01010',
      '01110'
    ],[
      '00100',
      '00100',
      '00100',
      '00100',
      '00100'
    ],[
      '01110',
      '00010',
      '01110',
      '01000',
      '01110'
    ],[
      '01110',
      '00010',
      '01110',
      '00010',
      '01110'
    ],[
      '01010',
      '01010',
      '01110',
      '00010',
      '00010'
    ],[
      '01110',
      '01000',
      '01110',
      '00010',
      '01110'
    ],[
      '01110',
      '01000',
      '01110',
      '01010',
      '01110'
    ],[
      '01110',
      '00010',
      '00010',
      '00010',
      '00010'
    ],[
      '01110',
      '01010',
      '01110',
      '01010',
      '01110'
    ],[
      '01110',
      '01010',
      '01110',
      '00010',
      '01110'
    ],[
      '10111',
      '10101',
      '10101',
      '10101',
      '10111'
    ],[
      '10010',
      '10010',
      '10010',
      '10010',
      '10010'
    ],[
      '10111',
      '10001',
      '10111',
      '10100',
      '10111'
    ],[
      '10111',
      '10001',
      '10111',
      '10001',
      '10111'
    ],[
      '10101',
      '10101',
      '10111',
      '10001',
      '10001'
    ],[
      '10111',
      '10100',
      '10111',
      '10001',
      '10111'
    ],[
      '10111',
      '10100',
      '10111',
      '10101',
      '10111'
    ],[
      '10111',
      '10001',
      '10001',
      '10001',
      '10001'
    ],[
      '10111',
      '10101',
      '10111',
      '10101',
      '10111'
    ],[
      '10111',
      '10101',
      '10111',
      '10001',
      '10111'
    ]];
    let count = 0;

    document.getElementById('connect').addEventListener('click', async () => {
      const microBit = await navigator.bluetooth.requestDevice({
        filters: [{
          services: [
            LED_SERVICE_UUID
          ]
        },{
          namePrefix: 'BBC micro:bit'
        }]
      });

      const server = await microBit.gatt.connect();
      const primaryService = await server.getPrimaryService(LED_SERVICE_UUID);

      ctx = await primaryService.getCharacteristic(LED_MATRIX_STATE);

      microBitList.push(microBit);
      ctxList.push(ctx);
    });

    render();

    function render() {
      if (microBitList.length) {
        const array = new Uint8Array(5);

        numList[count].forEach((str, i) => {
          array[i] = parseInt(str, 2);
        });

        ctxList.forEach((ctx) => {
          ctx.writeValue(array);
        });

        count = (count + 1) % numList.length;
      }

      setTimeout(render, 1000);
    }

    document.getElementById('disconnect').addEventListener('click', () => {
      if (microBit) {
        microBit.gatt.disconnect();
        microBit = null;
      }
    });
  </script>
</body>
</html>

f:id:kimizuka:20211020000918p:plain

https://develop.kimizuka.org/microbit/ にホスティングしているのでGoogle Chromeでアクセスします。

develop.kimizuka.org

今回はLED SERVICEとLED Matrix StateのUUIDを使いましたが、必要に応じてこちらのサイトから探す必要があります。

lancaster-university.github.io


f:id:kimizuka:20211020000952p:plain

「接続」をクリックします。
これでmicro:bitの電源が入っていて、bluetoothで接続できる範囲にあれば、micro:bitが表示されます。
表示されない場合はmicro:bitを再起動してから、再度接続ボタンを押してみてください。

f:id:kimizuka:20211020001125p:plain

「ペア設定」をクリックします。
これで、Google Chromeとmicro:bitがbluetoothを介してやりとりすることができるようになり、micro:bitのLEDマトリクスにスマイルマークが表示された後、0から19までをカウントアップするはずです。

今回のサンプルでは、インタラクティブな要素がなく、わざわざPCと接続せずともmicro:bit単体でできてしまうことをやってみたわけですが、ここまでできれば、例えばPCキーボードで入力した数字をmicro:bitに表示することなどお茶の子さいさいなので、挑戦したい方は是非コードを改良してみてください。

※ Mac版のGoogle Chromeでのみ動作確認を行なっています。