Micro:bit + Web Bluetooth API でLED Matrixをチカチカさせる。
Web Blutooth API + Micro:bit LED matrix #microbit #chibibit pic.twitter.com/CGoAyFm8A7
— 清水正行 (@_shimizu) September 19, 2017
概要
Web bluetooth APIを使ってmaicro:bitのLED on/offをコントロールする。
事前準備
- ペアリングのセキュリティを解除し、すべてのBLEサービスを有効にするために以下の作業を行う必要がある。参考:Flashing micro:bit firmware
- hexファイルをダウンロードする。
- USBケーブルを使用してマイクロビットをPCに接続。
- hexファイルをmicro:bitディスクドライブにコピーする。
- micro:bitを再起動する。
- LEDにドットが表示されるので、傾けて円を描く(キャリブレーション)
- サービス/キャラクタリスティックのUUIDを調べておく。
ここで確認できます。
サンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>Micro:bit LED MATRIX送信</title> <style> form { margin-top:1em; } label{ display:inline-block; height:10px; width:10px; cursor: pointer; padding:5px; border: 1px solid #434343; border-radius: 5px; background-color:gray; } input{ display: none; } .check_box:checked + .label { background-color: red; } </style> </head> <body> <h1>Micro:bit LED MATRIX送信</h1> <button id="connect">接続</button> <button id="disconnect">切断</button> <br> <form> <div> <input type="checkbox" class="check_box" id="cb1-1" name="cb1-1" /> <label class="label" for="cb1-1"></label> <input type="checkbox" class="check_box" id="cb1-2" name="cb1-2" /> <label class="label" for="cb1-2"></label> <input type="checkbox" class="check_box" id="cb1-3" name="cb1-3" /> <label class="label" for="cb1-3"></label><input type="checkbox" class="check_box" id="cb1-4" name="cb1-4" /> <label class="label" for="cb1-4"></label> <input type="checkbox" class="check_box" id="cb1-5" name="cb1-5" /> <label class="label" for="cb1-5"></label> </div> <div> <input type="checkbox" class="check_box" id="cb2-1" name="cb2-1" /> <label class="label" for="cb2-1"></label> <input type="checkbox" class="check_box" id="cb2-2" name="cb2-2" /> <label class="label" for="cb2-2"></label> <input type="checkbox" class="check_box" id="cb2-3" name="cb2-3" /> <label class="label" for="cb2-3"></label><input type="checkbox" class="check_box" id="cb2-4" name="cb2-4" /> <label class="label" for="cb2-4"></label> <input type="checkbox" class="check_box" id="cb2-5" name="cb2-5" /> <label class="label" for="cb2-5"></label> </div> <div> <input type="checkbox" class="check_box" id="cb3-1" name="cb3-1" /> <label class="label" for="cb3-1"></label> <input type="checkbox" class="check_box" id="cb3-2" name="cb3-2" /> <label class="label" for="cb3-2"></label> <input type="checkbox" class="check_box" id="cb3-3" name="cb3-3" /> <label class="label" for="cb3-3"></label><input type="checkbox" class="check_box" id="cb3-4" name="cb3-4" /> <label class="label" for="cb3-4"></label> <input type="checkbox" class="check_box" id="cb3-5" name="cb3-5" /> <label class="label" for="cb3-5"></label> </div> <div> <input type="checkbox" class="check_box" id="cb4-1" name="cb4-1" /> <label class="label" for="cb4-1"></label> <input type="checkbox" class="check_box" id="cb4-2" name="cb4-2" /> <label class="label" for="cb4-2"></label> <input type="checkbox" class="check_box" id="cb4-3" name="cb4-3" /> <label class="label" for="cb4-3"></label><input type="checkbox" class="check_box" id="cb4-4" name="cb4-4" /> <label class="label" for="cb4-4"></label> <input type="checkbox" class="check_box" id="cb4-5" name="cb4-5" /> <label class="label" for="cb4-5"></label> </div> <div> <input type="checkbox" class="check_box" id="cb5-1" name="cb5-1" /> <label class="label" for="cb5-1"></label> <input type="checkbox" class="check_box" id="cb5-2" name="cb5-2" /> <label class="label" for="cb5-2"></label> <input type="checkbox" class="check_box" id="cb5-3" name="cb5-3" /> <label class="label" for="cb5-3"></label><input type="checkbox" class="check_box" id="cb5-4" name="cb5-4" /> <label class="label" for="cb5-4"></label> <input type="checkbox" class="check_box" id="cb5-5" name="cb5-5" /> <label class="label" for="cb5-5"></label> </div> </form> <script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script> <script src="index.js"></script> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
var bluetoothDevice; var characteristic; //chibi:bit BLE UUID var LED_SERVICE_UUID = 'e95dd91d-251d-470a-a062-fa1922dfa9a8'; var LED_MATRIX_CHARACTERISTIC_UUID = 'E95D7B77-251D-470A-A062-FA1922DFA9A8'.toLowerCase(); //ボタンイベントリスナー d3.select("#connect").on("click", connect); d3.select("#disconnect").on("click", disconnect); d3.select("#send").on("click", sendMessage); //chibi:bitに接続する function connect() { let options = {}; //options.acceptAllDevices = true; options.filters = [ {services: [LED_SERVICE_UUID]}, {name: "BBC micro:bit [vaget]"} ]; navigator.bluetooth.requestDevice(options) .then(device => { bluetoothDevice = device; console.log("device", device); return device.gatt.connect(); }) .then(server =>{ console.log("server", server) return server.getPrimaryService(LED_SERVICE_UUID); }) .then(service => { console.log("service", service) return service.getCharacteristic(LED_MATRIX_CHARACTERISTIC_UUID) }) .then(chara => { console.log("characteristic", chara) alert("BLE接続が完了しました。"); characteristic = chara; }) .catch(error => { console.log(error); }); } d3.select("form").on("change",sendMessage) //LEDに表示するメッセージを送信 function sendMessage() { if (!bluetoothDevice || !bluetoothDevice.gatt.connected || !characteristic) return ; var input = d3.select(this).selectAll("input"); var values = []; input.each(function(d){ values.push({id:this.id, value:this.checked ? "1" : "0"}) }); var nested = d3.nest() .rollup(function(d){ return d.reduce(function(a, b) { return { value:a.value + b.value } ; })}) .key(function(d){ return d.id.split("-")[0] }) .entries(values); var buffer = new Uint8Array(nested.length); nested.forEach(function(d,i){ buffer[i] = parseInt(d.value.value, 2); }); characteristic.writeValue(buffer); } //BEL切断処理 function disconnect() { if (!bluetoothDevice || !bluetoothDevice.gatt.connected) return ; bluetoothDevice.gatt.disconnect(); alert("BLE接続を切断しました。") } |
ポイント
キャラクタリスティックにアクセスするまでの手順は、以前の記事と変わらない。
LED Matrix Stateへの書き込みには、8 ビット符号なし整数値の配列(ArrayBuffer)を準備し、そこへ5桁の2進数で書き込む。
例えば1行目の一番右のLEDをonにするなら以下。
1 2 |
var buffer = new Uint8Array(5); buffer[0] = perseInt("00001", 2); |
5行目の一番左のLEDならこんな感じ
1 2 |
var buffer = new Uint8Array(5); buffer[4] = perseInt("10000", 2); |
上記サンプルコードでは、チェックボックスを並べたUIを作成し、checked trueを”1″に、falseを”0″に変換して書き込むという仕組みになっている。