🫖

Raspberry Pi Pico Wでバーサライタを作成③ 表示データ作成

2024/08/16に公開

ここでは、MicroPythonを用いて、Raspberry Pi Pico Wでバーサライタ用の表示データの作成と完成版の動作を紹介する。以下の記事の続きである。
https://zenn.dev/ythk/articles/ythk-versawriter1
https://zenn.dev/ythk/articles/ythk-versawriter2

表示データの作成

前回は動作確認のため、適当に半円状のパターンを表示させてたが、今度は画像データを表示できるようにする。256x256の白黒画像を用意し、それをバーサライライタ用へ変換することにする。ということでxy座標から極座標へ変化する。都度変換するのは無駄なので、あらかじめそういうデータを作っておく。

画像データを極座標変換するプログラム

transformImage.py
import sys
from os.path import basename, splitext
import numpy as np
from PIL import Image

L = 256 # 画像のサイズ
R = 16  # 極座標の動径方向の刻み数 = LEDの数
A = 360 # 極座標の角度方向の刻み数

imagelist = []
print("image = {")
for path in sys.argv[1:]:
    name = splitext(basename(path))[0]
    imagelist.append(f"'{name}',")
    img = Image.open(path).resize((L, L)).convert('L')
    #img.show()
    wh_array = np.array(img).tolist()
    a_array = np.empty(A, dtype=int)
    for a in range(A):
        th = a/A*2*np.pi
        pattern = 0
        for r in range(R):
            w = (1 + r/(R-1)*np.cos(th))*(L-1)/2
            h = (1 - r/(R-1)*np.sin(th))*(L-1)/2
            if wh_array[int(np.clip(w,0,L-1))][int(np.clip(h,0,L-1))] < 128:
                pattern |= 1
            pattern <<= 1
        a_array[a] = pattern

    print(f"    '{name}' : ", end="")
    print(a_array.tolist(), end=",\n")
print("}")

print("image = [", *imagelist, "]")

入力画像の例


出力結果の例

動径方向をbitに圧縮するので、各角度ごと16bitの整数で表現できる。

