【Raspberry Pi】タッチパネル付きの 3.5 インチLCDパネルを接続してみた

はじめに

 Raspberry Pi Zero WH に接続できそうな GPIO 接続のタッチパネル付き 3.5 inch LCDを購入しました。

www.amazon.co.jp

商品説明では Pi Zero に関する記載はなかったのですが、GPIO のピン配列は他の Pi シリーズと同等のため問題ないだろうと考えて購入。実際に使用してみたところソフト的な問題で少しハマってしまいました。

製品の概要

購入した製品は Elecrow というブランドの Raspberry Pi 用タッチパネル付き 3.5 インチモバイルモニターです。Raspberry Pi の拡張端子に接続して使用するタイプの製品になっています。

f:id:rd3bit:20200902172926j:plain

パネルの機能はこんな感じです。

  • 3.5 インチ TFT パネル
  • 感圧式タッチスクリーン
  • 解像度 480 x 320 ピクセル

f:id:rd3bit:20200902173621j:plain

Pi Zero WH のとサイズ比較。

付属マニュアルが違う !?

 使用方法を確認するために同梱のマニュアルを見ます。マニュアルには接続方法やドライバーのインストール手順が書かれているので、マニュアルをしっかり読むことは大事です。

f:id:rd3bit:20200902173019j:plain

表紙にはナゼか HDMI という文字が書かれているのですが…

 内容を見てみると何か違うモノの説明が書かれています。

f:id:rd3bit:20200902173033j:plain

これ、別製品のマニュアルじゃないですか!?


GPIO 接続製品を買ったのにマニュアルは HDMI 接続品のものが入っていました。最初からこれでは、この先が心配になってきましたよ。

接続とドライバのインストール

 添付マニュアルが別製品用でインストールには役に立たないものでしたが、幸い Amazon の製品ページにインストールに必要な情報が記載されていました。

 

Amazon 商品ページ)より引用

ドライバーをインストールステップ:
Tips:Basic for Raspbian Jessie with PIXEL (2017-04-10-raspbian-jessie.img)
Step 1: Raspbian IMGファイルをダウンロード。
https://www.raspberrypi.org/downloads/raspbian/
Step 2: IMGファイルをSDカードに書き込み、次のリンクでの文章をご参照くださいませ。
https://www.raspberrypi.org/documentation/installation/installing-images/README.md
Step 3: Terminalウィンドウを開いてRPIにドライバーをダウンロード。
Run: git clone https://github.com/Elecrow-keen/Elecrow-LCD35.git
Step 4: ドライバーをインストール。
Run:
cd Elecrow-LCD35
sudo ./Elecrow-LCD35

 また、製品の詳細も商品ページに記載されているURLにありました。

 

情報も分かったところで接続します。

f:id:rd3bit:20200902173709j:plain

ピンの位置がずれないことだけに注意して接続するだけなので簡単です。

 

次にソフトウェアのインストールを行います。インストール手順書には Raspbian Jessie with PIXEL (2017-04-10-raspbian-jessie.img) が指定されていますが、さすがに古い環境なので Raspberry Pi OS (2020-08-20-raspios-buster-armhf) を使用します。

git clone https://github.com/Elecrow-keen/Elecrow-LCD35.git
cd Elecrow-LCD35
sudo ./Elecrow-LCD35

 

表示されませんよ

 インストール自体に問題は無いはずですが、液晶画面には何も表示されませんでした。

f:id:rd3bit:20200902173846j:plain

画面表示はされませんが、ssh 接続をして「xev -display :0.0」コマンドでタッチパネルのイベントを拾ってみるとパネルに触れたりパネル状をスライドしたときの情報は取れているため、接続ミスでは無いようです。

カーネルのバージョンに依存しているらしい

 商品ページやインストールガイドの記載では Raspbian Jessie を使用しているので、自分のシステム環境もJessie に変更して、再インストール。

はい、問題なく LCD に表示されました。f:id:rd3bit:20200902173945j:plain

 2020-08-20 版の Raspberry Pi OS のカーネルバージョンは 5.4 なので、カーネルのバージョンが 4.19 だった 2020-05-27 版の Raspberry Pi OS で再度挑戦してみます。

f:id:rd3bit:20200902174117j:plain

すると、LCDに表示することができました。ただし、2020-05-27 版のシステムでも apt upgrade を実行してしまうとカーネルバージョンが 5.4 に上がってしまうため LCD に何も表示されない問題が再発します。

DeviceTree の内容を調べてみる

Linuxカーネルの差分を調査するのは嫌だなーと思い、ネットで何かヒントがないか調べるためのキーワードを探る用に git clone で取得した「ドライバー」を解析してみます。

入手したファイルはドライバーといっても、内容物は設定用のコマンドと Device Tree Overlay のバイナリファイル、後はタッチパネルのキャリブレーション用ソフトの 3 点のみです。

表示ドライバ自体はRaspbian や Raspberry Pi OS のシステムに含まれていて、Device Tree Overlay で LCD 出力に必要な設定変更をしているようですね。

 

というわけで、Device Tree Overlay のファイルをソースに変換してみます。

dtc -I dtb -O dts -o elecrow35a-overlay.dts elecrow35a-overlay.dtb

ソースに変換したものがこれ ↓ です。


/dts-v1/;

