XBeeモジュールの使い方(画像転送)


  今回はルータXBeeからコーディネータXBeeに画像を転送する方法について解説します。今回解説する方法はZigbee3.0又はDigiMesh2.4のいずれのファームウェアでも動作します。今まではエンドデバイスXBeeやルータXBeeからコーディネータXBeeにセンサデータを送信する方法について解説してきましたが、制限はあるものの画像データの送信も可能です。以下のZigbeeファームウェアの場合の画像データを転送時の制限事項について説明します。

1.制限事項

(1)プロトコルの制約

 Zigbeeのプロトコル的な制約としては、最大ペイロードサイズ(MTU)がZigbeeでは、1フレームあたり最大で約72〜100バイト程度です。AES暗号有効時はさらに減少します。従って、MicroPythonでxbee.transmit()を実行する場合は約72バイト以下が安全圏と思われます。また、トランスミッション速度に関してはZigbeeの空間転送速度の最大値は理論値で250 kbpsですが実効速度は10〜30 kbps程度となります。 

(2)転送速度

 次に転送速度の実効値の目安を見積もってみます。画像データを分割して64バイト毎にチャンク送信し、utime.sleep(0.1)で0.1sのスリープ含んだ送信をした場合を想定すると、転送時間は以下のようになります。

画像サイズチャンク数転送時間の概算
4KB64約6秒
16KB256約25秒
64KB1024約90〜100秒
100KB1600約2分40秒程度

(3)ファイルサイズの上限

 XBeeの/flashのストレージ容量は総容量が約1MB(1024KB)ですが、実際に使用可能なユーザ領域(空き容量)は約440KB程度です。しかし、このユーザ領域はMicroPython ランタイムやファームウェア自身が使用しているため、全てを自由に使うことはできません。実効的には100KB 程度までがMicroPythonでZigBeeファームウェアを使用した際に安定して送信可能な値と考えられます。

2.画像転送

 そこで今回の解説では、以下の64×64ピクセルのモノクロ画像(ファイル名:MonaLisa.png)を例にコーディネータXBeeへの転送を試みます。

 画像を送信するルータXBeeのMicroPythonのサンプルコードを以下に示します。 MicroPython Terminalでエンターを押してCtrl+Fで1^^^のプロンプトにしてから、マウスの右クリックでCopyを選択して貼り付けます。その後、Ctrl+Dでコンパイルして、スタートで自動実行に同意する「Y」を押して、一旦このままにしておきます。File System Managerでコンパイルされた実行ファイルmain.mpyが生成されています。ここで、File System Managerを用いて/flashにMonaLisa.pngを書き込んでおきます。

import xbee
import os
import utime

COORD_ADDR = b'\x00\x13\xA2\x00\x41\xAE\x36\x69'
CHUNK_SIZE = 64
FILE_PATH = "MonaLisa.png"

def send_file():
    if FILE_PATH not in os.listdir():
        print("No file!")
        return

    with open(FILE_PATH, "rb") as f:
        while True:
            chunk = f.read(CHUNK_SIZE)
            if not chunk:
                break
            xbee.transmit(COORD_ADDR, chunk)
            utime.sleep(0.1)

    # 送信完了後に終了チャンクを送信
    xbee.transmit(COORD_ADDR, b"__EOF__")
    print("Send complete")

send_file()

 画像を受信するコーディネータXBeeのMicroPythonのサンプルコードを以下に示します。 ルータXBeeの場合と同様にMicroPython Terminalでエンターを押してコンパイルし、Ctrl+Rであらかじめ実行しておきます。

from xbee import receive
import os
import time

FILE_PATH = "MonaLisa.png"
RECEIVED_CHUNKS = []

def receive_file_loop():
    while True:
        pkt = receive()
        if pkt:
            payload = pkt['payload']
            if len(payload) < 1:
                print("Invalid payload")
                continue

            # 終了チャンクの検出
            if payload == b"__EOF__":
                print("EOF detected. Saving file.")
                save_file()
                continue

            RECEIVED_CHUNKS.append(payload)
            print("Received chunk. Total:", len(RECEIVED_CHUNKS))

        #time.sleep(0.1)

def save_file():
    with open(FILE_PATH, "wb") as f:
        for chunk in RECEIVED_CHUNKS:
            f.write(chunk)
    print("File save completed!:", FILE_PATH)
    RECEIVED_CHUNKS.clear()

receive_file_loop()

 コーディネータXBeeのコードが実行されていることを確認してから、ルータXBeeからCtrl+Rでコードを実行すると以下のようになります。

 コーディネータXBeeのMicroPython Terminalには以下のようにチャンクが受信され、画像ファイルが保存されたメッセージが表示されます。

 コーディネータXBeeのFile System Managerを用いて/flashを確認してみると、MonaLisa.pngが保存されていることを確認できます。この画像をPC側の適当なディレクトリにダウンロードし、ファイルを開くと以下のように元画像と同じ画像であることを確認することができます。