myimage.py
image = {
    'number0' : [240, 120, 120, 120, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 496, 496, 496, 496, 496, 496, 1008, 1008, 1008, 1008, 1008, 992, 992, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 4064, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7936, 7936, 7936, 7936, 7936, 7936, 16128, 16128, 16128, 16128, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 3968, 3968, 3968, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 1984, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 992, 992, 992, 992, 992, 496, 480, 480, 496, 496, 496, 496, 496, 496, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 496, 496, 496, 496, 496, 496, 496, 480, 992, 992, 992, 992, 992, 992, 992, 2016, 2016, 2016, 2016, 2016, 2016, 1984, 1984, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 3968, 3968, 3968, 3968, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 3968, 3968, 3968, 3968, 3968, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 1984, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 992, 992, 1008, 1008, 1008, 1008, 496, 496, 496, 496, 496, 496, 496, 240, 240, 240, 240, 240, 240, 240, 240, 248, 240, 240, 240, 120, 120, 120, 120],
    'number1' : [131056, 131056, 131056, 131008, 130560, 130048, 129024, 126976, 122880, 122880, 122880, 114688, 114688, 114688, 114688, 114688, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 65536, 66048, 66048, 66048, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67072, 67328, 67328, 67328, 69376, 69376, 69376, 69376, 69376, 69376, 69504, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 69376, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 102144, 118528, 116608, 116608, 116608, 116608, 124800, 124800, 124800, 128896, 130944, 131008, 131008, 131008, 131040, 131040, 131040, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131064, 131056, 131056, 131040, 131040, 131008, 131008, 130944, 130944, 130944, 130816, 130816, 130816, 130816, 130560, 130560, 130560, 130560, 130560, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130560, 130560, 130560, 130560, 130560, 130816, 130816, 130816, 130816, 130944, 130944, 130944, 131008, 131008, 131040, 131040, 131056, 131056, 131064, 131064, 131064, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056],
    'number2' : [64752, 64752, 64752, 64752, 65264, 65264, 65264, 65264, 65264, 65520, 65520, 65520, 65520, 65520, 65520, 65520, 65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, 65532, 65532, 65532, 65532, 65532, 32764, 32764, 32766, 32764, 32764, 32760, 32752, 16368, 16352, 8128, 3968, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 384, 384, 448, 448, 448, 960, 960, 960, 960, 960, 960, 960, 960, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 992, 992, 992, 992, 992, 992, 1008, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 1008, 1008, 1008, 992, 992, 992, 2016, 2016, 2016, 2016, 2016, 4064, 4064, 4064, 4064, 4064, 8160, 8128, 8128, 16320, 16320, 16320, 16320, 16320, 32704, 32704, 32640, 32640, 32640, 32640, 32640, 32640, 32640, 32640, 65408, 65408, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61456, 61488, 61488, 61488, 61496, 61496, 61496, 61564, 61564, 61564, 61564, 61564, 61564, 61564, 61564, 61564, 61560, 61560, 61688, 61688, 63736, 63736, 63736, 63736, 63736, 63736, 63736, 63728, 63728, 63728, 63728, 63728, 63728, 63728, 63728, 63728, 63728, 64752, 64752, 64752, 64752, 64752],
    'number3' : [65776, 98424, 98424, 98424, 98416, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 99312, 99312, 99312, 99296, 99296, 99296, 99296, 99296, 99296, 99296, 98784, 98784, 98784, 98784, 98784, 98752, 98496, 98496, 98496, 98496, 98496, 98368, 98368, 114752, 114752, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 114688, 114688, 114688, 114880, 114880, 114880, 114880, 115136, 115136, 115136, 115136, 115136, 115648, 115648, 115648, 115680, 115680, 115680, 115680, 115680, 115680, 115680, 115680, 115680, 115680, 115680, 115168, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 115184, 115184, 115184, 115184, 115184, 123376, 123376, 123376, 123376, 123872, 123872, 123872, 123872, 124896, 128992, 128992, 131040, 131040, 131040, 131040, 131040, 131040, 131040, 131040, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130816, 130816, 130816, 130816, 130816, 130816, 130560, 130560, 130560, 130560, 130560, 130048, 130048, 130048, 130048, 129024, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 122880, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 129024, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130560, 130560, 130560, 130560, 130560, 130560, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 131008, 131008, 131008, 131008, 131008, 122816, 106432, 106432, 106432, 102336, 102368, 102368, 102368, 102368, 102368, 100320, 100320, 100320, 100320, 100320, 100320, 100320, 99296, 99296, 99296, 99312, 99312, 99312, 99312, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98552, 98544, 98544, 98544, 98424, 98424, 98424, 98424],
    'number4' : [7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 8064, 3968, 3968, 3968, 3968, 3968, 3968, 3968, 4032, 4032, 4032, 4032, 4032, 4032, 4064, 2016, 2016, 2016, 2016, 2016, 1984, 1984, 4032, 4032, 4032, 4032, 4032, 8128, 8128, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 16256, 16256, 16128, 16128, 16128, 16128, 16128, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15360, 15360, 15360, 15360, 15360, 15360, 15360, 15360, 31744, 31744, 31744, 31744, 31744, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 31744, 31744, 15360, 15360, 31744, 31744, 15360, 15360, 15360, 15360, 15360, 15360, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 16128, 16128, 16128, 16128, 16128, 16128, 16256, 8064, 8064, 8064, 8128, 8128, 8128, 8128, 8160, 8160, 8176, 8176, 4080, 4080, 4080, 2032, 2032, 2032, 4080, 4080, 4088, 4088, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 16376, 16368, 16368, 16352, 16352, 16352, 16320, 16320, 16320, 16320, 16256, 16256, 16256, 16256, 16256, 16128, 32512, 32512, 32512, 32512, 32512, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31872, 31872, 31872, 32128, 32192, 32192, 32192, 32704, 32704, 32704, 32704, 32704, 32704, 32704, 32736, 32736, 32736, 32736, 32736, 32736, 32736, 32736, 32704, 32704, 32704, 32704, 16320, 16320, 16256, 16256, 16256, 16256, 16320, 16320, 16320, 16320, 16352, 16352, 16352, 16368, 16368, 16376, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 8184, 8176, 8176, 8176, 8176, 8176, 8176, 7920, 7792, 7696, 7680, 7680, 7680, 7680, 7680, 7680],
    'number5' : [112, 120, 120, 112, 112, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 496, 496, 496, 496, 496, 496, 496, 1008, 1008, 1008, 1008, 1008, 992, 992, 992, 992, 992, 480, 480, 480, 480, 480, 480, 480, 448, 192, 192, 192, 192, 192, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4096, 4096, 12288, 12288, 12288, 12288, 14336, 14336, 14336, 14336, 31744, 31744, 31744, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 65024, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 65024, 64512, 64512, 64512, 65024, 65024, 64512, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65024, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280, 65408, 65408, 65408, 65408, 65408, 65408, 65472, 65472, 65472, 65472, 61376, 61408, 61408, 61408, 61408, 61424, 61424, 61424, 61424, 61424, 59376, 59376, 59376, 59376, 59376, 58352, 58352, 58352, 57840, 57840, 57840, 57840, 57840, 57840, 57824, 57824, 57824, 57824, 57824, 57824, 57824, 57824, 57824, 57824, 61920, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61680, 61680, 61680, 61688, 61688, 61688, 61688, 61688, 61688, 61688, 61688, 61692, 61692, 61560, 61560, 61560, 61552, 61552, 61552, 61536, 63584, 63520, 63520, 63520, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 65024, 65024, 65024, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32256, 32512, 32512, 32512, 32512, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8128, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 992, 992, 992, 992, 992, 992, 992, 1008, 496, 496, 496, 496, 496, 496, 496, 496, 496, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 120, 112, 120, 120, 112, 112, 120, 120, 120, 120, 120],
    'number6' : [65776, 65776, 65776, 65776, 65776, 65776, 65776, 65776, 65776, 65776, 66032, 66032, 66032, 66032, 66032, 66032, 66032, 66032, 66544, 66544, 66544, 66528, 66528, 66528, 67552, 67552, 67552, 67552, 67552, 67552, 67552, 69600, 69600, 69600, 69568, 69568, 69568, 69568, 73664, 73664, 73664, 73664, 73664, 73664, 73664, 73600, 73600, 81792, 81792, 81792, 81792, 81792, 81792, 81792, 81792, 81792, 81792, 98048, 98048, 98048, 98048, 98048, 98048, 98048, 98048, 98048, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 126848, 126848, 126848, 126848, 126912, 126912, 126912, 126912, 126912, 126912, 126912, 126912, 124864, 124864, 124864, 124864, 124896, 124896, 124896, 124896, 124896, 123872, 123872, 123872, 123872, 123872, 123872, 123360, 123360, 123360, 123360, 123360, 123360, 123376, 123360, 123376, 123376, 123376, 123376, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123120, 123376, 123376, 123376, 123376, 127472, 127472, 127472, 127472, 127984, 127984, 127968, 127968, 127968, 127456, 127456, 127456, 127456, 127456, 127456, 127456, 127200, 127200, 127200, 127168, 127168, 127040, 127040, 127040, 127040, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130560, 130560, 130560, 130560, 97792, 97792, 97792, 97792, 97792, 97792, 97792, 97792, 97792, 81408, 81664, 81664, 81664, 81664, 81664, 81664, 81664, 81664, 81664, 81664, 73472, 73472, 73600, 73600, 73600, 73600, 73600, 73600, 73600, 73600, 73600, 69504, 69504, 69504, 69568, 69568, 69568, 69568, 69568, 69568, 69568, 67520, 67520, 67520, 67552, 67552, 67552, 67552, 67552, 67552, 67552, 66528, 66528, 66528, 66528, 66544, 66544, 66544, 66544, 66032, 66032, 66032, 66032, 66032, 66032, 66032, 66032, 65776, 65776, 65776, 65776, 65776, 65776, 65776, 65784, 65784, 65776, 65784, 65776, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65656, 65784],
    'number7' : [131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131056, 131064, 131064, 131064, 131064, 131064, 131056, 131040, 131008, 131008, 130944, 130944, 130816, 130816, 130560, 130560, 130048, 130048, 130048, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98304, 98336, 98336, 98336, 98336, 98336, 98416, 98416, 98416, 98416, 98424, 98424, 98424, 98428, 98556, 98552, 98552, 98552, 98552, 98552, 98552, 98552, 98552, 98544, 98544, 98544, 98544, 98544, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115184, 115168, 115168, 115168, 115168, 123360, 123360, 123360, 123360, 123360, 123360, 123360, 123376, 123376, 127472, 127472, 127472, 127472, 127472, 129520, 129520, 129520, 129520, 130544, 130544, 130288, 130800, 130800, 131056, 131056, 131064, 131064, 131064, 131064, 131064, 131064, 131064, 131064, 131068, 131068, 131068, 131068, 131068, 131064, 131064, 131064, 131064, 131056, 131056, 131056, 131056, 131008, 130816, 130816, 130560, 130560, 130048, 130048, 130048, 129024, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 114688, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 122880, 126976, 122880, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 129024, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130560, 130560, 130816, 130816, 131008],
    'number8' : [98416, 98424, 98424, 98416, 98416, 98416, 98416, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98544, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 99312, 99312, 99312, 99312, 99312, 99296, 100320, 100320, 100320, 100320, 100320, 100320, 102368, 102368, 102368, 102368, 118752, 122816, 122816, 122816, 131008, 131008, 131008, 131008, 131008, 131008, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 122880, 126976, 126976, 126976, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130048, 130560, 130560, 130560, 130560, 130560, 130560, 130816, 130816, 130816, 130816, 130816, 130816, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131040, 131040, 131040, 131040, 131040, 131040, 131040, 128992, 124896, 124896, 123872, 123872, 123888, 123888, 123888, 123376, 123376, 123376, 115184, 115184, 115184, 115184, 115184, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 114928, 115184, 115184, 115184, 115184, 115184, 123376, 123376, 123376, 123888, 123888, 123872, 123872, 124896, 124896, 124896, 124896, 131040, 131040, 131040, 131040, 131040, 131040, 131040, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130816, 130816, 130816, 130816, 130816, 130816, 130560, 130560, 130560, 130560, 130560, 130048, 130048, 130048, 130048, 129024, 129024, 129024, 129024, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 126976, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 129024, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130048, 130560, 130560, 130560, 130560, 130560, 130560, 130560, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130816, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 130944, 131008, 131008, 131008, 131008, 131008, 131008, 131008, 122816, 118720, 102368, 102368, 102368, 102368, 100320, 100320, 100320, 100320, 100320, 100320, 100336, 99296, 99312, 99312, 99312, 99312, 99312, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 98800, 98544, 98544, 98544, 98544, 98544, 98544, 98552, 98544, 98552, 98544, 98552, 98552, 98424, 98424, 98424, 98416, 98424, 98424, 98424, 98424, 98424, 98424],
    'number9' : [61680, 61560, 61560, 61560, 61560, 61560, 61560, 61560, 61560, 61688, 61560, 61688, 61688, 61688, 61688, 61688, 61688, 61688, 61688, 61688, 61680, 61680, 61680, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61936, 61920, 61920, 61664, 63712, 61664, 61664, 63712, 63712, 63584, 63552, 63552, 63552, 63552, 63488, 63488, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 32256, 32256, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 15872, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 7936, 7936, 7936, 7936, 7936, 7936, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 3968, 3968, 3968, 3968, 3968, 3968, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 1984, 1984, 1984, 2016, 2016, 2016, 2016, 2016, 2016, 992, 992, 992, 992, 992, 992, 992, 992, 480, 480, 480, 496, 496, 496, 496, 496, 496, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 496, 496, 496, 496, 496, 496, 496, 496, 480, 480, 992, 992, 992, 992, 992, 992, 992, 992, 992, 2016, 2016, 2016, 2016, 2016, 2016, 1984, 1984, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 8064, 16256, 16256, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 16128, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 32512, 65280, 65280, 65280, 65280, 65408, 65408, 65408, 65408, 65408, 61312, 61312, 61312, 61312, 61312, 61312, 61312, 61312, 61312, 61376, 61376, 61376, 61376, 61376, 61376, 61376, 61376, 61376, 59328, 59328, 59328, 59328, 59360, 59360, 59360, 59360, 59360, 59360, 58336, 58336, 58336, 58336, 58336, 58336, 57840, 57840, 57840, 57840, 57840, 57840, 57840, 57840, 57584, 57584, 57584, 61680, 61680, 57584, 57584, 57584, 57584, 57584, 61680, 61680, 61680, 61560],
}

