airpocketのアイコン画像
airpocket 2023年01月31日作成 © MIT
セットアップや使用方法 セットアップや使用方法 閲覧数 3572
airpocket 2023年01月31日作成 © MIT セットアップや使用方法 セットアップや使用方法 閲覧数 3572

Raspberry Pi で小型LCDを動かす

Raspberry Pi で小型LCDを動かす

はじめに

Raspberry Pi でILI9341という小さめのカラーLCDを動かしたくていろいろ試しました。
動かす方法がいくつかあった為、まとめの覚書です。

方法1.pythonからSPI接続したディスプレイに表示する
方法2.pythonでフレームバッファに直接書き込み
方法3.fbiを使って静止画を表示
方法4.MPlayerを使って動画を表示

長くなりすぎるのでそれぞれ別記事にまとめます。

まとめ

この記事ではRaspberry PiでILI9341というドライバで動く小型のLCDを動かしました。
pythonで書いたプログラムからSPI通信を使ってしています。
制御自体はとても簡単なものの、描画に時間がかかるため動画表示はあまり快適とは言えません。
FPSが1以上のゆっくりした描画であればこの方法でも支障はないかと思います。
adafruitのライブラリだけでは使える機能が限られるのでopecvと併用して使ってみました

使用したLCD

今回はよく見かけるSPI接続タイプの小型LCDを使用しました。
よく似たLCDでも、ドライバICが異なるとライブラリが使用できない場合があるため注意が必要です。
今回はドライバにILI9341を使っている2.2inch 320x240サイズのTFT LCDを使用します
ライブラリにはadafruitのライブラリを用います。よく使われるドライバに対応しているライブラリですがLCDのインスタンスの読み込みに微妙な違いがある様ですので、他のドライバのLCDを使用する際はご注意ください。

Raspberry Pi

Raspberry Pi は4Bを使っておけば間違いないのですが 、運よく3B+を入手できたので両方で確認します。
Raspberry Pi は4Bで32bit版 Raspberry Pi OS(Bullseye)を使用しました。
64bit版を使いたいところですが、まだ64bit版に対応できていないライブラリも多くあります。使用用途や環境が限定的かつ64bi対応済みならば64bit版でも良いのですが、古くからあるデバイスやアプリを使うときには32bit版、場合によっては最新のBullseyeではなくLegacy版(Buster)の方が良い場合もあります。
今回使用するLCDやドライバ群は比較的昔からあるものなので、32bit版を使用してトラブルを回避します。

接続方法

Raspberry Piとディスプレイの接続は次の通りです。

LCD Raspberry Pi
SDO/MISO 21:GPIO9(SPI0 MISO)
LED 12:GPIO18
SCK 23:GPIO11(SPI0 SCLK)
SDI/MOSI 19:GPIO10(SPI0 MOSI)
DC/RS 18:GPIO24
RESET 16:GPIO23
CS 24:GPIO8(SPI0 CS0)
GND 9:GND
VCC 17:3V3

バックライトを点灯させ続けるならLEDは3V3ラインにつなげておいてもOKです。
今回はバックライトのON/OFFも制御したいのでGPIOに接続しています。

前準備

まずはRaspberry Piの設定を行い、必要なモジュールをインストールします。

SPIの有効化

ターミナルから次のコマンドを入力してコンフィグメニューを起動。

sudo raspi-config

次の通りメニューを選択してSPIを有効化する。
Interface Options>SPI>Yes>Ok>Finish

ライブラリの準備

まずはパッケージを最新状態にしておきます。

sudo apt-get update
sudo apt-get upgrade

続いてopencvとlcdのモジュールをインストールします。
lcdを動かすだけならopencvは不要ですが、今回はUSBカメラ画像を表示する際にopencvを使用します。
2023/1/13現在、pip install opencv-pythonではうまく入らいないのでapt で入れます。

sudo apt-get install python3-opencv
sudo pip3 install adafruit-circuitpython-rgb-display

動作確認

