LoginSignup
7
4

More than 5 years have passed since last update.

micro:bit を Scratch 2 + Bluetooth で使う(まとめ編)

Last updated at Posted at 2018-04-11

Scratch 2 と micro:bit を Bluetooth LE でつなぐ

Scratch (スクラッチ) 2 オフラインエディタから Bluetooth LE で BBC micro:bit (マイクロビット) とやりとりする方法について「Scratch 3 までは待てない!」ということで、<調査編>で検討しました。

これをもとに、「スマイビー (Smi:be)」s2microbit-ble.pngという Electron アプリケーションを作成してみました。
(正式名称は s2microbit-ble ですが、読みにくいようなので短くしました。)

スマイビーを立ち上げておくと、Scratchから micro:bit の加速度・磁気・温度センサを読んだり、LEDマトリクスを操作したり、入出力ピンを使うことができます。ブルートゥースなのでPCからmicro:bitを遠隔操作したり、Scratchのコントローラーとして使うこともできます。(ブロックの詳しい説明)(デモプロジェクト)

Electronなので、Windows/Mac/(おそらくLinuxも)など別のOSでもビルドできます。

この記事では、システム構成、データやり取りの実装についてまとめます。

例:加速度センサを使った Scratch 2 用コントローラ

micro:bit と Scratch 2 をつなぐための構成

ざっくり図で書くと以下のような構成になっています。ヘルパーはこの中心の灰色の四角です。Electron のアプリケーションなので、メインプロセスとレンダラプロセスから成ります。今回はメインプロセスの中身について、データ受け渡し関係を中心に

  1. micro:bit の加速度センサ値を Scratch 2 のレポーターブロック 「加速度センサ X」 で受け取る
  2. Scratch 2 のコマンドブロック 「文字列を表示: Hello!」 で指定した文字列を micro:bit へ送る

についてまとめます。

system-configuration.png

s2microbit-ble のインストール方法やブロックの使用方法、Electron を使ったインストーラのビルド方法については以下で解説しています。

なお、以下で出てくるコードは、s2microbit-ble のメインプロセスのコードを一部抜粋・編集したものです。

micro:bit との Bluetooth 通信用 API

node-bbc-microbit を使っています。作者は sandeepmistry で、Node.js でBluetooth Low Energy を扱うためのモジュールとしてよく知られている noble のメインコントリビューターです。Web Bluetooth API もありますが、今回はWindows PCで動くHTTPサーバを作成する必要があるため、noble を使うことにしました。

node-bbc-microbit の APIの詳しい説明はこちらにあります。使うときは以下のように require しておきます。

main.js
const BBCMicrobit = require('bbc-microbit');

Scratch 2 との通信用HTTPサーバ

Scratch 2 オフライン版では、ブロック拡張では HTTP のリクエストを使っています。Scratch 2 からは GET してくるだけなので、ヘルパー側ではそれに対する応答を追加していく形です。今回は Express を使うことにします。詳しくはこちらの解説を参考にしてください。ポートを 50209 にしているのは、MrYsLab の s2m との互換性を残すためです。

main.js
const express = require('express');
let exapp = express();
let exserver = null;

function startHTTPServer(){
  exserver = exapp.listen(50209, function(){
    console.log("Server started... listening port " + exserver.address().port);
  });
}
// 適当な場所で
if (exserver === null) {
  startHTTPServer();
}

Electron のメイン・レンダラプロセス間通信

エラーなどはせめて DevTools の Console に表示してほしいです。メインプロセスとレンダラプロセス間の通信を使うために ipcMain を require しておきます。

main.js
// Module to control application life.
// Module to communicate with renderer process
// Module to create native browser window.
const { app, ipcMain, BrowserWindow } = require('electron');
const path = require('path');
const url = require('url');

let mainWindow;

function createWindow () {
  mainWindow = new BrowserWindow({width: 800, height: 600});

  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }));
  // 'closed' などその他の処理も追加しておく
  // 後で説明する micro:bit の discover をここでやってもよい
});

// こんな感じでコマンドプロンプトとDevToolsの両コンソールに出すようにしておきます
function logBothConsole (msg) {
  console.log(msg);
  mainWindow.webContents.send('mainmsg', msg);
}

レンダラ側では Console にメッセージを出してもらうために、index.html に以下のコードを追加しておきます。

index.html
  <body>
    ...略...
    <script>
      const { ipcRenderer } = require('electron');
      ipcRenderer.on('mainmsg', function (event, msg) {
        console.log("[main] " + msg);
      });
    </script>
  </body>

