中国のお店が中国国外に売る通販モールAliExpressで、激安の小型IPS液晶ディスプレイを買いました。
サイズは1.3インチ、解像度は240x240px、65万色対応だそうです。液晶コントローラとしてST7789VWというLSIが搭載されており、SPIで制御できます。
小型でちょっとした情報を表示するのに便利そうですね🥰
おそらく、Amazon.co.jpで売られているこちらのものと類似品だと思います。基板のシルク印刷が微妙に違いますが、ピン配置等は同じように見えます。
AliExpressでの私が購入時の値段は、なんと$2.30でした!300円しないのでお買い得ですね。
このディスプレイもPythonから簡単にアクセスできるライブラリを公開されている方がいて、ドライバを書かずとも簡単に好きなものが表示できます。 とても便利ですね🥰早速Raspberry Piにつないでみましょう。
Raspberry Piに接続
購入した小型液晶ディスプレイ
こんな感じのものが届きました。画面についていた保護シールははがしています。 ピンヘッダもついていて、はんだ付けなしでジャンパワイヤーなどを使って簡単にRaspberry Piに接続できます。
Raspberry Piにつないでみよう
Raspberry Piのピンヘッダは上図のように機能が割り当てられています。 このモジュールはSPIで通信しますが、そのほかにも制御線をつなぐ必要があります。 SPI以外はどのGPIOでも良い(Pythonプログラムで指定可)のですが、以下のようにしてみました。
RasPiピン番号 | RasPi 機能 | 液晶ディスプレイ | 説明 |
---|---|---|---|
17 | 3V3 power | VIN | 電源(3.3V) |
19 | MOSI | SDA | SPIデータ(Raspi→液晶) |
23 | SCLK | SCK | SPIクロック |
25 | GND | GND | グランド(基準電圧0V) |
29 | GPIO5 | RES | 液晶リセット信号 |
31 | GPIO6 | DC | 液晶データ・コマンド選択 |
33 | GPIO13 | BLK | バックライトON/OFF |
バックライトON/OFFは、制御しなければ何も接続しなくて大丈夫でした。 内部でプルアップされており、接続しなければ常時ONになるみたいです。 私は接続無しで使ってみました。
これらをジャンプワイヤーで接続すると、次のようになりました。
SPI通信について
今回はRaspberry PiがSPIコントローラ、液晶ディスプレイがSPIペリフェラルになります(ペリフェラルというのは、周辺機器というような意味です)。 SPIコントローラがクロックを出して通信をリードします。
SPI通信はSCLK(クロック)、SDO(データ出力)、SDI(データ入力)、CS(チップ選択)の4つの信号を使って通信します。 I2Cと違って、入力と出力用にそれぞれ信号線が用意されています。複数のデバイスで信号線を共有できるようにCS(チップ選択)線があり、 コントローラが通信したい相手を選んでCSをLow(0)にして、デバイスと通信します。
この液晶ディスプレイはコントローラからの信号を受けるだけで自分は何も出力しないので、信号線を片方向(MOSI)だけ使うようになっています。 なので、データ線が1本しか出ていません。
さらに、CSはピンが出ておらず、内部的にLowに落とされているようで、常時選択状態になっています。 つまり、このSPI信号線を独占してしまっています。 この液晶と同時に他のSPIペリフェラルを使うことはできません。
なお、以前はコントローラのことをマスター(ご主人様)、ペリフェラルをスレーブ(奴隷)といい、 信号線もMOSI(マスター出力スレーブ入力)、MISO(マスター入力スレーブ出力)と言っていましたが、 ご主人様が奴隷を使うイメージで例えるのは良くないということで、2020年ごろから名称が変わってきています。
Raspberry Piの準備
SPIの有効化
Raspberry Pi OSのインストール直後はSPIが無効になっていて、そのままでは使えません🙅♀️
有効化するには、raspi-config
のメニューから設定できます。
$ sudo raspi-config
で設定画面を起動し、"5 Interfacing Options" → "P4 SPI" → "Yes" を選択してください。
Pythonで表示させてみよう
Pythonライブラリーのインストール
イギリスで教育用ハードウェアなどを開発しているPimoroni社がPythonライブラリーを開発しています。
これを使うと簡単に表示できます。
$ sudo apt-get install python3-rpi.gpio python3-spidev python3-pip python3-pil python3-numpy $ pip3 install st7789
基本的な使い方
基本的な使い方から見ていきましょう。まず、
$ python3
でPythonのシェルを起動します。起動したら、必要なライブラリを読み込みます。
>>> import ST7789 >>> from PIL import Image
1つのST7789が先ほど紹介したこの液晶ディスプレイ用のライブラリです。 2つめはPillow (PIL)という有名なPython画像処理ライブラリです。 実はこのST7789ライブラリはPillowで生成した画像を表示するライブラリとなっているので、Pillowが必要です。
続いて、ST7789のインスタンスを作成します。
>>> disp = ST7789.ST7789(port=0, cs=0, rst=5, dc=6, backlight=None, spi_speed_hz=80 * 1000 * 1000)
引数ですが、port
でSPIのポートを指定します。Raspberry Piのピンヘッダが出ているのは0番なので、0を指定します。
続いてcs
のピン番号ですが、この液晶ディスプレイにはCSピンが無いので使いません。とりあえず0にしておきます。
rst
はリセット端子をGPIO5につないでいるので、5にします。同様にdc
にデータ・コントロール選択端子を指定します。
GPIO6につないでいるので6です。backlight
はバックライト制御端子を接続した場合は同様に指定します。
接続していない場合はNoneでOKです。
最後にspi_speed_hz
ですが、SPIクロックの速度を指定します。ここではライブラリのサンプルにあった通り80MHzにしています。
ジャンプワイヤーでつないでいるのにこんな高速で大丈夫かな?🤔とも思いましたが、動いたのでとりあえずそのままにしました。
このライブラリでは、インスタンス作成時にディスプレイのリセットを行い、初期化コマンドを送信して液晶ディスプレイをONにするようです。
次に、表示する画像を用意しましょう。まずは単純に、全面を色で塗りつぶしてみます。
>>> image = Image.new("RGB", (disp.width, disp.height), (102, 187, 106))
これでPillowの機能を使って画面サイズ分の緑色の画像を作成しました。色は最後の引数のタプルで指定し、ここではR=102, G=187, B=106です。 いよいよ表示してみましょう。
>>> disp.display(image)
ST7789インスタンスのdisplay()
メソッドの引数に、Pillowの画像を渡すとそれを表示してくれます。
このように、緑色1色で塗りつぶされました…となるはずが、私の場合はうまくいかず、画面が真っ黒のままでした😢
SPI Mode変更
色々調べたところ、私の買った液晶ディスプレイはSPI Mode 0(ライブラリのデフォルト)だとタイミングの問題でデータが取れないのか使えず、SPI Mode 3にすると描画できました。
Google検索するとそういう人もいたので、同じようなST7789搭載液晶ディスプレイでもいろんなバリエーションがあるのかもしれません。
ちなみにSPIのMODEとは、クロックとデータ取り込みのタイミングを規定するもので、Mode 0~3まで4種類あります。
このライブラリはSPI Modeを変更するインターフェースが無いので、以下のように中のプライベート変数を直接いじって動かしました。
import ST7789 from PIL import Image # Create a display instance disp = ST7789.ST7789(port=0, cs=0, rst=5, dc=6, backlight=None, spi_speed_hz=80 * 1000 * 1000) # Added: Change to SPI MODE 3 disp._spi.mode = 3 disp.reset() disp._init() # Create a green image image = Image.new("RGB", (disp.width, disp.height), (67, 160, 71)) # Show it on display disp.display(image)
私の場合はこれで問題なく表示できました。 もし似たような液晶ディスプレイを買って動かなかった方は試してみてください。
いろいろ表示させてみよう
せっかくなので、いろんなものを表示させてみましょう。 Pillowを使って描画できれば、何でも表示できます。
画像の表示
やっぱり液晶があると、美しい画像を表示させたいですね。ということで、ネットにある美しい画像を拾ってきましょう。
$ wget https://cdn-ak.f.st-hatena.com/images/fotolife/k/kimura_khs/20210110/20210110170457.jpg
次のようにして簡単に表示させられます。
import ST7789 from PIL import Image # Create a display instance disp = ST7789.ST7789(port=0, cs=0, rst=5, dc=6, backlight=None, spi_speed_hz=80 * 1000 * 1000) # Added: Change to SPI MODE 3 disp._spi.mode = 3 disp.reset() disp._init() # Open image file image = Image.open("20210110170457.jpg") # Resize to screen size image = image.resize((disp.width, disp.height), resample=Image.LANCZOS) # Show it on display disp.display(image)
これをファイルに保存し、実行すると次のようになりました。
奈良にある東大寺 二月堂の写真です。元の写真が縦横比1:1でないため横が縮小されてしまっていて申し訳ないのですが、表示できていますね。
ちなみに、この写真は私が撮影した写真です😆
文字の表示
Pillowがあれば、OpenType/TrueTypeフォントで文字も書けます。 フォントをダウンロードしてみましょう。
$ sudo apt install fonts-noto-cjk fonts-roboto
プログラムは以下のようになります。
import ST7789 from PIL import Image, ImageDraw, ImageFont # Create a display instance disp = ST7789.ST7789(port=0, cs=0, rst=5, dc=6, backlight=None, spi_speed_hz=80 * 1000 * 1000) # Added: Change to SPI MODE 3 disp._spi.mode = 3 disp.reset() disp._init() # Define fonts FONT_ROBOTO = ImageFont.truetype("Roboto-Medium.ttf", 24) FONT_NOTO = ImageFont.truetype("NotoSansCJK-Regular.ttc", 48) # Define colors COLOR_ORANGE = (255, 167, 38) COLOR_GREEN = (129, 199, 132) # Create an image with black background image = Image.new("RGB", (disp.width, disp.height), (0, 0, 0)) # Draw some text draw = ImageDraw.Draw(image) draw.text((0, 0), "みかんの", font=FONT_NOTO, fill=COLOR_ORANGE) draw.text((48, 48), "ゆるふわ", font=FONT_NOTO, fill=COLOR_ORANGE) draw.text((0, 96), "技術ブログ", font=FONT_NOTO, fill=COLOR_ORANGE) draw.text((0, 160), "www.mikan-tech.net", font=FONT_ROBOTO, fill=COLOR_GREEN) # Show it on display disp.display(image)
これで、文字も表示できるようになりました。
やはりカラー表示できるのは便利ですね。 文字や画像を組み合わせて、ちょっとした情報をカッコよく表示できるので、皆様もぜひDIYなどにお使いください!