だいぶ前に買った2.4インチTFT液晶ディスプレイ
あれはまだArduinoが流行りだした黎明期。 バンコクの秋葉原ことバンモー地区でこの液晶ディスプレイを見つけた。
商品名は、2.4" TFT LCD Shield+Touch Panel Display With SD Reader for Arduino UNO と書かれている。
値段は370バーツ。 今となっては高い気もするが、当時では安く感じたので買ったのだろう。
で、付属品はタッチペンのみ。 そう、説明書もソフトウェアも何もない。
裏面を見ると、Arduino UNOの入出力ポートと合うように配置されたピンがある。 つまりはこれをArduino UNOにパイルダーオンさせて使うようになっている。
もちろん繋げたからってすぐに使わるわけではない。 当時はまだ情報も少なかったから苦労したが、どうやらこのディスプレイの制御ICは"ILI9341"っぽいことがわかった。 定番っちゃ定番よね。
後はライブラリなどのソフトウェアをダウンロードしてインストールしてプログラミングすればよい。 だけだと終わっちゃうので、どれだけ道を外した使い方ができるか。 そこを徹底的に検証していきたい。 サンプルプログラムだけを動かして満足するキャッスルではないのだよ。
さて、商品名にも書かれているとおり、Arduino UNO で使う事を前提に設計されている。 このUNOは当然だがUNO R3のことだ。 なのでArduino UNO R4では動かない、というかコンパイルすらできない。 まずはUNO R4で動くようにしてみようと思う。
ILI9341ドライバーのライブラリをインストールすると、サンプルプログラムがいくつか入っている。 ほとんどのサンプルは、超便利ライブラリのAdafruit_GFX.hをつかっているのだが、最初のサンプルだけは一切ライブラリを使うことなく、全てをマニュアルで制御している。 うん、これだ。 やっぱオートマよりマニュアルの方が技術は上がるっていうしね。
マニュアル制御で用意されているサンプルプログラムは、Arduino UNO R3用とMEGA2560用の二つ。
それをチャチャチャーっと改造して、とりあえずオールマイティプログラムにしてみた。 プログラム自体は下に掲載しておく。
オールマイティと言うのには理由があって、このディスプレイと接続できるArduinoボードの何でも使えるようになっているから。
キャッスルが検証した中では、
Arduino UNO R3
Arduino MEGA2560
Arduino DUE
Arduino UNO R4 MINIMA
Arduino UNO R4 WiFi
の全てで動作は確認できた。 一応はね・・・
プログラムの内容は、ディスプレを初期化して、全画面ベタ塗りで5色、ランダムの大きさの4角形を300回描画、その処理にかかった時間をシリアルモニターで表示。
これからの検証はこのサンプルプログラムを基準にしていこうと思う。
#define LCD_RD A0 #define LCD_WR A1 #define LCD_RS A2 #define LCD_CS A3 #define LCD_REST A4 void Lcd_Writ_Bus(unsigned char d) { digitalWrite(8, d & B00000001); digitalWrite(9, d & B00000010); digitalWrite(2, d & B00000100); digitalWrite(3, d & B00001000); digitalWrite(4, d & B00010000); digitalWrite(5, d & B00100000); digitalWrite(6, d & B01000000); digitalWrite(7, d & B10000000); digitalWrite(LCD_WR, LOW); digitalWrite(LCD_WR, HIGH); } void Lcd_Write_Com(unsigned char VH) { digitalWrite(LCD_RS, LOW); Lcd_Writ_Bus(VH); } void Lcd_Write_Data(unsigned char VH) { digitalWrite(LCD_RS, HIGH); Lcd_Writ_Bus(VH); } void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2) { Lcd_Write_Com(0x2a); Lcd_Write_Data(x1>>8); Lcd_Write_Data(x1); Lcd_Write_Data(x2>>8); Lcd_Write_Data(x2); Lcd_Write_Com(0x2b); Lcd_Write_Data(y1>>8); Lcd_Write_Data(y1); Lcd_Write_Data(y2>>8); Lcd_Write_Data(y2); Lcd_Write_Com(0x2c); } void Lcd_Init(void) { digitalWrite(LCD_REST, HIGH); delay(5); digitalWrite(LCD_REST, LOW); delay(15); digitalWrite(LCD_REST, HIGH); delay(15); digitalWrite(LCD_CS, HIGH); digitalWrite(LCD_WR, HIGH); digitalWrite(LCD_CS, LOW); Lcd_Write_Com(0xCB); //Power control A (CBh) Lcd_Write_Data(0x39); Lcd_Write_Data(0x2C); Lcd_Write_Data(0x00); Lcd_Write_Data(0x34); Lcd_Write_Data(0x02); Lcd_Write_Com(0xCF); //Power control B (CFh) Lcd_Write_Data(0x00); Lcd_Write_Data(0X81); Lcd_Write_Data(0X30); Lcd_Write_Com(0xE8); //Driver timing control A (E8h) Lcd_Write_Data(0x84); Lcd_Write_Data(0x11); Lcd_Write_Data(0x7A); Lcd_Write_Com(0xEA); //Driver timing control B (EAh) Lcd_Write_Data(0x66); Lcd_Write_Data(0x00); Lcd_Write_Com(0xED); //Power on sequence control (EDh) Lcd_Write_Data(0x55); Lcd_Write_Data(0x01); Lcd_Write_Data(0X23); Lcd_Write_Data(0X01); Lcd_Write_Com(0xF7); //Pump ratio control (F7h) Lcd_Write_Data(0x10); Lcd_Write_Com(0xC0); //Power control Lcd_Write_Data(0x23); //VRH[5:0] Lcd_Write_Com(0xC1); //Power control Lcd_Write_Data(0x10); //SAP[2:0];BT[3:0] Lcd_Write_Com(0xC5); //VCM control Lcd_Write_Data(0x3e); //Contrast Lcd_Write_Data(0x28); Lcd_Write_Com(0xC7); //VCM control2 Lcd_Write_Data(0x86); //-- Lcd_Write_Com(0x36); // Memory Access Control Lcd_Write_Data(0x48); Lcd_Write_Com(0x21); //Display Inversion ON Lcd_Write_Com(0x3A); Lcd_Write_Data(0x55); Lcd_Write_Com(0xB1); Lcd_Write_Data(0x00); Lcd_Write_Data(0x18); Lcd_Write_Com(0xB6); // Display Function Control Lcd_Write_Data(0x08); Lcd_Write_Data(0x82); Lcd_Write_Data(0x27); Lcd_Write_Com(0x11); //Exit Sleep delay(120); Lcd_Write_Com(0x29); //Display on } void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) { unsigned int i, j; digitalWrite(LCD_RS, HIGH); digitalWrite(LCD_CS, LOW); l = l + x; Address_set(x, y, l, y); j = l * 2; for(i = 1; i <= j; i++) Lcd_Write_Data(c); digitalWrite(LCD_CS, HIGH); } void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) { unsigned int i, j; digitalWrite(LCD_RS, HIGH); digitalWrite(LCD_CS, LOW); l = l + y; Address_set(x, y, x, l); j = l * 2; for(i = 1; i <= j; i++) Lcd_Write_Data(c); digitalWrite(LCD_CS, HIGH); } void Rect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c) { H_line(x , y , w, c); H_line(x , y+h, w, c); V_line(x , y , h, c); V_line(x+w, y , h, c); } void LCD_Clear(unsigned int j) { unsigned int i,m; digitalWrite(LCD_RS, HIGH); digitalWrite(LCD_CS, LOW); Address_set(0, 0, 239, 319); for(i = 0; i < 240; i++) for(m = 0; m < 320; m++){ Lcd_Write_Data(j>>8); Lcd_Write_Data(j); } digitalWrite(LCD_CS, HIGH); } void setup() { Serial.begin(9600); pinMode(2, OUTPUT); //Data 8bit pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(A0,OUTPUT); pinMode(A1,OUTPUT); pinMode(A2,OUTPUT); pinMode(A3,OUTPUT); pinMode(A4,OUTPUT); digitalWrite(A0, HIGH); digitalWrite(A1, HIGH); digitalWrite(A2, HIGH); digitalWrite(A3, HIGH); digitalWrite(A4, HIGH); Lcd_Init(); } void loop() { unsigned long start = micros(); LCD_Clear(0xFFFF); LCD_Clear(0x0000); LCD_Clear(0xf800); LCD_Clear(0x07E0); LCD_Clear(0x001F); for(int i = 0; i < 300; i++) Rect(random(300), random(300), random(300), random(300), random(65535)); Serial.println(micros() - start); }