とりあえず動作確認のためのプログラムです。
https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display
公式のdemoコードをベースに、使用するピンなど多少変更しています。

import time
from busio import SPI
from board import SCK, MOSI, MISO, D8, D18, D23, D24, D2, D3
from digitalio import DigitalInOut, Direction
from adafruit_rgb_display.rgb import color565
from adafruit_rgb_display.ili9341 import ILI9341

# Configuration for GPIO pins:
CS_PIN    = DigitalInOut(D8)
LED_PIN   = DigitalInOut(D18)
RESET_PIN = DigitalInOut(D23)
DC_PIN    = DigitalInOut(D24)

LED_PIN.direction = Direction.OUTPUT

# Setup SPI bus using hardware SPI:
spi = SPI(clock=SCK, MOSI=MOSI, MISO=MISO)

# Create the ILI9341 display:
display = ILI9341(
    spi, cs = CS_PIN, dc = DC_PIN, rst = RESET_PIN,
    width = 240, height = 320, rotation = 90, baudrate=24000000)

# Turn on & off backlight:
LED_PIN.value = True
time.sleep(1)
LED_PIN.value = False
time.sleep(1)
LED_PIN.value = True

# Main loop:
while True:
    # Clear the display
    display.fill(0)
    print("clear display")
    # Draw a red pixel in the center.
    display.pixel(120, 160, color565(255, 0, 0))
    # Pause 1 seconds.
    time.sleep(1)
    # Clear the screen blue.
    display.fill(color565(0, 0, 255))
    # Pause 1 seconds.
    time.sleep(1)

adafruitのライブラリで使えるコマンドはこちらを参考にしてください。
https://docs.circuitpython.org/projects/rgb_display/en/latest/api.html#adafruit_rgb_display.rgb.Display
シンプルなdraw系のコマンドはありますが、あまり複雑なことはできません。テキスト表示もできないので、このライブラリだけで動かすのは少々辛そうです。

カメラ画像を表示してみる

USBカメラの画像をリアルタイムで表示してみました。
画像の書き換えが遅いのであんまり宜しくは無いですが一応動きます。
描画にopencvを使用していますので、テキスト表示やグラフ表示など、いろいろ応用可能です。

import time
from busio import SPI
from board import SCK, MOSI, MISO, D8, D18, D23, D24, D2, D3
from digitalio import DigitalInOut, Direction
from adafruit_rgb_display.rgb import color565
from adafruit_rgb_display.ili9341 import ILI9341

import cv2
from PIL import Image, ImageDraw

# Configuration for GPIO pins:
CS_PIN    = DigitalInOut(D8)
LED_PIN   = DigitalInOut(D18)
RESET_PIN = DigitalInOut(D23)
DC_PIN    = DigitalInOut(D24)

LED_PIN.direction = Direction.OUTPUT

# Setup SPI bus using hardware SPI:
spi = SPI(clock=SCK, MOSI=MOSI, MISO=MISO)

# Create the ILI9341 display:
display = ILI9341(
    spi, cs = CS_PIN, dc = DC_PIN, rst = RESET_PIN,
    width = 240, height = 320, rotation = 90, baudrate=24000000)

# Turn on & off backlight:
LED_PIN.value = True
time.sleep(1)
LED_PIN.value = False
time.sleep(1)
LED_PIN.value = True

# camera initialize
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

# main roop
while(True):
    ret, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame = Image.fromarray(frame)
    display.image(frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

capture.release()

おまけ

opencvの環境構築って失敗しやすいので、とりあえずカメラキャプチャを表示するだけのテストコード。
これが動けば、とりあえずopencvは動いてるのでトラブル時の切り分けに。

import cv2

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

# main roop
while(True):
    ret, frame = cap.read()
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

capq.release()
cv2.destroyAllWindows()
1
airpocketのアイコン画像
電子工作、プログラミング、AI、DIY、XR、IoT M5Stack / Raspberry Pi / Arduino / spresense / K210 / ESP32 / Maix / maicro:bit / oculus / Jetson Nano / minipupper etc
ログインしてコメントを投稿する