[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 を導入します。

Build software better, together
GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 330 million projects.

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

micropython-lib/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をコピーしました