Help us understand the problem. What is going on with this article?

NanoPi-NEOと5種のLCDと2種のOLED

More than 3 years have passed since last update.

概要

NanoPi-NEOでLCDやOLEDなどいろいろ繋いで表示させてみます。
今回のターゲットは下記の通り。
既存の表示ライブラリ等は一切使わず、画像(Gray/BGRA)表示のみに特化し、C++でフルスクラッチで作ってみた。
つまり、gpio,spi,i2cすべてLinux直叩きである。

_72D0257.PNG

コントローラ IF パネルサイズ 解像度 タイプ
SSD1306 (NanoHatOLED) I2C 0.96 inch 128x64 OLED (2値)
SH1106 I2C 1.3 inch 128x64 (132x64) OLED (2値)
ILI9341 (2.2") 4wire SPI 2.2 inch 240x320 TFT LCD
ILI9341 (2.4", TouchPanel) 4wire SPI 2.4 inch 240x320 TFT LCD
ILI9328 3wire SPI ?? 2.2 inch 240x320 TFT LCD
ILI9225 4wire SPI 2.2 inch 176x220 TFT LCD
ST7735 4wire SPI 1.8 inch 128x160 TFT LCD

また、一般的にLCDやOLEDと呼ばれるのは以下の集合体のことである。

  • コントローラIC
  • OLED/LCDパネル
  • 通信信号以外の配線部

つまり、通信して表示させようとした場合、コントローラ以外の部分の仕様も影響してくる。
よくあるのが、RGB/BGRフォーマット、上下反転、左右反転、左端が欠落する。など、配線部により決定する部分である。
この場合は必要に応じソフトウェア的に対処する。

ソースコード

ソースは、こちら。
https://github.com/blue777/NanoPi-NEO

コンパイル
g++ -O3 -pthread -std=c++11 Test_display.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`

今回関連するファイルは以下の通り。

File Description
Test_display.cpp テスト用アプリ
common/ctrl_gpio.h GPIO制御用クラス
common/ctrl_i2c.h I2C制御用クラス
common/ctrl_spi.h SPI制御用クラス
common/display_if.h ディスプレイ統一IFクラス
common/display_ssd1306_i2c.h SSD1306(i2c接続版)
common/display_rgb565_spi.h SPI接続ディスプレイ用ベースクラス
common/display_ili9225_spi.h ILI9225用
common/display_ili9328_spi.h ILI9328用
common/display_ili9341_spi.h ILI9341用
common/display_st7735_spi.h ST7735用
common/img_conv.h 画像フォーマット変換用
common/img_halftone.h 誤差拡散2値化処理用

表示系IFは、display_if.hを継承使用し、統一している。
配線・デバイス依存部は、コンストラクタへ集約。

ディスプレイ統一IFのメソッドは下記の人たち。

関数名 概要
Init() デバイス初期化。表示はまだされない
GetSize() ディスプレイサイズの取得。Init()~Quit()間で有効
DispClear() 黒で全面初期化する
WriteImageGRAY(x,y,data,stride,width,height) グレー(8bit)画像の転送。x,yが転送先の位置
WriteImageBGRA(x,y,data,stride,width,height) カラー(8bit x4)画像の転送。x,yが転送先の位置
DispOn() 表示の開始
DispOff() 表示の終了
Quit() デバイスの終了

NanoPi-NEO(2)のGPIO PinLayout

本家:
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO2

以下の通りである。詳細は本家を参照してください。

Linux gpio Name Pin# Pin# Name Linux gpio
SYS_3.3V 1 2 VDD_5V
I2C0_SDA 3 4 VDD_5V
I2C0_SCL 5 6 GND
203 GPIOG11 7 8 UART1_TX/GPIOG6 198
GND 9 10 UART1_RX/GPIOG7 199
0 UART2_TX/GPIOA0 11 12 GPIOA6 6
2 UART2_RTS/GPIOA2 13 14 GND
3 UART2_CTS/GPIOA3 15 16 UART1_RTS/GPIOG8 200
SYS_3.3V 17 18 UART1_CTS/GPIOG9 201
64 SPI0_MOSI/GPIOC0 19 20 GND
65 SPI0_MISO/GPIOC1 21 22 UART2_RX/GPIOA1 1
66 SPI0_CLK/GPIOC2 23 24 SPI0_CS/GPIOC3 67

OLED系

今回はSSD1306とSH1106の2種。
コマンドは、ほぼ共通でSSD1306の方が高機能になっており、描画コマンドも多い。

SSD1306 (NanoHatOLED - i2c 接続)

概要

入手元:
http://www.friendlyarm.com/index.php?route=product/product&product_id=191
$6.99

インスタンス生成:
Display_SSD1306_i2c(180); // for SSD1306

image.png

配線

NanoHatOLEDなので、NanoPi-NEO(2)に載せるだけ。
回路図は以下にあるが、制御に必要となる信号線は4本のみである。
http://wiki.friendlyarm.com/wiki/images/c/c3/SCHEMATIC_NanoHat_OLED-1703_v1.0.pdf

SH1106 (i2c接続)

概要

入手元:
https://www.amazon.co.jp/gp/product/B01MF97E87/ref=oh_aui_detailpage_o05_s00?ie=UTF8&psc=1
¥720

ソースコードもSSD1306と共通で、Display_SSD1306_i2c(rotate,xoffset) の、xoffset=2を設定すれば問題なく動く

インスタンス生成:
Display_SSD1306_i2c(180,2); // for SH1106

image.png

配線

SPI版もあるが今回はi2c接続版のため下記の通り接続すればOK

SH1106 (i2c) NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin#
VCC SYS_3.3V 1
GND GND 9
SCL I2C0_SCL 5
SDA I2C0_SDA 3

LCD系

一般的な4wire SPI接続であれば、以下の7本が必要となる。
(LCDコントローラチップからのデータ読み出し行う場合は+1本)

  • VCC
  • GND
  • D/C (Data/Command select。GPIOで個別制御)
  • RESET (リセット信号。GPIOで個別制御)
  • SPI0_CLK (クロック)
  • SPI0_MOSI (データ)
  • SPI0_CS (Chip select)

ソースコードでは、上記に加えバックライトOn/Off制御用に1本追加となる。
SPI0_MISO/GPIOC1はSPI通信のデータ受信用だが、データ受信しないため、バックライト制御用GPIOとして使用する。
NanoPi-NEO(2)のGPIO PinLayoutを元に、配線を集中させるよう検討した結果、下側の8本(Pin#17~24)に完結できた。(笑

バックライト制御

上記ソースコードでは、DispOn/DispOff でバックライト制御もできるようにGPIO出力している。
通常、バックライトは WhiteLED のため、3.3vの電源でそのまま使用できる(ことが多い)。
接続例に分けて4種類記載してみる。
工作といえど、バックライトOn/Off制御は見栄えが良い(笑

そもそも制御しない

ソースコードでは、GPIOポートに-1を設定すればGPIO制御が無効化できるようにしています。
バックライトのLEDは直接電源に接続すればOK。

GPIO直接制御版

GPIOの出力電流で十分賄える場合である。
例えば、NanoPi-NEO(2)の場合、最大20mA出力できる模様。
20mAに収まるLCDパネルのバックライトであれば、そのまま接続でOK.

LEDのカソード(-)側で制御

100mA未満であれば、希少品の2SC1815で十分かな。
回路図は一般的な工作例なので、本気組の方はLTSpice等でちゃんと設計しましょう。

image.png

LEDのアノード(+)側で制御

100mA未満であれば、希少品の2SC1815と2SA1015で十分かな。
回路図は一般的な工作例なので、本気組の方はLTSpice等でちゃんと設計しましょう。

image.png

ILI9341 (240x320, 2.2inch)

概要

入手元:
https://www.amazon.co.jp/gp/product/B01CZL6QIQ/ref=oh_aui_detailpage_o03_s00?ie=UTF8&psc=1
¥980

軽く見てみた限り、割と有名なチップ。
QVGA対応なので、ほぼ標準品的な位置づけであるとも言えるかもしれない。
また、液晶パネルサイズも、2.2inch, 2.4inch, 2.8inch, 3.2inchとバリエーション豊かである。

インスタンス生成:
Display_ILI9341_spi_TM22(0); // for Tianma2.2" Panel

image.png

配線

バックライトLEDをGPIOでOn/Offする場合の結線方法である。
SPI0_MISO/GPIOC1はSPI通信のデータ受信側だが、データ受信しないため、GPIOとして使用する。
On/Off制御が不要な場合は、LEDをSYS_3.3Vへ繋げば良い。

ILI9341 NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin# 備考
SDO/MISO - - LCDのデータ読むときに必要
LED LEDのアノード(+)側で制御 21 SPI0_MISO/GPIOC1 (gpio65) Pin#21で制御
SCK SPI0_CLK/GPIOC2 23
SDI/MOSI SPI0_MOSI/GPIOC0 19
DC/RS UART2_RX/GPIOA1 22 D/C制御用GPIO (gpio1)
RESET UART1_CTS/GPIOG9 18 Reset制御用GPIO (gpio201)
CS SPI0_CS/GPIOC3 24
GND GND 20
VCC SYS_3.3V 17

バックライトについて

バックライトの消費電流 : 2.45mA @ 3.3v

SYS_3.3Vに接続ででOnになる。
消費電流的に制御回路入っている模様なので、GPIO直接ドライブでもOK.
ただし、知らぬ間に仕様変更されることもあるので、基本的には、LEDのアノード(+)側で制御 で制御するのが無難

ILI9341 (240x320, 2.4inch, TouchPanel)

概要

入手元:
https://www.amazon.co.jp/gp/product/B071KBS7MD/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
¥890

タッチパネル付きだけど、今回タッチパネルは使用しない。
そして、タッチパネルICの仕様もまったくもって不明である。

インスタンス生成:
Display_ILI9341_spi_TM24(180); // for Tianma2.4" Panel

image.png

配線

ILI9341 2.4" Touch NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin# 備考
T-IRQ - - TouchPanel関係
T-DO - - TouchPanel関係
T-DIN - - TouchPanel関係
T-CS - - TouchPanel関係
T-CLK - - TouchPanel関係
SDO - - LCDのデータ読むときに必要
LED LEDのアノード(+)側で制御 SPI0_MISO/GPIOC1 (gpio65) Pin#21で制御
SCK SPI0_CLK/GPIOC2 23
SDI(MOSI) SPI0_MOSI/GPIOC0 19
D/C UART2_RX/GPIOA1 22 D/C制御用GPIO (gpio1)
RESET UART1_CTS/GPIOG9 18 Reset制御用GPIO (gpio201)
CS SPI0_CS/GPIOC3 24
GND GND 20
VCC SYS_3.3V 17

バックライトについて

バックライトの消費電流 : 63.3mA @ 3.3v

SYS_3.3Vに接続ででOnになる。
Gpio制御する場合は「LEDのアノード(+)側で制御」が必要。

ILI9328 (240x320, 2.4inch)

概要

入手元:
http://www.aitendo.com/product/10943
¥1750

制御コマンド系は、ILI9341,ST7335系(8bit系)とは異なる。
また、ILI9225(16bit系)とも異なる。
4wireSPIではなく、3wire接続タイプとなる。
D/Cが無い代わりに、StartCodeを1byteつけて送る必要がある。

インスタンス生成:
Display_ILI9328_spi_TM22(0);

image.png

配線

ILI9328 NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin# 備考
D_SDO - - LCDのデータ読むときに必要
D_LED LEDのカソード(-)側で制御 SPI0_MISO/GPIOC1 (gpio65) Pin#21で制御
D_SCK SPI0_CLK/GPIOC2 23
D_SDI SPI0_MOSI/GPIOC0 19
D_RS UART2_RX/GPIOA1 22 D/C制御用GPIO (gpio1)
D_/RST UART1_CTS/GPIOG9 18 Reset制御用GPIO (gpio201)
D_CS SPI0_CS/GPIOC3 24
D_GND GND 20
VCC_IN SYS_3.3V 17

D_LEDをGPIO制御しない場合は、GNDに落とすと常時Onになる。

バックライトについて

バックライトの消費電流 : 53.9mA @ 3.3v

GND接地でOnになる。
Gpio制御する場合は「LEDのカソード(-)側で制御」が必要。

ILI9225 (176x240, 2.2inch)

概要

入手元:
https://www.amazon.co.jp/gp/product/B010SHM2E6/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
¥750

制御コマンド系は、ILI9341,ST7335系(8bit系)とは異なる。
また、ILI9328(16bit系)とも異なる。

インスタンス生成:
Display_ILI9225_spi(180); // for basic ILI9225

image.png

配線

ILI9225 NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin# 備考
VCC SYS_3.3V 17
GND GND 20
GND
NC
NC
LED LEDのアノード(+)側で制御 21 SPI0_MISO/GPIOC1 (gpio65) Pin#21で制御
CLK SPI0_CLK/GPIOC2 23
SDI SPI0_MOSI/GPIOC0 19
RS UART2_RX/GPIOA1 22 D/C制御用GPIO (gpio1)
RST UART1_CTS/GPIOG9 18 Reset制御用GPIO (gpio201)
CS SPI0_CS/GPIOC3 24

バックライトについて

消費電力は、0.01mA未満。測定限界以下。

SYS_3.3Vに接続ででOnになる。
消費電流の少なさは、FET入力か何かなのでしょう。
なお、バックライト点灯させた状態におけるLCD全体の消費電流は、44mA @ 3.3v であった。

ST7735 (128x160, 1.8inch)

概要

入手元:
https://www.amazon.co.jp/gp/product/B010SHK0Y0/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1
¥480

インスタンス生成:
Display_ST7735_spi(180); // for KMR1.8

image.png

配線

ST7735 NanoPi-NEO(2) PinName NanoPi-NEO(2) Pin# 備考
LED- - - 実はGNDに繋がっている。
LED+ LEDのアノード(+)側で制御 - SPI0_MISO/GPIOC1 (gpio65) Pin#21で制御
SD_CS - -
MOSI - -
MISO - - LCDのデータ読むときに必要
SCK - -
CS SPI0_CS/GPIOC3 24
SCL SPI0_CLK/GPIOC2 23
SDA SPI0_MOSI/GPIOC0 19
AO UART2_RX/GPIOA1 22 D/C制御用GPIO (gpio1)
RESET UART1_CTS/GPIOG9 18 Reset制御用GPIO (gpio201)
NC -
NC -
NC -
VCC SYS_3.3V 17
GND GND 20

バックライトについて

バックライトの消費電流 : 35.00mA @ 3.3v

SYS_3.3Vに接続ででOnになる。
Gpio制御する場合は「LEDのアノード(+)側で制御」が必要。

LED-をGNDに、LED+をGPIOに繋ぎ直ドライブすると、かなり暗く、
消費電力を測ってみたところ、7.18 [mA] であった。
かなりな電力不足である。
(過電流でCPU側が壊れるかもしれないので、あまりやらないように)

まとめ

  • ST7735, ILI9341 はCommand長が8bitであり、基本コマンドはかなり共通している。
  • ILI9225, ILI9328 は、Command長が16bitであり、ILI9325とも比較してみたが、共通コマンドはあるものの、ほとんどが不統一の状態。チップ毎に制御コード書かないとイケナイ。
  • 各種LCDパネルには、パネル固有値(ガンマテーブル、制御電圧値)があるが、そもそもパネルの素性がメーカー名すらも不明な状態のため、何が正しいデータなのかもわからない。
  • 上記4つの赤基板LCDパネルの視野角は、かなり狭い。。。ちゃんとした物が欲しい場合は、数打たなければいけない。
  • LCDパネルには、バックライトが直接GPIO制御できるよう増幅回路が入っているものもあり、非常に便利!
  • SPI通信速度はパネルによっては、仕様の10MHz以上に設定できるものもあり、表示フレームレートを稼ぐことができる。

    • 例えば、240x320 で40MHz駆動の場合 $40[MHz] / (320[pix]*240[pix]*16[bit]) = 32.55 [fps]$ が理論値。
    • しかし実測は、主にSPIドライバのオーバヘッドで、9fps程度しか出ない
    • 80MHz(表示は崩れるが)で駆動しても、11.5fps 程度。誰かSleepしてる?あるいはioctlがネック?
  • Aitendo購入のILI9328コントローラの液晶、これらLCDの中では一番視野角が広く、左右80度、上下30度程度内で色変化がほぼ無い。

    • しかしNanoPi-NEOでは、なぜか動かせなかった。(NEO2はすんなり動いた。NEOで深い追いはしていないので、再度実施すれば、動くかもしれないし、動かないかもしれない)
    • たまに、コマンドあるいはStartCodeの取りこぼしするときがある。その結果、描画されないなどの現象が稀に発生している。SCLクロックが速すぎ。というわけでも無さそうなので、CSタイミングの問題かも。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away