シミュレータの作成

動作確認を実際のバーサライライタで行うのは大変なので、pythonでシミュレータも作った。from myimage import imageで先ほどの変換された画像データを取り込んでいる。時間ごと画像を差し替えることで、アニメーション表示している。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from math import pi, sin, cos, fmod
from myimage import image

TMAX = 10  # シミュレーションの周期
AMAX = 360  # 円周座標の分割数
DELTA = 0.1  # シミュレーションの時間間隔
RSHIFT = 0  # 回転中心から、LEDの端までの距離

numberlist = ['number0', 'number1', 'number2', 'number3', 'number4', 'number5', 'number6', 'number7', 'number8', 'number9']

def ledPattern(a, t):
    # number
    if t < 5:
        i = int(t*2)
        return image[numberlist[i]][a]
    t-=5

    # number-reverse
    if t < 5:
        i = int(t*2)
        return ~image[numberlist[i]][a]
    t-=5


def extractR(pattern, a):
    return ((15. + RSHIFT - r, a) for r in range(16) if pattern & (1 << r))


fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, aspect="equal")
ax.set_xlim(-16-RSHIFT, 16+RSHIFT)
ax.set_ylim(-16-RSHIFT, 16+RSHIFT)
ax.add_patch(patches.Circle((0,0), radius=15.0 + RSHIFT, fill=True, color="gray"))

