
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″に変換して書き込むという仕組みになっている。