[RPi] RaspberryPi pico に SDCard を接続して LCD で画像表示

RaspberryPi

前回は RaspberryPi pico に小型 TFT モジュールを接続して表示、MicroPython のライブラリを導入して描画してみました。このモジュールには SD スロットが付いてるので、SD カードから画像データを読み出して表示してみます。

SD カードインターフェース

SD カードにアクセスする方法として「SDモード」と「MMCモード」があります。「SPIモード」はクロック・Data IN・Data Outの3線で "SPI" デバイスとしてアクセスします。「MMCモード」はクロック・コマンド・データ(1~4本)を使ってアクセスします。

どちらもコマンドを送ってレスポンスを返す、を繰り返しますが、SPI モードは受信データ長の分だけ空データの送信を行う必要があるのに対して、MMCモードはコマンドとデータを別々に扱うため高速な通信ができます。また SPI モードは実行可能なコマンドに制限があります。

ILI9341 モジュールに付属の SD カードスロットは「SPI モード」としての端子が出ているので、これらを RaspberryPi pico の SPI 端子と接続します。SPI の場合、先の3線の他に CS (Chip Select) の制御も必要になります。

結線

前回の結線に加えて、SD カード側の端子を接続します。pico が master、モジュールが slave なので、SPI0_TX を SD_MOSI に(送信)、SPI0_RX を SD_MISO に(受信)、SPI0_SCK を SD_SCK に(クロック) 接続します。さらに SD_CS を空き GPIO の GP28 に接続しておきます。

ILI9341 RaspberryPi pico
1 SD_CS 34 GP28
2 SD_MOSI 10 GP7(SPI0_TX)
3 SD_MISO 6 GP4(SPI0_RX)
4 SD_SCK 9 GP6(SPI0_SCK)
5 F_CS N/C

SD_MISO (pico: GP4) は SD から pico への受信信号ですが、この信号は 10kΩ抵抗でプルアップしておきます。これをしておかないとデータを連続で受信できないことが多く失敗するため必要になります(送信信号はほぼ空データになるので不要です)。

SDCard ライブラリ

micropython のリポジトリから sdcard.py を導入します。

File not found · micropython/micropython
MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems - File not found · micropython/micropython

追記: micropython-lib に移動したようです。

micropython-lib/micropython/drivers/storage/sdcard/sdcard.py at master · micropython/micropython-lib
Core Python libraries ported to MicroPython. Contribute to micropython/micropython-lib development by creating an account on GitHub.

画像ファイルの準備

ILI9341 の画像フォーマットは RGB 16bit(RGB565) big-endian ですが、用意する手段がなかなかないので windows bitmap (.bmp) ファイルを元に加工して使います。任意の画像ツールで以下を行います。

  • 240x320 のサイズに加工
  • 上下反転 (bmp フォーマットが反転しているため)
  • RGB16bit で "BITMAP_rgb565.bmp" のファイル名で保存 (ファイル名は例)

以下の python スクリプトで bmp ファイルのヘッダを削除し、エンディアンを反転します。このスクリプトは pico ではなく PC 上で実行します。

import os,struct

data = []
with open('BITMAP_rgb565.bmp', 'rb') as f:
    f.seek(0x8a, os.SEEK_SET)
    while True:
        word = f.read(2)
        if word:
            val = struct.unpack('<H', word)[0]
            data.append(struct.pack('>H', val))
        else:
            break

with open('BITMAP_rgb565_be.raw', 'wb') as f:
    f.writelines(data)

出来上がった "BITMAP_rgb565_be.raw" が ILI9341 でそのまま表示できるファイルになります。これを FAT32 でフォーマットした SD カードの "/sd" ディレクトリに保存します。

サンプルプログラム

SD から画像ファイルを読み込んで LCD に描画する main.py を作成します。

from machine import Pin, SPI
import ili9341, os, sdcard

spi = SPI(1, baudrate=51200000, sck=Pin(14), mosi=Pin(15))
display = ili9341.Display(spi, dc=Pin(18), cs=Pin(16), rst=Pin(17))

sd = sdcard.SDCard(SPI(0), cs=Pin(28))
os.mount(sd, '/sd')
os.chdir('/sd')
display.draw_image('BITMAP_rgb565_be.raw', 0, 0, 240, 320)

1~2行目はモジュールのインポートです。

4~5行目は SPI インスタンスの設定を行い、それを指定して ili9341 の Display 関数を呼び出して LCD 表示できるようにします。

ここまでは前回と同じです。

7行目は SD カードの初期化・インスタンスの生成を行います。SPI0 とGP28 を指定します。

8~9行目は os 関数で SD カードの "/sd" へのマウントを行い、"/sd" に移動します。これが正しく動作すれば、SD カード上のファイルにアクセスができます。

10行目は SD カード上にある画像ファイル "BITMAP_rgb565_be.raw" を指定して読込み、LCD 上に表示します。

実行

画像ファイルを保存した SD カードをスロットに入れて、USB で pico と PC を接続します。

pico への main.py のインストールは前回と同じで VSCode で行います。アップロード後に main.py が実行され、LCD 上に用意した画像が出れば成功です。


コメント

タイトルとURLをコピーしました