Help us understand the problem. What is going on with this article?

micro:bitとブラウザ間で文字列をやり取りするまでの手順

micro:bitとブラウザ間で文字列をやり取りするまでの手順

by nakazawaken1
1 / 61

目的

スマホ等からWebBluetoothを使って micro:bit に文字列を送信、
また、逆に micro:bit からスマホ等に文字列を送信するための手順をまとめています。


使用するもの

  • micro:bit
  • USB ケーブル
  • WebBluetooth 対応ブラウザ(2020年1月時点でPCまたはAndroidのChrome)
  • テキストエディタ

micro:bit 側のプログラム作成


まずは Bluetooth に接続、切断されたことがわかるようにしてみます。


https://makecode.microbit.org にアクセスします。
image.png


新しいプロジェクトを選択します。
image.png


右上の歯車をクリックし、プロジェクトの設定を選択します。
image.png
※日本語表示になっていない場合は、Language から、日本語を選択します。
image.png
image.png


名前を UART にし、No Pairing Required: Anyone can connect via Bluetooth. を有効にします。
image.png
※これで WebBluetoothから面倒な手続きなしで micro:bit に接続できるようになります。


ブロックプログラミングを始めます。
image.png


高度なブロックを開きます。
image.png


拡張機能を選択します。
image.png


bluetooth を選択します。
image.png


「一部の拡張機能を削除してbluetoothを追加する」ボタンを押します。
image.png


bluetooth - その他 のなかの「Bluetooth UARTサービス」を「最初だけ」ブロックの中に配置します。
image.png
image.png


接続されていない状態がわかるように、基本 - アイコン から目を閉じた顔マークを配置します。
image.png
image.png


Bluetooth が接続されたことがわかるように、Bluetooth のなかの 「Bluetooth 接続されたとき」と笑った顔マークを配置します。
image.png
image.png


Bluetooth が切断されたことがわかるように、「Bluetooth 接続が切断されたとき」と目を閉じた顔マークを配置します。(顔マークは先に配置したものを右クリックで複製すると早いです。)
image.png
image.png


作成したプログラムの書き込み


右上歯車ボタンを押し、「デバイスを接続する」を選択します。
image.png


さらに、「デバイスを接続する」を選択します。
image.png


次のようなポップアップが表示されるので、 micro:bit を選択して、「接続」ボタンを押します。
image.png
※これで、画面左下の「ダウンロード」ボタンを押すと、作成したプログラムが直接 micro:bit に書き込まれるようになります。


画面左下の「ダウンロード」ボタンを押し、プログラムを書き込みます。
image.png
書き込みが成功すれば microbit に顔マークが表示されます。
image.png

ブラウザ側のプログラム作成


テキストエディタを起動して、次の内容を入力します。

<!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 という名前で保存し、ブラウザで開きます。

image.png


「接続」ボタンを押すと、次のようなポップアップが表示されるので、 micro:bit を選択して、「ペア設定」ボタンを押します。
image.png


うまく行けば、micro:bit の顔の表示が変わり、ブラウザのボタンは切断ボタンに変わります。
image.png
image.png


切断ボタンを押すと、顔の表示が戻ります。
image.png


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 から変更された部分は次のとおりです。
image.png
image.png


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側のプログラム変更


「ボタンが押されたとき」のブロックを追加します。
image.png
image.png


「Bluetooth UART 文字列を書き出す」を追加します。
image.png
image.png


書き出す内容を、 Button A pressed. とします。
image.png


左下「ダウンロードボタン」を押して、micro:bit に変更したプログラムを書き込みます。


micro:bit → ブラウザ 文字送信動作確認


ブラウザで uart2.html を開きます。


接続ボタンを押します。


micro:bit の A ボタンを押します。


ブラウザの受信内容に、 Button A pressed. と表示されれば成功です。
image.png


ブラウザから micro:bit へ文字を送信する

microbit側のプログラム変更


「Bluetooth データを受信したとき」のブロックを追加します。
image.png
image.png


「文字列を表示」ブロックを追加します。
image.png
image.png


表示内容を、「Bluetooth UART つぎのいずれかの文字の手前まで読み取る」にします。
image.png
image.png


ブラウザ側のプログラム変更


次の内容で、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>

※ uart2.html からの変更箇所は次のとおりです。
image.png
image.png


service.getCharacteristic(UUID_RX_CHAR_CHARACTERISTIC) で micro:bit の受信機能のハンドルを取得し、
rx.writeValue でブラウザから文字列を送信しています。


ブラウザ → micro:bit 文字送信動作確認


ブラウザで uart3.html を開きます。
image.png


接続ボタンを押して接続します。
image.png
※接続が成功すれば、送信ボタンが押せるようになります。


送信ボタンを押します。成功すると、micro:bit に test という文字がスクロールで表示されます。
output.gif


以上で、ブラウザと micro:bit 間の文字列送信ができるようになりました。

これをベースに、ブラウザからコマンドを送って、micro:bit にそのコマンドを判別していろいろな動作をさせたり、
micro:bit からセンサーデータをブラウザに送ってブラウザ側でグラフにしたりすることができそうです。


おまけ


計測開始を押すと、micro:bitの光センサーの値が、1秒毎にブラウザに送られてくるプログラムを作ったので共有します。

ブラウザ側
https://programpark.jp/microbit_uart.html

micro:bit側
https://makecode.microbit.org/_gJP7Ab3K7hH9


おわりに

日本語は送受信できませんでした。
1度の送信は20文字までのようです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした