MicroPython的午睡(73) uarrayとuctypesで数値配列のファイル入出力

Joseph Halfmoon

前々回、ラズパイPico上でuarrayとuctypesを使い、連続したメモリ上に置かれるバイナリ配列を操作してみました。メモリに制約のあるマイコン上のMicroPythonでは必須でしょう。今回はこれまたMicroPythonの特徴の一つであるFlash上のストレージに対してバイナリ配列の読み書きをやってみます。

※「MicroPython的午睡」投稿順 Indexはこちら

MicroPythonは、機種やバージョンにより容量はさまざまですが、マイコンのFlashメモリの一部を読み書き可能なストレージとして使えるようにしてくれてます。ラズパイPicoで MicroPython v1.19.1の場合は、1.4Mバイトほどの「ストレージ」が利用可能です。当然 MicroPythonのスクリプト(ソース、コンパイル済どちらも)を置いておくこともできますが、データの保存等にも使えます。その昔のフロッピー1枚分くらいの容量ですが、あるとないとでは大違いじゃないかとおもいます。

当然限られた容量での運用のために、メモリ上のバイナリ配列は、ファイル入出力時でもバイナリとしたいです。今回はあからさまに呼び出しているわけではないですが、IO入出力ストリームに関するMicroPythonのマニュアルページは以下に。

io — 入出力ストリーム

上記でも説明されているバイナリ入出力を行ってみます。

実験に使用したスクリプト

以下のスクリプトでは、以下の入出力操作を行っています。

  1. uarrayモジュールを使ってメモリ上に確保した4バイト整数型の256要素の配列を、バイナリファイルとしてストレージに出力。
  2. ストレージ上のバイナリファイルをメモリ上に読み込んだのち、uctypesを用いて4バイト整数型の配列として再解釈。
import uctypes, uarray

ARY = {
    "ary": (0 | uctypes.ARRAY, 256 | uctypes.INT32),
}

def saveUarray():
    uiArray = uarray.array("l", [0] * 256)
    for i in range(256):
        uiArray[i] = i - 128
    print(uiArray[0],uiArray[1],uiArray[254],uiArray[255])
    with open('test.bin', 'wb') as fw:
        fw.write(uiArray)

def main():
    saveUarray()
    with open('test.bin', 'rb') as fr:
        ubArray = fr.read()
    adr0 = uctypes.addressof(ubArray)        
    ary1 = uctypes.struct(adr0, ARY)
    print(ary1.ary[0], ary1.ary[1], ary1.ary[254], ary1.ary[255])
    
if __name__ == "__main__":
    main()
実験結果

まず、saveUarray()関数によりストレージに書き出されたバイナリファイルの大きさを確認してみます。4bytes x 256要素 = 1024 bytes と無駄なく詰まっていることがわかります。generatedBINfile

以下の出力の最初の行は、メモリに書き出し前の特定要素の値です。2行目は、ストレージに書き出したものをバイナリデータとして読み込み、uctypesを使って配列にマップして再解釈してみた同じインデックス要素の値です。writeReadResults

ちゃんとバイナリ入出力できてるみたい、って当たり前か。

MicroPython的午睡(72) Thonny IDE 4.0.1インストール へ戻る

MicroPython的午睡(74) MicroPythonソースから最新版ビルド へ進む