2018年3月18日日曜日

Raspberry Piに0.96インチのLCDを付けて、カメラの画像を表示してみた


背景

Raspberry piのGPUを使って数fpsで物体認識を行うというデモをidein(イデイン)株式会社が公開しています。



公演会場をスキャンすると、椅子を認識して「folding chair」(折りたたみ椅子)と表示していました。


デモで使われているような小さなLCD付きのRaspberry Pi Zeroが欲しくなったので、作ってみました。
(この記事で作るのは外側だけです。こちらの記事でDNNを利用した物体認識の動かし方を把握し、こちらの記事でLCDを組み合わせて、物体認識装置を作りました。)
ところどころ詰まる部分があったので、備忘録を兼ねて情報を共有します。

全体像

  1. 使ったもの
  2. 配線
  3. カメラを接続
  4. Raspberry Piのソフトウェア開発環境の準備
  5. LCDの起動
  6. LCDに文字を表示
  7. LCDにカメラの画像を表示
  8. 自動起動設定
  9. まとめ

使ったもの

必須

  • Raspberry Pi Zero WH
    スイッチサイエンス秋月電子で買えます。
  • Raspberry Pi Zero用カメラ
    早く手に入れたいならAmazon、数週間かかって良いくらい急がないならAliexpressで買えます。
  • 16GM Micro SD + Raspbian Lite
    Raspberry PiにSSH接続できるように設定しておいてください。
    Raspbianはデスクトップ版でも動作しますが、デスクトップ画面の表示に計算能力が割り当てられる分、表示の更新が遅くなります。
    2017/11リリース版で動作を確認しました。
  • 0.96インチカラーLCDモジュール
  • Raspberry Pi Zeroの電源
    USB microBケーブル + 1A USB電源を使いました。
  • オスメスジャンパワイヤ
    Raspberry Piからの電源や信号の引き出しに利用します。
  • はんだ + ハンダゴテ
    LCDモジュールへの部品取り付けに使います。

小さくまとめたい場合

  • ピンソケット
    LCDモジュールとRaspberry PIを直接接続できるようにします。
  • ペンチ
    ピンソケットのピンを抜くのに使います。
  • ワイヤストリッパー
  • オスメスジャンパワイヤの切断と被覆線剥ぎに使いました。
    ニッパーでも代用できます。

小さくまとめなくて良い場合

ブレッドボード

配線

信号線の関係

Raspberry PiとLCDモジュールをこのように接続します。

LCD Raspberry pi
VCC 5V
TFTCS GPIO3
DC GPIO27
RST GPIO22
MOSI GPIO10 (SPI0 MOSI)
MISO GPIO9 (SPI0 MISO)
SCLK GPIO11 (SPI0 SCLK)
GND GND


小さくまとめたい場合

  1. 1x7の長さのピンソケットを作り、3番目のソケットの金具を抜きます。
  2. 金具を抜いた部分がTFTSCに、ソケットの端がDCとGNDになるようにソケットをはめてハンダつけします。
  3. オスメスジャンパワイヤを5VとGPIO3に差し込み、5VがVCCに、GPIO3がTFTSCに届く長さで切断して、はんだ付けします。


小さくまとめなくても良い場合

  1. LCDに付属のピンヘッダをはんだ付けします。
  2. LCDをブレッドボードに刺します。
  3. オスメスジャンパワイヤでRaspberry PiとLCDを接続します。


カメラを接続

カメラを使う場合は、接続しておきます。
そのうちケースを作るかもしれませんが、とりあえずテープで固定しました。
カメラのケーブルの信号線がむき出しになっている部分がRaspberry Piの基板と接触する可能性がありそうだったので、そこにもテープを貼りました。(写真右側の固定には利用していないテープ)


Raspberry Piのソフトウェア開発環境の準備

SPIとCameraの有効化

raspi-configを開き、SPIとCameraを有効にして再起動します。
sudo raspi-config
  1. Interfaces -> SPI -> YES
  2. Interfaces' -> Camera -> YES
  3. 再起動

関連プログラムのインストール

画像や文字の表示はpygameというpythonでゲームを作れるライブラリを利用します。
pythonで表示を行うため、pythonでカメラの情報を読み取るためのpicameraもインストールします。
動作確認に使う人が居るかもしれないので、gitもついでにインストールします。
sudo apt update
sudo apt upgrade
sudo apt install python3-pygame python3-picamera git

LCDの起動

fbftftというプログラムを利用して、LCDモジュールをLinuxのFaceBuffer(情報を表示する先)として利用できるようにします。
fbtftの対応LCDモジュールリストには、記事を書いている時点では今回使うLCDは入っていませんが、このLCDで使われているST7735というLCDドライバと同じものを使っているLCDはいくつかリストにある(adafruit18やsainsmart18など)ので、それを利用します。

下記のコマンドを入力すると、adafruit18としてLCDが動き始めます。
sudo modprobe fbtft_device name=adafruit18 gpios=reset:22,dc:27,cs:3 rotate=90

コマンドをが入力される前は、LCDは白いです。


コマンドが入力されてFaceBufferデバイスとして動き始めると、黒くなります。
黒いですが、バックライトは点灯しています。


この状態になったらFaceBufferのデバイスとして動いていると思います。

