airpocket が 2023年01月31日18時22分26秒 に編集
初版
タイトルの変更
Raspberry Pi で小型LCDを動かす
タグの変更
RaspberryPi
ILI9341
Python
opencv
メイン画像の変更
記事種類の変更
セットアップや使用方法
ライセンスの変更
(MIT) The MIT License
本文の変更
# はじめに 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の有効化 ターミナルから次のコマンドを入力してコンフィグメニューを起動。 ```shell sudo raspi-config ``` 次の通りメニューを選択してSPIを有効化する。 Interface Options>SPI>Yes>Ok>Finish ## ライブラリの準備 まずはパッケージを最新状態にしておきます。 ```shell sudo apt-get update sudo apt-get upgrade ``` 続いてopencvとlcdのモジュールをインストールします。 lcdを動かすだけならopencvは不要ですが、今回はUSBカメラ画像を表示する際にopencvを使用します。 2023/1/13現在、pip install opencv-pythonではうまく入らいないのでapt で入れます。 ```shell sudo apt-get install python3-opencv sudo pip3 install adafruit-circuitpython-rgb-display ``` # 動作確認 とりあえず動作確認のためのプログラムです。 https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display 公式のdemoコードをベースに、使用するピンなど多少変更しています。 ```python 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を使用していますので、テキスト表示やグラフ表示など、いろいろ応用可能です。 ```python 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は動いてるのでトラブル時の切り分けに。 ```python 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() ```