コンパクトで扱いやすい人気のマイコンボードmicro:bit(マイクロビット)にはBLE (Bluetooth Low Energy)に対応した無線通信機能が標準で搭載されています。今回はmicro:bitとパソコンをBluetooth接続して、micro:bitをワイヤレスコントローラーとして使ってみたいと思います!
micro:bitのBLE (Bluetooth Low Energy)通信機能
micro:bit(マイクロビット)の裏面を見てみると、BBC(開発元の英国放送協会)ロゴの少し上に、「BLE ANTENNA」という表示があり、そこから左上に伸びた白い線の先に、下の写真では分かりづらいですが、凸凹状の配線のようなものが見えます。これがBLE(Bluetooth Low Energy)の通信用アンテナです。
BLE(Bluetooth Low Energy)はスピーカーやイヤフォンでよく使われている近距離での無線通信に用いられている技術である「Bluetooth」の一部で、「Low Energy」という名のとおり、低消費電力の通信モードです。それまでのBluetoothに比べ消費電力が大幅に少なく、ボタン型の電池で1年以上通信が可能な機器もあるようです。
BLEは少ないデータ量を頻繁にやり取りする使い方に向いており、遠隔で開け締めできる鍵や、押すだけで注文ができてしまうオンラインショッピング専用のボタンスイッチなど、様々なものがインターネットにつながって利用できるようになる「IoT(モノのインターネット)」を中心に、幅広く活用されています。
micro:bitの公式サイトでもBluetoothおよびBLEに関する説明が掲載されています。
“機能|micro:bit”.Micro:bit Educational Foundation.
https://microbit.org/ja/guide/features/#bluetooth
今回はこのBLEアンテナを介したBluetooth通信機能を使って、パソコン上に表示した自作の簡単なゲームを操作するためのワイヤレスコントローラーを作ります。
micro:bitをワイヤレスコントローラーにしてパソコンを操作
ゲームを操作するためのワイヤレスコントローラーを作るにあたって、具体的にどんなものを作るのかイメージをつかむため、最初に実際の動作をご覧いただこうと思います。
自機(画面中青色の四角)をmicro:bitをコントローラーにして左右に動かしながら、障害物(画面中黄色の四角)を避けて進んでいくという非常にシンプルなゲームなのですが、せっかくmicro:bitで操作を行うので、自機の移動をmicro:bitの加速度センサーを使い、micro:bitを傾けることで自機が左右に動くようにしたいと思います。
処理の流れとしては下記のようになります。
1)micro:bit側で加速度センサーの値をBluetooth通信で送信できるように準備する
2)パソコン側からmicro:bitとBluetooth接続する
3)接続ができたら、micro:bit側に接続完了表示をして、ゲーム開始
4)加速度センサーの値をパソコン側で受け取って、自機の動きに反映
5)障害物に当たってしまったら、ゲームを止めてBluetooth接続を切る
micro:bit側の設定
micro:bit側では下図のようなプログラムを作っていきます。
処理としては下記の3つとなります。
①加速度センサー(傾きで自機を操作)の値をBluetoothで送信する準備
②Bluetooth接続時の処理(接続が完了したらチェックマークを表示)
③Bluetooth接続切断時の処理(接続が切断されたら×マークを表示)
まずmicro:bit用のプログラムを作成するMakeCodeのホーム画面(https://makecode.microbit.org/#lang=ja)で「新しいプロジェクト」をクリックして、ブロックエディタを表示します。
※ブロックエディタの使用については「micro:bitで始めるプログラミング入門[基本操作〜カップラーメン専用タイマー制作]」記事も参照してください。
“micro:bitで始めるプログラミング入門[基本操作〜カップラーメン専用タイマー制作]”
https://www.pc-koubou.jp/magazine/10208
MakeCodeの初期状態ではBluetoothを使うためのブロックが収められた「Bluetooth」メニューがありませんので、画面中ほど「高度なブロック」をクリックすると表示される「拡張機能」をクリックします。
「拡張機能」画面で「bluetooth」をクリックします。
下図のようなダイアログが表示された場合は「Remove extention(s) and add bluetooth」ボタンをクリックします。
下図のように「Bluetooth」メニューが追加されました。
追加された「Bluetooth」メニューをクリックすると下図のようにBluetooth関連のブロックが表示されます。
まず、加速度センサー(傾きで自機を操作)の値をBluetoothで送信する準備をするため、一番上の「Bluetooth加速度計サービス」ブロックをエディタ上にドラッグ&ドロップします。
加速度センサーの値をBluetoothで送信するための準備は最初に1回行うだけですので、追加した「Bluetooth加速度計サービス」を「最初だけ」ブロックの中にはめ込みます。
準備ができたことが分かるように、「Bluetooth加速度計サービス」ブロックに、「基本」メニュー内「アイコンを表示」ブロックをつなぎ、表示させたいアイコンの形を設定します(下図のアイコン以外でもかまいません)。
続いて同様に「Bluetooth」メニュー内にある「Bluetooth 接続されたとき」ブロックをエディタ上にドラッグ&ドロップします。
先ほどと同様にBluetooth接続できたことがわかるよう「アイコンを表示」ブロックを「Bluetooth 接続されたとき」ブロックにはめ込み、好みのアイコンを設定します。
続いて同様に「Bluetooth 切断されたとき」ブロックをエディタ上にドラッグ&ドロップし、「アイコンを表示」ブロックをはめ込んでBluetooth接続が切断された時に表示されるアイコンを設定します。
これでmicro:bit側のプログラムは完成です。画面左下の「ダウンロード」ボタンでプログラムファイル(.hex形式)をダウンロードし、パソコンに接続したmicro:bitにコピーしておきます。
Web Bluetooth APIの設定
micro:bit側の設定を終えたらパソコン側で動作させるゲームプログラムの準備に入りますが、その前にmicro:bitとパソコンがBluetoothで通信ができるよう設定を行います。
micro:bit側では上記のプログラムだけでBluetoothでの通信が可能になりますが、パソコン側で動作させるプログラムからパソコンに備わっているBluetooth機能を利用するためには、通常は複雑な設定が必要となります。
今回は簡単な設定でBluetooth機能を扱える「Web Bluetooth API」を使用します。
「Web Bluetooth API」はWebブラウザからBluetooth機能を利用できるようにするための機能と仕様をまとめたもので、2018年11月現在ではChrome、Operaといったブラウザで利用可能です。
今回はChrome(バージョン70)でWeb Bluetooth APIを使ってみたいと思います。
ChromeでWeb Bluetooth APIを使用するには、「試験運用版のウェブプラットフォームの機能を有効にする(Experimental Web Platform features)」を有効化します。
chromeのアドレスバーに下記を入力して設定画面を表示します。
chrome://flags/#enable-experimental-web-platform-features
下図のように「Bluetooth」メニューが追加されました。
表示された設定画面の「Experimental Web Platform features」欄右にあるボタンを「Disabled」から「Enabled」に変更し、表示された「RELAUNCH NOW」ボタンをクリックするかChromeを再起動すると設定完了です。
これでmicro:bitとパソコンがBluetooth通信するための準備ができました。
パソコンで動作させるコンテンツの設定
Bluetooth通信の準備ができたら、パソコン上で動作させるゲームプログラムの準備を行います。
上記のとおり今回はWeb Bluetooth APIを使用しますので、ゲームプログラムもWebブラウザ上で動作する形で作成したいと思います。
メモ帳などのテキストエディタで新規ファイルを作成し、「main.js」というファイル名で保存します(「main」という名前は別の名前でもかまいませんが、「.js」はJavaScriptというファイル形式を示すものになりますので、変更しないようにしてください)。
作成したファイルに、まずmicro:bitとBluetooth接続する部分を記述していきます。
下記にソースコードを示します。
// 加速度サービスUUID const ACCELEROMETER_SERVICE_UUID = 'e95d0753-251d-470a-a062-fa1922dfa9a8'; // 加速度キャラクタリスティックUUID const ACCELEROMETER_CHARACTERISTICS_UUID = 'e95dca4b-251d-470a-a062-fa1922dfa9a8'; let microbit = null; let angle = null; let timer = null; //画面をクリックしたらmicro:bitとBluetooth接続する $(function() { $('.player').css('top', $(window).height()/2+'px'); $(window).click(function() { connect(); }); });
最初の4行はmicro:bitから送信される加速度センサーの値を受け取るため、あらかじめ定められているmicro:bitの加速度センサー固有の値を設定しています。
次の3行はデータの初期化、その下は画面をクリックするとmicro:bitとBluetooth接続するための記述になっています。
続いて、ゲームの中心部分であるプレイ中の動作に関する記述を以下のとおり追記していきます。
/* ----------------------------------------------- * ゲーム開始 ----------------------------------------------- */ function startGame() { timer = setInterval(function() { if (Math.random() < 0.2) { let x = Math.random() * $(window).width(); $('<div></div>') .addClass('block') .css('left', x+'px') .appendTo('body'); } let playerX = parseInt($('.player').css('left')); let playerY = parseInt($('.player').css('top')); let playerWidth = parseInt($('.player').css('width')); let playerHeight = parseInt($('.player').css('height'));; let playerCenterX = playerX + playerWidth / 2.0; let playerCenterY = playerY + playerHeight / 2.0; if (angle) { // 移動量 let move = 8; if (angle > 0 && angle < 90) { move *= 1; } if (angle > 90 && angle < 180) { move *= -1; } let x = 0; if (x >= 0 && x + playerWidth <= $(window).width()) { x = playerX + move; } $('.player').css('left', x+'px'); } $('.block').each(function(idx) { let top = parseInt($(this).css('top')) + 5; $(this).css('top', top+'px'); let left = parseInt($(this).css('left')); let width = parseInt($(this).css('width')); let height = parseInt($(this).css('height')); let centerX = left + width / 2.0; let centerY = top + height / 2.0; // 当たり判定 if (Math.abs(centerX - playerCenterX) < width/2 + playerWidth/2 && Math.abs(centerY - playerCenterY) < height/2 + playerHeight/2) { disconnect(); } if ($(window).height()/2 + 100 < top) { $(this).remove(); } }); }, 100); }
上記ではゲーム中の動きの部分である、先ほどの動画で黄色い四角として描かれていた障害物をランダムに配置して上から降ってくる動きと、青い四角で表示されていた自機をmicro:bitの傾き(=加速度センサーの値)によって左右に動かす動き、そして自機が障害物に当たったかどうかの判定を行う部分を記述しています。
続いて自機が障害物に当たり、ゲームが停止した時に表示されているブロックを全て消す処理を下記のように記述します。
/* ----------------------------------------------- * ゲーム停止 ----------------------------------------------- */ function stopGame() { clearInterval(timer); timer = null; $('.block').remove(); }
続いて最初に書いたBluetooth接続時に呼び出すペアリング処理部分を記述します。
/* ----------------------------------------------- * ペアリング開始 ----------------------------------------------- */ function connect() { console.log('connect'); // BLEデバイスをスキャンする navigator.bluetooth.requestDevice({ // acceptAllDevices: true, filters: [{ namePrefix: 'BBC micro:bit' }], optionalServices: [ACCELEROMETER_SERVICE_UUID] }) // デバイス接続する .then(device => { console.log(device); microbit = device; return device.gatt.connect(); }) // 加速度センササービスを取得する .then(server => { console.log(server); return server.getPrimaryService(ACCELEROMETER_SERVICE_UUID); }) // キャラクタリスティックを取得する .then(service => { console.log(service); return service.getCharacteristic(ACCELEROMETER_CHARACTERISTICS_UUID); }) // 加速度が変化したら指定したメソッドを呼び出す .then(characteristic => { console.log(characteristic); characteristic.startNotifications(); characteristic.addEventListener('characteristicvaluechanged', accelerometerChanged); // ゲームスタート startGame(); }) .catch(error => { console.log(error); }); }
ここに自機が障害物に当たりゲームが停止した際に呼び出すペアリング解除の記述を加えます。
/* ----------------------------------------------- * ペアリング解除 ----------------------------------------------- */ function disconnect() { console.log('disconnect'); if (!microbit || !microbit.gatt.connected) { return; } microbit.gatt.disconnect(); // ゲームストップ stopGame(); }
最後に、加速度センサーの値をゲーム上での自機操作に用いる値へ変換する部分の記述を加えて、ゲーム部分のプログラムは完成です。
/* ----------------------------------------------- * 加速度センサの値が変化したら呼び出される ----------------------------------------------- */ function accelerometerChanged(event) { // 加速度X座標 let accelX = event.target.value.getInt16(0, true)/1000.0; // 加速度Y座標 let accelY = event.target.value.getInt16(2, true)/1000.0; // 加速度Z座標 let accelZ = event.target.value.getInt16(4, true)/1000.0; // 角度 angle = Math.atan2(accelZ, accelX) * (180.0 / Math.PI); if (accelZ > 0) { angle = 360.0 - angle; } angle = Math.abs(angle); }
ゲームプログラムができたら、これをWebブラウザ(Chrome)上で表示するためのHTMLファイルを準備します。
メモ帳等のテキストエディタで新規ファイルを作成し、下記ソースコードを入力して「index.html」(「.html」以外の名前は変更してもかまいません)という名前で、上記の「main.js」と同じ場所に保存します。
<!DOCTYPE html> <html lang="ja"> <head> <!--スタイルシートで自機と障害物の見た目を規定--> <style type="text/css"> .player { width : 40px; height : 40px; background-color : #00ADFF; position : fixed; } .block { width : 40px; height : 40px; background-color : #FFF231; position : fixed; } </style> </head> <body> <!--自機の表示--> <div class="player"></div> <!--ゲーム内各要素の動きのベースとなるライブラリ読み込み--> <script src="jquery-3.3.1.min.js"></script> <!--ゲームプログラムの読み込み表示--> <script src="main.js"></script> </body> </html>
上記コメント(赤字部分)にも記載していますが、まず自機と障害物の見た目(青色/黄色の縦横40ピクセルの正方形)をスタイルシート(Webコンテンツ用の見栄え記述様式)で規定した後、本文部分で自機の表示、ゲーム内各要素の動きを簡単に記述するためのJavaScriptライブラリ*である「jQuery」というファイルの読み込み、そして先ほど作成したゲーム本体のプログラムファイルである「main.js(別のファイル名にした場合は指定したファイル名に書き換えてください)」の読み込みを行っています。
*ライブラリ…プログラムの様々な機能に関する記述をまとめたもの。ライブラリを使用すると、同じ機能を記述する場合に毎回自分で記述を書かなくても、ライブラリから使用したい機能を呼び出すだけで済むため、短い記述で多くの機能を盛り込んだプログラムを作成しやすくなる
「main.js」と「index.html」が揃ったら、上記で読み込んでいるライブラリファイル「jquery-3.3.1.min.js」ファイルをjQuery公式サイトからダウンロードします。
“Download jQuery”. The jQuery Foundation. 2018.
http://jquery.com/download/
上図赤枠部分「Download the compressed, production jQuery 3.3.1」を右クリックして、「名前を付けてリンク先を保存…」をクリックして上記「main.js」「index.html」と同じ場所に「jquery-3.3.1.min.js」を保存します。
下図のように3つのファイルが同じ場所に置かれていれば、パソコン側のコンテンツの準備は完了です。
実際に動かしてみる
いよいよ実際にmicro:bitとパソコンをBluetoothで接続し、ゲームをプレイしてみます。
プログラムをコピーしたmicro:bitの電源を入れ、パソコン上の「index.html」をChromeで開きます。下図のようにChromeのウィンドウにドラッグ&ドロップしても開くことができます。
「index.html」をChromeで開くと、ウィンドウに青い正方形が一つ表示された画面になります。
この時、micro:bitの電源が入った状態(LEDが「□」に光っている状態)でウィンドウ内をクリックすると下図のような表示が出ますので、「BBC micro:bit」を選択して「ペア設定」をクリックします。
ペアリングが完了するとウィンドウ上側から黄色い障害物の四角が落ちてきますので、micro:bitを傾けて黄色い障害物を避けて遊びます。
障害物に当たるとBluetooth接続が解除され、手元のmicro:bitには「×」が表示され、パソコン上のChromeウィンドウでは自機だけが表示された状態になります。
再度ウィンドウ内をクリックしてペアリングを行うと、ゲームが再開します。
最初にも載せましたが、ペアリング〜障害物に当たるところまでの模様を動画に収めていますので、もう一度ご覧ください。
まとめ
今回はmicro:bitのBLE(Bluetooth LE)通信機能を用いて、micro:bitとパソコンの間でデータのやり取りを行い、実際にゲームのワイヤレスコントローラーという形で操作をしてみました。
今回使用した「Web Bluetooth API」はまだ対応ブラウザが少なく、micro:bitとパソコン間で本格的なBluetooth通信を行うために高度な設定が必要ですが、パソコン側での通信部分さえ準備できれば、micro:bit側には特別な設定なく、Bluetoothを用いたデータのやり取りが可能です。
micro:bitはコンパクトで軽量かつ複数のセンサーも備えているので、ぜひこのBLE通信機能にアイデアを組み合わせて、便利な活用方法を考えてみてください。
石郷祐介
大学卒業後、公設研究機関勤務を経て、「情報科学芸術大学院大学[IAMAS]」に入学。
専門学校講師を経て、企業の研究開発をコンセプトから開発まで支援する「合同会社4D Pocket」代表、エンジニアを養成するフリースクール「一般社団法人HOPTER TECH SCHOOL」代表理事、「名古屋文理大学」及び「名古屋造形大学」非常勤講師。