1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

micro:bitAdvent Calendar 2024

Day 11

micro:bitの無線通信でBufferを送受信

Last updated at Posted at 2024-12-10

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

image.png

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

image.png

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

image.png

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

image.png

なぜ、Bufferを使って送受信するのか

Radio機能のデータ送受信において、名前と数値ではなく、Bufforを使うと次のメリットがあります。

  1. 送受信データのサイズが小さくなる
    名前の情報が送受信データに含まれなくなりますので、その分だけ、サイズが小さくなります
  2. 通信のオーバーヘッドが削減される
    通信には、送受信データだけでなく、通信のオーバーヘッドもありますので、3回分が1回分に削減されます
  3. 3つのデータをセットで送受信できる
    別々に送信すると受信時にどれかを取りこぼすことがありますが、3つのデータを1つのセットとして受信できます

特に、3つ目のメリットが重要で、複数のデータが一つのセットとして構成されている場合、その構成する要素がひとつでも欠けてしまえば(取りこぼしてしまえば)、そのデータは意味を成さなくなってしまいます。

まとめ

micro:bitは無線通信をサポートしており、MakeCode for micro:bit上で、数値名前と数値文字列の送受信といった、これらのブロックコーディングが可能です。

また、JavaScript等のテキストベースであれば、Bufferを使った効率的な送受信のコーディングも可能です。データの送受信に、このBufferを用いると、データサイズが小さくなり、通信オーバーヘッドが削減され、完全なデータ受信が保証されます。

実際に、加速度データの送受信を例に、名前と数値を使った送受信とBufferを使った送受信を試してみました。

共有プロジェクト:Bufferを使った送受信

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?