/ {
	compatible = "brcm,bcm2835\0brcm,bcm2708\0brcm,bcm2709";

	fragment@0 {
		target = < 0xdeadbeef >;

		__overlay__ {
			status = "okay";

			spidev@0 {
				status = "disabled";
			};

			spidev@1 {
				status = "disabled";
			};
		};
	};

	fragment@1 {
		target = < 0xdeadbeef >;

		__overlay__ {

			waveshare35a_pins {
				brcm,pins = < 0x11 0x19 0x18 >;
				brcm,function = < 0x00 0x00 0x00 >;
				linux,phandle = < 0x01 >;
				phandle = < 0x01 >;
			};
		};
	};

	fragment@2 {
		target = < 0xdeadbeef >;

		__overlay__ {
			#address-cells = < 0x01 >;
			#size-cells = < 0x00 >;

			waveshare35a@0 {
				compatible = "ilitek,ili9486";
				reg = < 0x00 >;
				pinctrl-names = "default";
				pinctrl-0 = < 0x01 >;
				spi-max-frequency = < 0xe4e1c0 >;
				txbuflen = < 0x8000 >;
				rotate = < 0x5a >;
				bgr = < 0x00 >;
				fps = < 0x1e >;
				buswidth = < 0x08 >;
				regwidth = < 0x10 >;
				reset-gpios = < 0xdeadbeef 0x19 0x00 >;
				dc-gpios = < 0xdeadbeef 0x18 0x00 >;
				debug = < 0x00 >;
				init = < 0x10000b0 0x00 0x1000011 0x20000ff 0x100003a 0x55 0x1000036 0x28 0x10000c2 0x44 0x10000c5 0x00 0x00 0x00 0x00 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 0x1000036 0x28 0x1000011 0x1000029 >;
				linux,phandle = < 0x02 >;
				phandle = < 0x02 >;
			};

			waveshare35a-ts@1 {
				compatible = "ti,ads7846";
				reg = < 0x01 >;
				spi-max-frequency = < 0x1e8480 >;
				interrupts = < 0x11 0x02 >;
				interrupt-parent = < 0xdeadbeef >;
				pendown-gpio = < 0xdeadbeef 0x11 0x00 >;
				ti,x-plate-ohms = [ 00 3c ];
				ti,pressure-max = [ 00 ff ];
				linux,phandle = < 0x03 >;
				phandle = < 0x03 >;
			};
		};
	};

	__overrides__ {
		speed = < 0x02 0x7370692d 0x6d61782d 0x66726571 0x75656e63 0x793a3000 >;
		txbuflen = [ 00 00 00 02 74 78 62 75 66 6c 65 6e 3a 30 00 ];
		rotate = [ 00 00 00 02 72 6f 74 61 74 65 3a 30 00 ];
		fps = [ 00 00 00 02 66 70 73 3a 30 00 ];
		bgr = [ 00 00 00 02 62 67 72 3a 30 00 ];
		debug = < 0x02 0x64656275 0x673a3000 >;
		swapxy = < 0x03 0x74692c73 0x7761702d 0x78793f00 >;
	};

	__symbols__ {
		waveshare35a_pins = "/fragment@1/__overlay__/waveshare35a_pins";
		waveshare35a = "/fragment@2/__overlay__/waveshare35a@0";
		waveshare35a_ts = "/fragment@2/__overlay__/waveshare35a-ts@1";
	};

	__fixups__ {
		spi0 = "/fragment@0:target:0\0/fragment@2:target:0";
		gpio = "/fragment@1:target:0\0/fragment@2/__overlay__/waveshare35a@0:reset-gpios:0\0/fragment@2/__overlay__/waveshare35a@0:dc-gpios:0\0/fragment@2/__overlay__/waveshare35a-ts@1:interrupt-parent:0\0/fragment@2/__overlay__/waveshare35a-ts@1:pendown-gpio:0";
	};

	__local_fixups__ {
		fixup = "/fragment@2/__overlay__/waveshare35a@0:pinctrl-0:0\0/__overrides__:speed:0\0/__overrides__:txbuflen:0\0/__overrides__:rotate:0\0/__overrides__:fps:0\0/__overrides__:bgr:0\0/__overrides__:debug:0\0/__overrides__:swapxy:0";
	};
};

 Device Tree 内にある waveshare35a というキーワードからすると、恐らくは waveshare.com のこの製品がオリジナルだと考えられます。また、さらに waveshare35a でネット検索すると GitHub に dts ファイルが存在することを見つけました。

github.com

このコードの kernel 5.1 以降に対応するパッチを見ると、 gpio の極性(?)設定を変更する必要がありそうです。

そこで、waveshare35a.dtsの変更内容を参考にelecrow35a-overlay.dtbを修正してみます。

# dtb をソースに変換する
dtc -I dtb -O dts -o elecrow35a-overlay.dts elecrow35a-overlay.dtb
# 変更点 1
reset-gpios = < 0xdeadbeef 0x19 0x01 >; # 0x00 を 0x01 に書き換える
# 変更点 2
pendown-gpio = < 0xdeadbeef 0x11 0x01 >; # 0x00 を 0x01 に書き換える
# ソースを dtb に変換する
dtc -I dts -O dtb -o elecrow35a-overlay.dtb elecrow35a-overlay.dts
# 修正した dtb ファイルをインストールする
sudo ./Elecrow-LCD35

 この作業を行うことで  カーネルバージョン 5.4 の Raspberry Pi OS でも LCD 表示を行うことが可能になりました。

 f:id:rd3bit:20200902174117j:plain

おわりに

少しハマってしまいましたが何とか Raspberry Pi Zero WH + 3.5 インチ LCD + タッチパネルという環境が動作するようになりました。次は Raspberry Pi High Quality Camera を接続して遊んでみたいと考えています。