반응형

2.2인치 ILI9341 TFT LCD를 아두이노와 함께 사용해 보자.


알리에서 약 5천원에 구매한 ILI9341.


Logic Signal Voltage Level은 3.3V이지만 J1을 납땜해 연결하면 5V의 Signal도 입력 받을 수 있다(납땝이 좀 지저분하게 됐다). 하지만 이 방법 보다는 Logic Level Converter를 사용하는게 좋다.


원래 J1은 이렇게 떨어져 있다.


사실 ILI9341은 아두이노가 아니라 라즈베리파이와 함께 사용해보려 했지만 인터넷에 있는 대부분의 자료들이 더 이상 적용되지 않았다. 백라이트조차 켜지지 않았다. 라즈베리파이 운영체제의 업데이트, 소프트웨어의 업데이트 등으로 변경된 내용이 많아 좀 더 정리가 필요했다.



아두이노와 연결 하자.


ILI9341 - Arduino

DC - 9

CS - 10

RESET - 8

MOSI - 11

MISO - 12

SCK - 13

LED - 3.3V

VCC - 5V

GND - GND


아두이노IDE에서 File - Examples - Adafruit ILI9341 - graphictest을 선택하면 아래 소스가 로드된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/***************************************************
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651
  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
 
 
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
 
// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10
 
// Adafruit shield가 아닌 경우 아래와 같이 핀 추가.
#define TFT_RST 8
#define TFT_MOSI 11
#define TFT_MISO 12
#define TFT_CLK 13
 
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
 
void setup() {
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 
 
  tft.begin();
 
  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  
  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);
 
  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);
 
  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9341_CYAN));
  delay(500);
 
  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
  delay(500);
 
  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9341_GREEN));
  delay(500);
 
  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
  delay(500);
 
  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));
 
  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9341_WHITE));
  delay(500);
 
  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);
 
  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);
 
  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);
 
  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);
 
  Serial.println(F("Done!"));
 
}
 
 
void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}
 
unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;
}
 
unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(00);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}
 
unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();
 
  tft.fillScreen(ILI9341_BLACK);
  yield();
  
  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;
 
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
 
  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
 
  yield();
  return micros() - start;
}
 
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
 
  return micros() - start;
}
 
unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;
 
  tft.fillScreen(ILI9341_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }
 
  return micros() - start;
}
 
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
    yield();
  }
 
  return t;
}
 
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
 
  return micros() - start;
}
 
unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;
 
  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
 
  return micros() - start;
}
 
unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(i, i, i));
  }
 
  return micros() - start;
}
 
unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i*10, i*10));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i*10, i*100));
    yield();
  }
 
  return t;
}
 
unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 00));
  }
 
  return micros() - start;
}
 
unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;
 
  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
    yield();
  }
 
  return micros() - start;
}


로드된 소스는 Adafruit shield 사용을 전제로 작성된 소스이므로 위와 같이 24~33번 라인을 수정한다.


컴파일하고 업로드하면 그래픽이 표시된다.









실행해 보면 생각만큼 빠르지는 않다. 아두이노 전용은 아니지만 STM32, ESP8266, ESP32를 위한 더 빠른 라이브러리가 있다. 아두이노에도 적용 가능하지 않을까싶다. 아래 링크를 참고하자.

TFT_eSPI


반응형
Posted by J-sean
:
반응형

거실에 큰 TV가 한 대 있지만 식탁과는 마주보지 않고 거의 90도의 각도를 이루고 있기 때문에 식사 중에는 거의 볼 수 가 없다. 밥을 오래 먹는건 아니지만 혼자 밥만 먹기 심심할 때나 가족들과 먹더라도 TV가 보고 싶을때 볼 수 있었으면 좋겠다.


그래서 구매 했다. 샤오미 미 TV 스틱과 10.1인치 모니터.


샤오미 미 TV 스틱.


안드로이드 TV다. 실제 TV 방송을 볼 수는 없다.


미 TV 스틱 외 리모콘, 어댑터, 케이블이 들어 있다.


필요 없는 설명서. 버린다.



따로 구매한 10.1인치 HD TFT LCD 모니터. 박스가 좀 구겨져서 도착 했다.


전원은 12V를 사용하고 2개의 스피커가 달려 있다. 이것 저것 많이 지원한다고 한다.


박스 안에 같이 들어 있는 구성품. 중국 먼지가 많이 따라 왔다. 닦아 주자.


HDMI 외 D-sub, USB등 여러가지 포트가 있다.



그런데 화살표 부분을 잡아 당기면 벗겨져야 할 보호 필름이 벗겨 지지 않는다. 살펴보니 필름이 모니터 케이스에 꽉 물려 있다. 짜증...


분해하기 싫었지만 어쩔 수 없었다. 내부는 평범하다. 흔히 볼 수 있는 AD 보드와 스피커가 보인다.


어쨌든 보호 필름을 제거 했다.


12V 어댑터는 US 타입이므로 KR 타입 플러그를 사용 한다.



모니터 전원을 켜 봤다. 별 이상은 없어 보인다.


샤오미 미 TV 스틱을 연결하고 간단한 세팅 진행 후 유튜브를 실행 한다.


화면 전체적으로 푸른 빛이 돌긴 하지만.. 뭐.. 잘 나온다.


거실 식탁에 올려 놓고 밥먹을 때 봐야겠다.


반응형
Posted by J-sean
:
반응형

라즈베리 파이를 이용한 여러가지 프로젝트를 진행하기 전에 쓸만한 디스플레이를 고르기 위해 AliExpress에서 7인치 디스플레이를 주문 했다. 다른 제품보다 충격에 민감할 수 밖에 없는 제품이기에 배송이 걱정 되었지만 사이즈가 작으니 포장만 잘 하면 문제 없이 도착할거라 생각했다.


우체국택배를 통해 배송 되었다.


박스를 열어 보니 다행히 나름 깔끔하게 잘 포장되어 있었다.


7 inch HD Display Screen. 해상도는 1024X600이다.


LCD Driver. 여기에 다른 부품들을 연결 한다.



디스플레이의 소스, 화면 상태등을 조정할 수 있는 보드. 상품 설명에는 Key Board라는 이름으로 소개 되어 있고 SOURCE, MENU, POWER등 5개의 버튼이 달려 있다.


디스플레이 리모컨, 5V USB 전원 케이블, Key Board 케이블


Key Board 케이블을 Key Board와 LCD Driver에 연결 한다. 굉장히 뻑뻑해서 한 번 연결되면 분리하기 어렵다.


디스플레이의 Flat Flexible Cable을 LCD Driver에 연결 한다. 더 들어갈거 같은데.. 라는 생각이 들 정도만 들어 간다.



5V 전원과 컴퓨터등의 소스를 연결한다. HDMI, D-Sub, Composite Video 케이블 연결이 가능 하다.


상품 소개에 나오는 각 포트 설명


케이블 연결이 잘 되었다면 특별히 설정할 건 없다. 소스로 연결한 기기를 켜면 일반 모니터와 동일하게 작동 한다. 레트로파이를 설치한 라즈베리 파이에 연결하고 Bubble Bobble을 실행했다.


Metal Slug 실행 화면. 7인치 디스플레이기 때문에 14인치 노트북의 절반 크기도 안된다.



노트북에 연결한 화면. 노트북 디스플레이의 내용도 잘 표시 된다. Key Board의 녹색 불빛은 생각보다 밝다.


구매 비용은 $24로 3만원이 좀 안되는 가격에 무료 배송이다. 저렴한 가격이지만 생각보다 괜찮은 성능을 보여 주는 제품으로 여러가지 프로젝트에 응용 가능할 것으로 생각되며 이 제품보다 약간 큰 9인치나 10.1인치도 구매해 보고 싶은 생각이 들 정도로 만족스러웠다.


반응형
Posted by J-sean
: