目的
スマホ等からWebBluetoothを使って micro:bit に文字列を送信、
また、逆に micro:bit からスマホ等に文字列を送信するための手順をまとめています。
使用するもの
- micro:bit
- USB ケーブル
- WebBluetooth 対応ブラウザ(2020年1月時点でPCまたはAndroidのChrome)
- テキストエディタ
micro:bit 側のプログラム作成
まずは Bluetooth に接続、切断されたことがわかるようにしてみます。
https://makecode.microbit.org にアクセスします。
右上の歯車をクリックし、プロジェクトの設定を選択します。
※日本語表示になっていない場合は、Language から、日本語を選択します。
名前を UART にし、No Pairing Required: Anyone can connect via Bluetooth. を有効にします。
※これで WebBluetoothから面倒な手続きなしで micro:bit に接続できるようになります。
「一部の拡張機能を削除してbluetoothを追加する」ボタンを押します。
bluetooth - その他 のなかの「Bluetooth UARTサービス」を「最初だけ」ブロックの中に配置します。
接続されていない状態がわかるように、基本 - アイコン から目を閉じた顔マークを配置します。
Bluetooth が接続されたことがわかるように、Bluetooth のなかの 「Bluetooth 接続されたとき」と笑った顔マークを配置します。
Bluetooth が切断されたことがわかるように、「Bluetooth 接続が切断されたとき」と目を閉じた顔マークを配置します。(顔マークは先に配置したものを右クリックで複製すると早いです。)
作成したプログラムの書き込み
次のようなポップアップが表示されるので、 micro:bit を選択して、「接続」ボタンを押します。
※これで、画面左下の「ダウンロード」ボタンを押すと、作成したプログラムが直接 micro:bit に書き込まれるようになります。
画面左下の「ダウンロード」ボタンを押し、プログラムを書き込みます。
書き込みが成功すれば microbit に顔マークが表示されます。
ブラウザ側のプログラム作成
テキストエディタを起動して、次の内容を入力します。
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Micro:bit UART 通信</title>
<style type="text/css">
* {
font-size: 3vmin;
padding: 3vmin;
}
body {
text-align: center;
}
</style>
<h1>Micro:bit UART 通信</h1>
<form>
<button type="button" id="connect">接続</button>
</form>
<script>
const UUID_UART_SERVICE = '6e400001-b5a3-f393-e0a9-e50e24dcca9e'
let gatt = null
const update = connected => {
document.getElementById('connect').textContent = connected ? '切断' : '接続'
}
document.getElementById('connect').addEventListener('click', e => {
if(!(navigator.bluetooth && navigator.bluetooth.requestDevice)) {
alert('WebBluetooth に未対応のブラウザです。')
return
}
if (document.getElementById('connect').textContent == '接続') {
navigator.bluetooth.requestDevice({
filters: [
{ services: [UUID_UART_SERVICE] },
{ namePrefix: 'BBC micro:bit' }
]
}).then(device => {
gatt = device.gatt
return gatt.connect()
}).then(server => {
update(true)
}).catch(function(err) {
alert(err)
})
} else {
gatt.disconnect()
update(false)
}
})
</script>
navigator.bluetooth.requestDevice で micro:bit を探します。
device.gatt が通信用のハンドルのようなものです。
gatt.connect で接続します。
接続が成功したら、ボタンを切断に変えるようにしています。
切断するのは gatt.disconnect です。
Bluetooth 接続の動作確認
作成したファイルを uart1.html という名前で保存し、ブラウザで開きます。
「接続」ボタンを押すと、次のようなポップアップが表示されるので、 micro:bit を選択して、「ペア設定」ボタンを押します。
うまく行けば、micro:bit の顔の表示が変わり、ブラウザのボタンは切断ボタンに変わります。
micro:bit からブラウザへ文字を送信する
ブラウザ側のプログラム変更
下記内容で uart2.html ファイルを作成し、ブラウザで開きます。
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Micro:bit UART 通信</title>
<style type="text/css">
* {
font-size: 3vmin;
padding: 3vmin;
}
body {
text-align: center;
}
textarea {
vertical-align: middle;
}
</style>
<h1>Micro:bit UART 通信</h1>
<form>
<div>
<button type="button" id="connect">接続</button>
受信内容<textarea id="recieve_text"></textarea>
</div>
</form>
<script>
const UUID_UART_SERVICE = '6e400001-b5a3-f393-e0a9-e50e24dcca9e'
const UUID_TX_CHAR_CHARACTERISTIC = '6e400002-b5a3-f393-e0a9-e50e24dcca9e'
let gatt = null
let tx = null
const update = connected => {
document.getElementById('connect').textContent = connected ? '切断' : '接続'
}
document.getElementById('connect').addEventListener('click', e => {
if(!(navigator.bluetooth && navigator.bluetooth.requestDevice)) {
alert('WebBluetooth に未対応のブラウザです。')
return
}
if (document.getElementById('connect').textContent == '接続') {
navigator.bluetooth.requestDevice({
filters: [
{ services: [UUID_UART_SERVICE] },
{ namePrefix: 'BBC micro:bit' }
]
}).then(device => {
gatt = device.gatt
return gatt.connect()
}).then(server =>
server.getPrimaryService(UUID_UART_SERVICE)
).then(service =>
service.getCharacteristic(UUID_TX_CHAR_CHARACTERISTIC)
).then(characteristic => {
tx = characteristic
tx.startNotifications()
tx.addEventListener('characteristicvaluechanged', e => {
const text = new TextDecoder().decode(e.target.value)
document.getElementById('recieve_text').value = text + document.getElementById('recieve_text').value
})
update(true)
}).catch(function(err) {
alert(err)
})
} else {
gatt.disconnect()
update(false)
}
})
</script>
※uart1.html から変更された部分は次のとおりです。
uart1から増えた処理は、gatt を取得したあとに、
server.getPrimaryService(UUID_UART_SERVICE) で micro:bit の UART 機能にアクセスし、
service.getCharacteristic(UUID_TX_CHAR_CHARACTERISTIC) で micro:bit の送信機能のハンドルを取得しています。
そして、tx.addEventListener で micro:bit が送信したデータを受け取る処理を登録し、
tx.startNotifications で受信を開始しています。
microbit側のプログラム変更
「Bluetooth UART 文字列を書き出す」を追加します。
書き出す内容を、 Button A pressed. とします。
左下「ダウンロードボタン」を押して、micro:bit に変更したプログラムを書き込みます。
micro:bit → ブラウザ 文字送信動作確認
ブラウザで uart2.html を開きます。
接続ボタンを押します。
micro:bit の A ボタンを押します。
ブラウザの受信内容に、 Button A pressed. と表示されれば成功です。
ブラウザから micro:bit へ文字を送信する
microbit側のプログラム変更
「Bluetooth データを受信したとき」のブロックを追加します。
表示内容を、「Bluetooth UART つぎのいずれかの文字の手前まで読み取る」にします。
ブラウザ側のプログラム変更
次の内容で、uart3.html を作成します。
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Micro:bit UART 通信</title>
<style type="text/css">
* {
font-size: 3vmin;
padding: 3vmin;
}
body {
text-align: center;
}
textarea {
vertical-align: middle;
}
</style>
<h1>Micro:bit UART 通信</h1>
<form>
<div>
<button type="button" id="connect">接続</button>
受信内容<textarea id="recieve_text"></textarea>
</div>
<div>
送信内容
<input type="text" id="send_text" value="test">
<button type="button" id="send" disabled>送信</button>
</div>
</form>
<script>
const UUID_UART_SERVICE = '6e400001-b5a3-f393-e0a9-e50e24dcca9e'
const UUID_TX_CHAR_CHARACTERISTIC = '6e400002-b5a3-f393-e0a9-e50e24dcca9e'
const UUID_RX_CHAR_CHARACTERISTIC = '6e400003-b5a3-f393-e0a9-e50e24dcca9e'
let gatt = null
let tx = null
let rx = null
const update = connected => {
document.getElementById('connect').textContent = connected ? '切断' : '接続'
document.getElementById('send').disabled = !connected
}
const send = text => rx.writeValue(new TextEncoder().encode(text + '\n'))
document.getElementById('connect').addEventListener('click', e => {
if(!(navigator.bluetooth && navigator.bluetooth.requestDevice)) {
alert('WebBluetooth に未対応のブラウザです。')
return
}
if (document.getElementById('connect').textContent == '接続') {
navigator.bluetooth.requestDevice({
filters: [
{ services: [UUID_UART_SERVICE] },
{ namePrefix: 'BBC micro:bit' }
]
}).then(device => {
gatt = device.gatt
return gatt.connect()
}).then(server =>
server.getPrimaryService(UUID_UART_SERVICE)
).then(service =>
Promise.all([
service.getCharacteristic(UUID_TX_CHAR_CHARACTERISTIC),
service.getCharacteristic(UUID_RX_CHAR_CHARACTERISTIC)])
).then(characteristics => {
tx = characteristics[0]
tx.startNotifications()
tx.addEventListener('characteristicvaluechanged', e => {
const text = new TextDecoder().decode(e.target.value)
document.getElementById('recieve_text').value = text + document.getElementById('recieve_text').value
})
rx = characteristics[1]
update(true)
}).catch(function(err) {
alert(err)
})
} else {
gatt.disconnect()
update(false)
}
})
document.getElementById('send').addEventListener('click', e => {
send(document.getElementById('send_text').value)
})
</script>
service.getCharacteristic(UUID_RX_CHAR_CHARACTERISTIC) で micro:bit の受信機能のハンドルを取得し、
rx.writeValue でブラウザから文字列を送信しています。
ブラウザ → micro:bit 文字送信動作確認
接続ボタンを押して接続します。
※接続が成功すれば、送信ボタンが押せるようになります。
送信ボタンを押します。成功すると、micro:bit に test という文字がスクロールで表示されます。
以上で、ブラウザと micro:bit 間の文字列送信ができるようになりました。
これをベースに、ブラウザからコマンドを送って、micro:bit にそのコマンドを判別していろいろな動作をさせたり、
micro:bit からセンサーデータをブラウザに送ってブラウザ側でグラフにしたりすることができそうです。
おまけ
計測開始を押すと、micro:bitの光センサーの値が、1秒毎にブラウザに送られてくるプログラムを作ったので共有します。
ブラウザ側
https://programpark.jp/microbit_uart.html
micro:bit側
https://makecode.microbit.org/_gJP7Ab3K7hH9
おわりに
日本語は送受信できませんでした。
1度の送信は20文字までのようです。