angles = range(AMAX)
time = 0
while True:
    time = fmod(time + DELTA, TMAX)
    ra_list = (extractR(ledPattern(a, time), a) for a in angles)
    rsc_list = [[r, sin(a*2*pi/AMAX), cos(a*2*pi/AMAX)] for items in ra_list for (r, a) in items]
    r, sinA, cosA = np.array(rsc_list).T
    x, y = -r * sinA, -r * cosA
    s = ax.scatter(x, y, s=50, c="blue")
    ax.set_title(f"time = {time:.2f}s")
    plt.pause(DELTA)
    s.remove()


シミュレータの表示例

ラズピコのプログラム

最終的なバーサライライタのプログラムは以下の通り。

main.py
from rp2 import asm_pio, PIO
from machine import Pin, ADC
from time import ticks_us, ticks_diff
from math import fmod
from myimage import image

TMAX = 60 # 時間の上限
AMAX = 360  # 円周座標の分割数

SER = Pin(13, Pin.OUT)
SCLK = Pin(14, Pin.OUT)
RCLK = Pin(15, Pin.OUT)
PHOTO = ADC(2)

blocklist = [ 'block00', 'block01', 'block02', 'block03', 'block04', 'block05', 'block06', 'block07', 'block08', 'block09', 'block10', 'block11', 'block12', 'block13', 'block14', 'block15']
runlist = ['run0', 'run1', 'run2', 'run3', 'run4', 'run5', 'run6', 'run7',]
buturilist = ['buturi0', 'buturi1', 'buturi2', 'buturi3', 'buturi4', 'buturi5', 'buturi6']
numberlist = ['number9', 'number8', 'number7', 'number6', 'number5', 'number4', 'number3', 'number2', 'number1', 'number0']
catlist = ['cat0', 'cat1','cat2']

@asm_pio(
    out_init=PIO.OUT_LOW,
    out_shiftdir=PIO.SHIFT_RIGHT,
    sideset_init=(PIO.OUT_LOW, PIO.OUT_LOW),
)
def controlLED():
    pull()
    set(x, 15)
    label("loop")
    out(pins, 1).side(0b00)
    jmp(x_dec, "loop").side(0b01)
    nop().side(0b11)


def ledPattern(a, t):
    # buturi
    if t<14:
        i = int(t//2)
        return image[buturilist[i]][a]
    t-=14
    
    # number
    if t<5:
        i = int(t*2)
        return image[numberlist[i]][a]
    t-=5

    # block
    if t<20:
        i = int(t*4)%(16*2+8)
        if i<16:
            return image[blocklist[i]][a]
        elif i<16+8:
            return image[blocklist[15]][(a+int(AMAX*(i-15)/16))%AMAX]
        else:
            return image[blocklist[39-i]][(a+AMAX//2)%AMAX]
    t-=20

    # number
    if t<5:
        i = int(t*2)
        return ~image[numberlist[i]][a]
    t-=5

    #cat
    if t<16:
        i = int(t*4)%3
        return image[catlist[i]][a]
    t-=16

    # error
    return 0


led = Pin("LED", Pin.OUT)
led.low()
sm = rp2.StateMachine(0, controlLED, out_base=SER, sideset_base=SCLK)
sm.active(1)
t = 0  # 時間(s)
period = 10000  # 一周にかかる時間(us)
ticks_prev = ticks_us()  # 前回原点を通過した時刻

while True:
    ticks_now = ticks_us()
    delta = ticks_diff(ticks_now, ticks_prev)
    isOrigin = PHOTO.read_u16() > 20000
    if isOrigin and delta > 10000:  # 一周した
        ticks_prev = ticks_now
        period = (period + delta) / 2
        t = fmod(t + delta * 1e-6, TMAX)
        delta = 0
        led.value(True)
    else:
        led.value(False)
    a = int(fmod(delta/period, 1) * AMAX) % AMAX
    sm.put(ledPattern(a, t))

特にdef ledPattern(a, t)はシミュレータと同じになるよう作ってある。つまりシミュレータで一度動作確認をしてから、ここにコピペすれば良い。前回は、回転数ごとパターンが変わるようにプログラムしていたが、そうすると回転速度によってアニメーション速度も変わってしまう。そこでledPatternの引数から回転数を消して、代わりに実際の時間に変更した。

完成品と動作結果

肉眼で見るともっとチラつかずに見えるのだけど、動画で撮るとチラついてしまう・・・。数字や文字はかなり鮮明に見える。猫は、3コマのアニメなのだけど、著者の絵心によるものが大きい。

扇風機の羽を早く回すほど綺麗に見えるが、バーサライライタの重心がピッタリ回転中心に合っているわけではないので、それほど速く回すことはできない。振動が大きくなって危険を感じる。一応
端に1gの錘をつけるだけで、振動が変わるくらい繊細である。もっときちんと設計するならともかく、そういう機械的な限界が、ラズピコの処理速度よりも先に来るみたいである。

今回は全てのLEDを同じ明るさで光らせているが、当然担当範囲が狭い中心部分の方が明るくなる[1]。これをソフト的に補正するのは絶望的なので、ハード的に補正するのが良いかもしれない。光を拡散させるため、LEDの上にマスキングテープを貼っているのだが、その枚数で調整するのが最も簡単である[2]。可変抵抗を使うのは頑張りすぎだろう。PWMによる明るさ調整も相性が悪いであろう。

今後の展望

  • 16LEDといわず、もっと巨大化させる
  • フルカラーLEDを使う
  • 羽を複数枚重ねて立体表示させる
  • プリント基盤を作る
  • フレキシブル基板を円弧状に曲げて、球面表示ができるようにする

脚注
  1. 作ってから気づいた ↩︎

  2. さっき気づいた ↩︎

Discussion