1. micro:bit の加速度センサ値を Scratch 2 のレポーターブロックで受け取る

センサ値を受け取るような Scratch のレポーターブロック(「加速度センサ X」 など)を作る流れをまとめます。センサ値を if 文で処理して、たとえば 「右にかたむいている」 のような、true/false の二値を返すようなレポーターブロック (boolean block) とすることもできます。

system-configuration_m2s.png

(1) node-bbc-microbit の examples/accelerometer-listener.js を参考にします。はじめに discover しておく必要があります。APIの説明にあるように、周辺のすべての micro:bit を見つける関数や、ID を指定する方法などがあります。今回ははじめに見つかった micro:bit をに接続することにします。

見つかれば connectAndSetUp を呼んで接続し、続いて writeAccelerometerPeriodでセンサ値の取得周期を設定します。160の単位はミリ秒です。さらに、subscribeAccelerometerで加速度の値が変化した際にイベント'accelerometerChange'が emit されるようにしておきます。他のセンサや I/O Pin の設定なども同様に行えます。

main.js
BBCMicrobit.discover( function(microbit) { // 周辺の micro:bit を見つけて
  // 接続する
  microbit.connectAndSetUp(function() {
    logBothConsole('microbit: connected');
    // 加速度センサ値の取得周期を160ミリ秒に設定し、イベントの emit を有効化
    microbit.writeAccelerometerPeriod(160, function() {
      microbit.subscribeAccelerometer(function(error) {
        logBothConsole('microbit: subscribed to accelerometer');
      });
    });
  });
});   

(2) bbc-microbit から emit されたイベントに対するコールバックを作成し、センサ値を保存しておきます。図の Variables となっている部分です。ここでは accelerometer という名前の連想配列を使っています。なお、Scratch 2 で使う際には適度な精度でよいので、toFixedを使って小数点以下二桁にします。

main.js
BBCMicrobit.discover( function(microbit) {
  microbit.on('accelerometerChange', function(x, y, z) {
    x = x.toFixed(2);
    y = y.toFixed(2);
    z = z.toFixed(2);
    accelerometer = { 'x': x, 'y': y, 'z': z };
  });
  // 以下は(1)で作成したもの
  microbit.connectAndSetUp(function() {
  ...
});

(3) Scratch 2 の GET /poll リクエストに対して、保存された値を返します。ポーリングは毎秒30回ぐらいらしいですが、ほかの処理が重いともう少し遅くなっているかもしれません。

main.js
exapp.get('/poll', function(req, res) {
  var reply = '';
  reply += 'acc_x ' + accelerometer['x'] + '\n';
  reply += 'acc_y ' + accelerometer['y'] + '\n';
  reply += 'acc_z ' + accelerometer['z'] + '\n';
  res.send(reply);
});

acc_x などの文字列は、Scratch 2 のエディタで読み込む、ブロック拡張用のファイル (.s2e) で定義しておきます(詳しくはこちら)。

2. Scratch 2 のコマンドブロックで指定した文字列を micro:bit へ送る

Scratch側から micro:bit(もしくは中間のヘルパー)に指示を出すにはコマンドブロック(「文字列を表示: Hello!」 など)を使います。

system-configuration_s2m.png

コマンドブロックの作成は非常に簡単で、Scratch 2 からの GET リクエストが来た時に処理を書いておくだけです。以下の例では、bbc-microbit API の writeLedText を使って、micro:bit の LED にスクロールテキストを表示します。20文字までというのは API の仕様です

main.js
let device = null;
// 1 (1) に出てきた microbit.connectAndSetUp のコールバックの中で
//    device = microbit;
// されていると仮定

exapp.get('/scroll/:text', function(req, res) {
  if (device) {
    // text is a string that must be 20 characters or less
    var txt = req.params.text.substring(0, 20);
    device.writeLedText(txt, function(error) {
      logBothConsole('microbit: display ' + txt);
    });
  }
  res.send('OK');
});

まとめ

Scratch 2 のブロックの拡張は思ったよりも簡単です。MrYsLab の s2m を参考にいろいろ追加してみました。一方、今回は子供のPCにすぐにインストールできるように Electron + electron-builder を使いましたが、ネイティブモジュールが絡む Electron のビルドは、慣れるまでがややこしかったです。

Scratch 3 はもう少し先に考えるとして、Scratch 2 ではひとまずこれで様子を見ます。子供も早速、なにやら手裏剣?対戦ゲーム(一人はキーボード、一人はmicro:bit)を加速度センサで作っていました。USBケーブルから解放されて、ズバッと micro:bit を振ってます!

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4