📺
ILI9488をRaspberry Pi Zeroで動かしたら苦戦した話
事の発端
- ILI9488買った
- Raspberry Pi Zeroで使いたいな
- なんかできない
- !?!?!??
結果
いろいろいじったらできた
この手のものはラズパイ3以前と4以降でどうもSPIの動きが違うらしく、それのせいだと思う(ラズパイ4持ってないので実験はしてない)
やり方
ライブラリとラズパイの準備
RPi.GPIOとspidevが必要なのでこれを入れる
pip install RPi.GPIO spidev
SPIはraspi-configで有効にしておく
配線
LCD | Rasp GPIO |
---|---|
VCC | 3.3V |
GND | GND |
CS | 8 |
RST(RESET) | 25 |
DC(D/C) | 24 |
SDI(MOSI) | 10 |
CLK,SCK(CLOCK) | 11 |
コード
raspi_ili9488.py
import RPi.GPIO as GPIO
import spidev
import time
### Raspberry PiのGPIOピンのセッティング
DC = 24
RST = 25
CS = 8
LED = 18
### GPIO開始制御
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(DC, GPIO.OUT)
GPIO.setup(RST, GPIO.OUT)
GPIO.setup(CS, GPIO.OUT)
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, GPIO.HIGH) # バックライトON
### SPI開始制御
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 10000000 # 10MHzで安定した 不安な場合は2MHz程度がいい
spi.mode = 0
### LCDの低レベル信号制御
def lcd_write_cmd(cmd):
GPIO.output(CS, GPIO.LOW)
GPIO.output(DC, GPIO.LOW)
spi.writebytes([cmd])
GPIO.output(CS, GPIO.HIGH)
def lcd_write_data(data):
GPIO.output(CS, GPIO.LOW)
GPIO.output(DC, GPIO.HIGH)
if isinstance(data, int):
spi.writebytes([data])
else:
# 大きなバッファは分割して送信
# 大きくするほど早くなるかもしれないけど不安定になるので注意
chunk_size = 4092
for i in range(0, len(data), chunk_size):
spi.writebytes(data[i:i+chunk_size])
GPIO.output(CS, GPIO.HIGH)
def lcd_reset():
GPIO.output(RST, GPIO.LOW)
time.sleep(0.12)
GPIO.output(RST, GPIO.HIGH)
time.sleep(0.12)
### 初期化シーケンス
def lcd_init():
lcd_reset()
lcd_write_cmd(0xE0)
lcd_write_data([0x00,0x03,0x09,0x08,0x16,0x0A,0x3F,0x78,0x4C,0x09,0x0A,0x08,0x16,0x1A,0x0F])
lcd_write_cmd(0xE1)
lcd_write_data([0x00,0x16,0x19,0x03,0x0F,0x05,0x32,0x45,0x46,0x04,0x0E,0x0D,0x31,0x37,0x0F])
lcd_write_cmd(0xC0)
lcd_write_data([0x17,0x15])
lcd_write_cmd(0xC1)
lcd_write_data([0x41])
lcd_write_cmd(0xC5)
lcd_write_data([0x00,0x12,0x80])
lcd_write_cmd(0x36)
lcd_write_data([0x48])# LCDのRGBと回転の命令 ※1
lcd_write_cmd(0x3A)
lcd_write_data([0x66])
lcd_write_cmd(0xB0)
lcd_write_data([0x00])
lcd_write_cmd(0xB1)
lcd_write_data([0xA0])
lcd_write_cmd(0xB4)
lcd_write_data([0x02])
lcd_write_cmd(0xB6)
lcd_write_data([0x02,0x02])
lcd_write_cmd(0x11)
time.sleep(0.12)
lcd_write_cmd(0x29)
### 画面塗りつぶし
def fill_color(r, g, b):
width, height = 320, 480
# カラム設定
lcd_write_cmd(0x2A)
lcd_write_data([0,0,(width-1)>>8,(width-1)&0xFF])
# ロウ設定
lcd_write_cmd(0x2B)
lcd_write_data([0,0,(height-1)>>8,(height-1)&0xFF])
# メモリ書き込み
lcd_write_cmd(0x2C)
# 24bitカラーを18bitカラーに強制的にする
# それぞれ8bitから2bitずつ落として6bitにする
color_bytes = [r & 0xFC, g & 0xFC, b & 0xFC]
block_size = 1024 # 一度に送るピクセル数
total_pixels = width * height
buf = color_bytes * block_size
sent = 0
while sent < total_pixels:
to_send = min(block_size, total_pixels - sent)
lcd_write_data(buf[:to_send*3])
sent += to_send
### メイン実行
if __name__ == "__main__":
try:
lcd_init()
fill_color(255,0,0) # 赤
time.sleep(2)
fill_color(0,255,0) # 緑
time.sleep(2)
fill_color(0,0,255) # 青
time.sleep(2)
finally:
GPIO.cleanup()
※1について
ILI9488の製造上の問題なのか使われているロジックチップが違うからなのか、このままだと正しく表示されないことがあります。
物によって設定が変わるので、自分で調整してみてください。
値 | 向き |
---|---|
0x00 | 標準向き |
0x28 | 90°回転 |
0x48 | 90°回転 + RGB順 |
0x88 | 180°回転 |
0xE8 | 270°回転 + RGB順 |
こいつ!動くぞ!!
トラブルシューティング
Q1. 動かない、サンドストーム状態
A1. ILI9488じゃない可能性がある。同じ3.5inchのLCDでもILI9486の場合もあるから要注意
Q2. 画面が光らない
A2. 多分壊れているか、LEDに3.3Vが入っていない。raspi-configでSPIは有効になってる?SPIの配線は間違えていないかチェック。
Q3. 画面に半分しか表示されない
A3. ※1を参照して
Q4. RGBのカラーが反対になる
A4. ※1を参照して
文句
そもそもaliexpressで買うとなんで同じ見た目なのにこうも仕様が変わるのかわからないし、そもそもほかのILI系統を問題なくraspiで動かしてる人たちを見てやったのになぜかできなくて故障を疑った。
最終的に一番よく動いてくれたTFT_eSPIのライブラリをパクってやったらなんか動いてしまって、いろいろ調整してここまでもっていった。
ぼくの調べまくった時間を返してほしい。
Discussion