2
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?

カラーLEDパネルにRaspberry Pi Picoで画像ファイルを表示する (CircuitPython)

Last updated at Posted at 2025-06-06

IMG_4803.JPG
街中でよく見かけるLEDパネルが個人でも1枚単位で入手できるようになって数年経ち、日に日に価格も安くなっていますが、タイトルのような最も単純なことをお手軽に(安価に)やろうとしたときに予想外にまとまった情報が少なかった(特に日本語)のと、Microsoft Copilotとかが例によって古い内容を答えてきたので、またもや【令和7年最新版】としてここに一旦まとめておきます。お手軽なのでCとかではなくCircuitPythonを使います。
というわけで高いRaspberry Piなどを使わないのでパネル込み時価5000円で遊べます。

表示するのは64x32ピクセルのbmp画像ファイルです1HUB75なので基本的にダイナミック点灯というか、古のCRTよろしく行ごとに走査しながら点灯させているので冒頭のデジカメ写真ではよくわからないかもしれませんが、直視ではこれよりはもう少し階調のわかる表示ができます。アイコン画像なども十分表示できるでしょう。

Raspberry Pi Pico

純正品なら2でもWでもどれでも大丈夫だと思います。未確認ですがCircuitPythonが入れられるものなら互換品でも大丈夫だと思います。モデルに合ったCircuitPythonを入れておいてください。

LEDパネルと接続方法

最近Amazonなどでもよく見かけるHUB75インタフェースのヤツです。自分は64x32ドット3mmピッチのものを3500円ぐらいで入手しました2。ちょっと修正すれば64x64のやつでもいけるはず。
以下の通りRaspberry Pi Picoと接続します。電源も念のため別系統で3Aぐらいのものを用意しましたが、実際の消費電流は1A程度でした。
接続については他に情報がたくさんあるのでここではこれ以上詳細の説明はしません。

code.py
rgb_pins=[
    board.GP2,  # R1
    board.GP3,  # G1
    board.GP6,  # B1
    board.GP7,  # R2
    board.GP8,  # G2
    board.GP9,  # B2
],
addr_pins=[board.GP10, board.GP16, board.GP18, board.GP20],  # A  # B  # C  # D
clock_pin=board.GP11,
latch_pin=board.GP12,  # (STB)
output_enable_pin=board.GP13,

画像ファイル表示のミニマムなコード

必要なライブラリをimportして最初にdisplayioを初期化します。

code.py
import gc
import board
import displayio
import rgbmatrix
import framebufferio
import time

displayio.release_displays()
...

つぎに先ほどのピン接続でrgbmatrixを設定します。
カラーのビット深度は一応framebufferRGB565をカバーする6(6×3色=18>5+6+5=16)にしておきます。
今回パネルはデイジーチェインせず1枚なのでtile1、LEDセルの並びは通常のZ型配列、doublebufferTrueです。

code.py
matrix = rgbmatrix.RGBMatrix(
    width=64,
    height=32,
    bit_depth=6,
    rgb_pins=[  # Preserve GP4 & GP5 for standard STEMMA-QT
        board.GP2,  # R1
        board.GP3,  # G1
        board.GP6,  # B1
        board.GP7,  # R2
        board.GP8,  # G2
        board.GP9,  # B2
    ],
    addr_pins=[board.GP10, board.GP16, board.GP18, board.GP20],  # A  # B  # C  # D
    clock_pin=board.GP11,
    latch_pin=board.GP12,
    output_enable_pin=board.GP13,
    tile=1,
    serpentine=False,
    doublebuffer=True,
)
...

64x32のbmpファイルはPCからCircuitPythonのドライブ(H:とか)に適当にフォルダを作成して保存しておきます。今回は24ビットカラーのファイルを用意しましたが、いい感じに減色してくれるようで問題ありませんでした。
そしてTileGridを作成します。引数には先ほど読み込んだbitmapとそこから作るpixel_shader、描画開始座標(今回はパネル左上)を渡します。32x32画像などを表示する場合はxを16にするとセンターに表示されます。

code.py
image_path = "/graphics/test.bmp"
try:
    bitmap = displayio.OnDiskBitmap(image_path)
except Exception as e:
    print(f"Error loading image: {e}")

tile_grid = displayio.TileGrid(
    bitmap, 
    pixel_shader=bitmap.pixel_shader,
    x=0,
    y=0
)            
...

