はじめに
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()
投稿者の人気記事
-
airpocket
さんが
2023/01/31
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する