余談:
adafruit18は124x160pxですが、このLCDは80x160pxなので、上下(もしくは左右)それぞれ22x160pxは表示する先が無いので破棄されます。
fbtft_deviceflexfbで高さと幅を変えてみても、自分の試した範囲では、情報が破棄されるエリアを消せませんでした。
そのため、情報が破棄されるエリアを使わないように、FaceBufferへの書き込みを行う必要があります。

「画像の上部に文字を表示してるはずなのに何も出ない」という場合は、試しに画面の中央や全体に何か表示させてみると期待通りに表示されるかもしれません。

LCDに文字を表示

LCDに「Hello World!」という緑色の文字が表示されるプログラムを作りました。
hello.py
import pygame, sys, os
from pygame.locals import *
os.environ["SDL_FBDEV"] = "/dev/fb1"
pygame.init()

# set up the window
screen = pygame.display.set_mode((160, 124), 0, 32)
screen.fill((255, 255, 255))

basicfont = pygame.font.SysFont(None, 18)
text = basicfont.render('Hello World!', True, (100, 200, 100))
textrect = text.get_rect()
textrect.centerx = screen.get_rect().centerx
textrect.centery = screen.get_rect().centery
screen.blit(text, textrect)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

FaceBufferデバイスは管理者権限でないと操作できないため、管理者権限のpython3で実行します。
sudo python3 hello.py


期待通りに表示されました。

このプログラムはgithubで公開しているので、下記のようなコマンドでファイルをダウンロードして実行できます。
mkdir ~/gitptojects
cd ~/gitprojects
git clone https://github.com/asukiaaa/raspi_tft_display_camera.git
cd raspi_tft_display_camera
sudo python3 hello.py

LCDにカメラの画像を表示

カメラの画像を表示し、画像の横に「Hello World!」と表示するプログラムを作りました。

show_camera_image.py
import io, picamera, pygame, sys, os
from pygame.locals import *
os.environ["SDL_FBDEV"] = "/dev/fb1"

pygame.init()

# set up the window
screen = pygame.display.set_mode((160, 124), 0, 32)
screen.fill(0)

basicfont = pygame.font.SysFont(None, 15)
text = basicfont.render('Hello World!', True, (255, 255, 255))
textrect = text.get_rect()
#textrect.centerx = screen.get_rect().centerx
textrect.left = screen.get_rect().centerx
textrect.centery = screen.get_rect().centery
screen.blit(text, textrect)

#width = 640
#height = 480
width = 480
height= 640
rgb_buffer = bytearray(width * height * 3)
camera = picamera.PiCamera()
camera.resolution = (width, height)
camera.rotation = 90
offset = 22

# run the game loop
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    stream = io.BytesIO()
    camera.capture(stream, format='rgb')
    stream.seek(0)
    stream.readinto(rgb_buffer)
    stream.close()
    img = pygame.image.frombuffer(rgb_buffer, (width, height), 'RGB')
    img = pygame.transform.scale(img, (int(img.get_width() * 80 / img.get_height()), 80))
    #img = pygame.transform.scale(img, (80, int(img.get_height() * 80 / img.get_width())))
    #img = pygame.transform.rotate(img, -90)

    screen.blit(img, (0, offset))
    pygame.display.update()

picameraからpygameにデータを渡す部分は、AdafruitのPicamを参考にしました。
「LCDの起動」の余談にも下記ましたが、サイズの異なるLCDの実行コマンドで動作させているので、上下に22pxの表示されないエリアがあります。
そのため、表示されるエリアに収まる大きさに画像をリサイズして、22pxから22 + 80pxに収まるように表示しています。

文字を表示したプログラムと同様に、管理者権限のpython3で実行します。
sudo python3 show_camera_image.py


期待通りに表示されました。
自分の環境だと、3fpsくらいで画像が更新されているようでした。

文字を表示したプログラムと同様に、こちらのプログラムもgithubで公開しています。
文字を表示するプログラムでダウンロードしたファイルの中に含まれているので。下記のようなコマンドで実行できます。
cd ~/gitprojects/raspi_tft_camera_display
sudo python3 show_camera_image.py

自動起動設定

rc.localのexitよりも上に下記のような記述を追加すると、Raspberry Pi起動と同時にLCDへの情報表示プログラムを実行できます。
/etc/rc.local
modprobe fbtft_device name=adafruit18 gpios=reset:22,dc:27,cs:3 rotate=90
python3 /home/pi/gitprojects/raspi_tft_camera_display/show_camera_image.py &

exit 0

まとめ

小さなLCDにカメラの画像を表示できました。
今回作成したプログラムは、下記のリポジトリに公開しています。

asukiaaa/raspi_tft_display_camera

何かの参考になれば嬉しいです。


この記事の内容を参考に、物体認識装置を作ってみました。
良かったらこちらもご覧ください。

Raspberry Pi ZeroとPicameraと0.96インチLCDで物体認識装置を作ってみた

参考

Raspberry Pi 2でカラーグラフィック液晶の制御
サインスマート 1.8″ TFT カラー LCD用のグラフィックライブラリの作成
adafruit/Adafruit-ST7735-Library
Wiring & Test | Adafruit Mini TFT - 0.96" 160x80
ILI9341ベースのQVGA/SPI TFT液晶モジュールを試してみる
Sensor Modes | Picamera Hardware

0 件のコメント :