micro:bitの無線通信
micro:bitには、無線通信のRadio機能が備わっており、MakeCode for micro:bitでのブロックコーディングが可能です。
基本的な送受信
送受信に関して次のブロックを使用できます。
# | 種類 | 送信(ブロードキャスト) | 受信(イベント) |
---|---|---|---|
1 | 数値 | radio.sendNumber() | radio.onReceivedNumber() |
2 | 名前と数値 | radio.sendValue() | radio.onReceivedValue() |
3 | 文字列 | radio.sendString() | radio.onReceivedString() |
JavaScript
let v = 0
radio.onReceivedNumber(function (receivedNumber) {
console.log("数値: " + receivedNumber)
})
radio.onReceivedValue(function (name, value) {
console.log(name + ": " + value)
})
radio.onReceivedString(function (receivedString) {
console.log("文字列: " + receivedString)
})
basic.forever(function () {
v = randint(0, 10)
basic.pause(1000)
radio.sendNumber(v)
basic.pause(1000)
radio.sendValue("v", v)
basic.pause(1000)
radio.sendString("v=" + v)
})
Blocks
Radioの送受信
送信は、ブロードキャストされ、他のすべてのmicro:bitで受信可能です。
送信された情報は、イベントとして受信することができます。
送受信において、そのグループIDが同一であれば、イベントが発生します。
隠されたBuffer送受信
Radio機能では、Bufferの送受信も実装されていますが、そのブロックの定義で非表示としてブロックが隠されています。
その為、ドラッグアンドドロップでは、コーディングできませんので、JavaScriptモードで、テキストベースのコーディングをします。
# | 種類 | 送信(ブロードキャスト) | 受信(イベント) |
---|---|---|---|
1 | Buffer | radio.sendBuffer() | radio.onReceivedBuffer() |
JavaScript
radio.onReceivedBuffer(function (receivedBuffer) {
console.log("buffer(length): " + receivedBuffer.length)
})
basic.forever(function () {
basic.pause(1000)
let buffer = Buffer.create(12)
radio.sendBuffer(buffer)
})
Blocks
Buffer(バッファ)とは
Buffer: temporary part of memory used to transfer data between your program and devices - https://makecode.microbit.org/types/buffer
バイト配列のデータであり、Radio機能の場合、最大19バイトのデータを一度に送受信できます。
次のコードは、12バイト長のBufferを生成しています。
let buffer = Buffer.create(12)
コーディング例:加速度データの送受信
加速度データ(x,y,z)の送受信を例に、基本的な方法での送受信とBufferを使った送受信とをコーディングしてみます。
基本的な方法での送受信
まずは、基本的な方法として、名前と数値を使った送受信を試してみます。
送受信データの設計
加速度 | 名前 | 数値 |
---|---|---|
加速度x | x | (X軸の加速度) |
加速度y | y | (Y軸の加速度) |
加速度z | z | (Z軸の加速度) |
※ 役割のルール: Aボタンを押した方が、送信側
JavaScript
let K = 0
input.onButtonPressed(Button.A, function () {
K = 9.8 / 1023
})
radio.onReceivedValue(function (name, value) {
if ("x" == name) {
console.log("x: " + value)
} else if ("y" == name) {
console.log("y: " + value)
} else if ("z" == name) {
console.log("z: " + value)
} else {
console.log("???")
}
})
basic.forever(function () {
if (0 != K) {
radio.sendValue("x", K * input.acceleration(Dimension.X))
radio.sendValue("y", K * input.acceleration(Dimension.Y))
radio.sendValue("z", K * input.acceleration(Dimension.Z))
}
})
Blocks
Aボタンを押した方が送信側
無線通信を開始すると、MakeCode for micro:bitのシミュレータ上にもうひとつ別のmicro:bitが現れ、Radio機能をシミュレーションすることができます。ただし、同一のプロジェクトが実行されますので、Aボタンを押しすことにより、送信側を決定しています(変数Kの値が0以外になると送信側)。
Bufferを使った送受信
名前と数値を使って、X軸、Y軸、Z軸の加速度データを順に送信し、順に受信しましたが、Bufferに3つのデータを詰め込めば、一括で送信と受信ができます。
Bufferにデータを詰め込むには、送受信するデータのフォーマットとサイズ、オフセットを確認する必要があります。
加速度データは、整数ではなく小数として送受信したいので、32ビットのFloat型とします。エンディアンは、リトルエンディアンです。Float32LE
のサイズは、4バイトです。加速度x,y,zの順に詰め込むので、オフセットは、4バイトずつずらしています。
送受信データの設計
# | 加速度 | フォーマット | サイズ | オフセット |
---|---|---|---|---|
1 | 加速度x | Float32LE | 4バイト | 0 |
2 | 加速度y | Float32LE | 4バイト | 4 |
3 | 加速度z | Float32LE | 4バイト | 8 |
※ Bufferのサイズは、3つのサイズを合計した12バイト長が必要
ビッグエンディアンとリトルエンディアン
ビッグエンディアン(big endian)とリトルエンディアン(little endian)は、そのサイズが大きい・小さいという意味ではありません。複数バイトからなる値をバイト配列に収める際の方式(順序)を意味するものです。
micro:bitでは、リトルエンディアンが採用されていますので、フォーマットもリトルエンディアン(LE)を選択しました。しかし、ビッグエンディアンを選択しても構いません。送受信の双方で同じ方式を選択すればよいのです。
JavaScript
input.onButtonPressed(Button.A, function () {
K = 9.8 / 1023
})
radio.onReceivedBuffer(function (receivedBuffer) {
if (12 == receivedBuffer.length) {
console.log("x: " + receivedBuffer.getNumber(NumberFormat.Float32LE, 0))
console.log("y: " + receivedBuffer.getNumber(NumberFormat.Float32LE, 4))
console.log("z: " + receivedBuffer.getNumber(NumberFormat.Float32LE, 8))
} else {
console.log("???")
}
})
let K = 0
let buffer = Buffer.create(12)
basic.forever(function () {
if (0 != K) {
buffer.setNumber(NumberFormat.Float32LE, 0, K * input.acceleration(Dimension.X))
buffer.setNumber(NumberFormat.Float32LE, 4, K * input.acceleration(Dimension.Y))
buffer.setNumber(NumberFormat.Float32LE, 8, K * input.acceleration(Dimension.Z))
radio.sendBuffer(buffer)
}
})
Blocks
なぜ、Bufferを使って送受信するのか
Radio機能のデータ送受信において、名前と数値ではなく、Bufforを使うと次のメリットがあります。
- 送受信データのサイズが小さくなる
名前の情報が送受信データに含まれなくなりますので、その分だけ、サイズが小さくなります - 通信のオーバーヘッドが削減される
通信には、送受信データだけでなく、通信のオーバーヘッドもありますので、3回分が1回分に削減されます - 3つのデータをセットで送受信できる
別々に送信すると受信時にどれかを取りこぼすことがありますが、3つのデータを1つのセットとして受信できます
特に、3つ目のメリットが重要で、複数のデータが一つのセットとして構成されている場合、その構成する要素がひとつでも欠けてしまえば(取りこぼしてしまえば)、そのデータは意味を成さなくなってしまいます。
まとめ
micro:bitは無線通信をサポートしており、MakeCode for micro:bit上で、数値
、名前と数値
、文字列
の送受信といった、これらのブロックコーディングが可能です。
また、JavaScript等のテキストベースであれば、Buffer
を使った効率的な送受信のコーディングも可能です。データの送受信に、このBuffer
を用いると、データサイズが小さくなり、通信オーバーヘッドが削減され、完全なデータ受信が保証されます。
実際に、加速度データの送受信を例に、名前と数値
を使った送受信とBuffer
を使った送受信を試してみました。
共有プロジェクト:Bufferを使った送受信