続いて先ほどのmatrixを元にframebufferを作成し、空のdisplay_groupも作成してそれを描画対象に指定します。今回はグループは1つだけ、またグループと言っても今回は1枚のbitmapだけがグループ内の要素となります。

code.py
display = framebufferio.FramebufferDisplay(matrix)
display_group = displayio.Group()
display.root_group = display_group
...

そしてwhileループになります。念のためガベージコレクションして、先ほどのTile_gridgroupappendすれば画像が表示されます3。ここが実際の表示開始部分になります。古い情報ではshow()が使われているものがありましたがこれは廃止され4、この形式に変更されたようです5
あまり早くループを回すとメモリエラーが発生するようなので最後に適当にウェイトを入れておきます。

code.py
while True:
    try:
        gc.collect()
        if image_path:
            group.append(tile_grid)
            time.sleep(5)
...

複数の画像を切り替えるには続けて最初のtile_gridremoveして次に表示するファイルから作成したTile_Grid2とかを再度appendすればOKです。最初のファイルと同様にimage_path2bitmap2などとして設定しておいてください。
巷のスクロールやアニメーションのデモも同様の手法で画像を更新して実現しているようです。

code.py
# 上のtile_glidの実装の下に
tile_grid2 = displayio.TileGrid(
    bitmap2, 
    pixel_shader=bitmap2.pixel_shader,
    x=0,
    y=0
)

...

# 上の`time.sleep(5)の後に
            if image_path2:
                group.remove(tile_grid)
                gc.collect()
                group.append(tile_grid2)
                time.sleep(5)
                group.remove(tile_grid2)
...

基本的にはこれだけです。
Web上の情報にはスクロールとか文字表示とかアニメーションとかもっと複雑なものがいろいろありますが、まずは自分がお手軽なPythonでの画像表示の基本的な流れを理解するために試したものです。

最後にcode.pyの全体を載せておきます。

code.py
import gc
import board
import displayio
import rgbmatrix
import framebufferio
import time

displayio.release_displays()

# === Setup for Pico ===
# Setup rgbmatrix display (change pins to match your wiring)
matrix = rgbmatrix.RGBMatrix(
    width=64,
    height=32,
    bit_depth=6,
    rgb_pins=[  # Preserve GP4 & GP5 for standard STEMMA-QT
        board.GP2,  # R1
        board.GP3,  # G1
        board.GP6,  # B1
        board.GP7,  # R2
        board.GP8,  # G2
        board.GP9,  # B2
    ],
    addr_pins=[board.GP10, board.GP16, board.GP18, board.GP20],  # A  # B  # C  # D
    clock_pin=board.GP11,
    latch_pin=board.GP12,
    output_enable_pin=board.GP13,
    tile=1,
    serpentine=False,
    doublebuffer=True,
)

display = framebufferio.FramebufferDisplay(matrix)
group = displayio.Group()
display.root_group = group
# === end of pico setup === #

image_path = "/graphics/test.bmp"
image_path2 = "/graphics/test2.bmp"
try:
    bitmap = displayio.OnDiskBitmap(image_path)
    bitmap2 = displayio.OnDiskBitmap(image_path2)
except Exception as e:
    print(f"Error loading image: {e}")

tile_grid = displayio.TileGrid(
    bitmap, 
    pixel_shader=bitmap.pixel_shader,
    x=0,
    y=0
)
tile_grid2 = displayio.TileGrid(
    bitmap2, 
    pixel_shader=bitmap2.pixel_shader,
    x=0,
    y=0
)

# === Main Loop ===
while True:
    try:
        gc.collect()
        if image_path:
            group.append(tile_grid)
            time.sleep(5)
            if image_path2:
                group.remove(tile_grid)
                gc.collect()
                group.append(tile_grid2)
                time.sleep(5)
                group.remove(tile_grid2)
    except MemoryError:
        print("MemoryError! Trying to recover...")
        group = displayio.Group()
        display.root_group = group
        gc.collect()
        time.sleep(1)

今回は以上です。

  1. 実用性についてツッコんではいけない。

  2. 2.5mmピッチのやつは倍ぐらいの値段するので却下。

  3. これを書いた後で見つけたのですが、ここまでの話というか公式ガイドの日本語訳が https://steam-tokyo.com/circuitpython-displayio-lib-1-5/ こちらにあります(ただし一部情報が古い)。

  4. https://github.com/adafruit/circuitpython/issues/7213

  5. なんでわかりにくくしたんだ、という気はする。

2
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
2
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?