아두이노2017. 4. 20. 01:05

예전 글(http://deneb21.tistory.com/508) 에서 노키아 5110 LCD를 아두이노로 컨트롤 하는 방법에 대해서 알아보았다. 이번에는 그래픽 라이브러리를 사용해서 간단한 그래픽을 나타내 보려고 한다. 라이브러리는 Adafruit 의 GFX 라이브러리와 PCD8544(5110 LCD 정식 품명) 라이브러리를 이용했으며 다운 받은 라이브러리에 포함된 예제를 핀배열과 백라이트 부분을 살짝 수정해서 그래픽을 표시해 보았다. 5110 LCD에 대한 기본적인 사항은 이 글의 첫 줄에 있는 예전 글을 참고하면 된다.


연결은 예전과 동일하다. 만약 라이브러리 파일의 예제 그대로 연결하고 싶다면 아래의 연결을 따르지 않아도 된다. 물론 아래의 소스도 수정이 되어야 할 것이다.


■ Nokia 5110 LCD 와 아두이노 우노의 연결




 Arduino UNO

 Nokia 5110 LCD

 7

 CE

 6

 RST

 5

 DC

 4

 DIN

 3

 CLK

 2

 LIGHT

 3.3V

 VCC

 GND

 GND




■ 라이브러리 다운로드


Adafruit GFX 라이브러리 : https://github.com/adafruit/Adafruit-GFX-Library


Adafruit PCD8544 Nokia 5110 LCD library : https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library


위의 두 가지 라이브러리를 다운로드 받아서 압축을 풀고 아두이노 설치폴더 하위의 Libraries 폴더에 복사해 넣으면 된다. 참고로 GFX 라이브러리는 예전 OLED LCD 사용에 대한 글에서도 사용한 라이브러리이다.


Adafruit-GFX-Library-master.zip

Adafruit-PCD8544-Nokia-5110-LCD-library-master.zip




■ 소스

아래 소스는 라이브러리 설치 시 Example 로 제공되는 소스(pcdtest.ino)이며 핀 연결 부분을 나의 연결에 맞게 수정했으며 백라이트 제어 부분을 추가한 소스이다.


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
/*********************************************************************
This is an example sketch for our Monochrome Nokia 5110 LCD Displays
  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/338
These displays use SPI to communicate, 4 or 5 pins are required to
interface
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.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/
 
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
 
#define PIN_BL    2   //백라이트 제어를 위한 핀연결
 
// Software SPI (slower updates, more flexible pin options):
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
//Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); //원래 핀연결
Adafruit_PCD8544 display = Adafruit_PCD8544(34576);   //나의 연결에 맞게 수정한 핀연결
 
// Hardware SPI (faster, but must use certain hardware pins):
// SCK is LCD serial clock (SCLK) - this is pin 13 on Arduino Uno
// MOSI is LCD DIN - this is pin 11 on an Arduino Uno
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
// Adafruit_PCD8544 display = Adafruit_PCD8544(5, 4, 3);
// Note with hardware SPI MISO and SS pins aren't used but will still be read
// and written to during SPI transfer.  Be careful sharing these pins!
 
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
 
 
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16
 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };
 
void setup()   {
  //백라이트를 ON 함
  pinMode(PIN_BL,OUTPUT); 
  digitalWrite(PIN_BL,LOW); //HIGH = Turn Backlight OFF, LOW = Turn Backlight ON
 
  Serial.begin(9600);
 
  display.begin();
  // init done
 
  // you can change the contrast around to adapt the display
  // for the best viewing!
  display.setContrast(50);
 
  display.display(); // show splashscreen
  delay(2000);
  display.clearDisplay();   // clears the screen and buffer
 
  // draw a single pixel
  display.drawPixel(1010, BLACK);
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // draw many lines
  testdrawline();
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // draw rectangles
  testdrawrect();
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // draw multiple rectangles
  testfillrect();
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // draw mulitple circles
  testdrawcircle();
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // draw a circle, 10 pixel radius
  display.fillCircle(display.width()/2, display.height()/210, BLACK);
  display.display();
  delay(2000);
  display.clearDisplay();
 
  testdrawroundrect();
  delay(2000);
  display.clearDisplay();
 
  testfillroundrect();
  delay(2000);
  display.clearDisplay();
 
  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
   
  testfilltriangle();
  delay(2000);
  display.clearDisplay();
 
  // draw the first ~12 characters in the font
  testdrawchar();
  display.display();
  delay(2000);
  display.clearDisplay();
 
  // text display texts
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0,0);
  display.println("Hello, world!");
  display.setTextColor(WHITE, BLACK); // 'inverted' text
  display.println(3.141592);
  display.setTextSize(2);
  display.setTextColor(BLACK);
  display.print("0x"); display.println(0xDEADBEEF, HEX);
  display.display();
  delay(2000);
 
  // rotation example
  display.clearDisplay();
  display.setRotation(1);  // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further.
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0,0);
  display.println("Rotation");
  display.setTextSize(2);
  display.println("Example!");
  display.display();
  delay(2000);
 
  // revert back to no rotation
  display.setRotation(0);
 
  // miniature bitmap display
  display.clearDisplay();
  display.drawBitmap(3016,  logo16_glcd_bmp, 16161);
  display.display();
 
  // invert the display
  display.invertDisplay(true);
  delay(1000); 
  display.invertDisplay(false);
  delay(1000); 
 
  // draw a bitmap icon and 'animate' movement
  testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_WIDTH, LOGO16_GLCD_HEIGHT);
}
 
 
void loop() {
  
}
 
 
void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  uint8_t icons[NUMFLAKES][3];
  randomSeed(666);     // whatever seed
 
  // initialize
  for (uint8_t f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS] = random(display.width());
    icons[f][YPOS] = 0;
    icons[f][DELTAY] = random(5+ 1;
    
    Serial.print("x: ");
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(" y: ");
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(" dy: ");
    Serial.println(icons[f][DELTAY], DEC);
  }
 
  while (1) {
    // draw each icon
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK);
    }
    display.display();
    delay(200);
    
    // then erase it + move it
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS],  logo16_glcd_bmp, w, h, WHITE);
      // move it
      icons[f][YPOS] += icons[f][DELTAY];
      // if its gone, reinit
      if (icons[f][YPOS] > display.height()) {
  icons[f][XPOS] = random(display.width());
  icons[f][YPOS] = 0;
  icons[f][DELTAY] = random(5+ 1;
      }
    }
   }
}
 
 
void testdrawchar(void) {
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0,0);
 
  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n'continue;
    display.write(i);
    //if ((i > 0) && (i % 14 == 0))
      //display.println();
  }    
  display.display();
}
 
void testdrawcircle(void) {
  for (int16_t i=0; i<display.height(); i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, BLACK);
    display.display();
  }
}
 
void testfillrect(void) {
  uint8_t color = 1;
  for (int16_t i=0; i<display.height()/2; i+=3) {
    // alternate colors
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
    display.display();
    color++;
  }
}
 
void testdrawtriangle(void) {
  for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, BLACK);
    display.display();
  }
}
 
void testfilltriangle(void) {
  uint8_t color = BLACK;
  for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
    display.fillTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, color);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}
 
void testdrawroundrect(void) {
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, BLACK);
    display.display();
  }
}
 
void testfillroundrect(void) {
  uint8_t color = BLACK;
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}
   
void testdrawrect(void) {
  for (int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, BLACK);
    display.display();
  }
}
 
void testdrawline() {  
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(00, i, display.height()-1, BLACK);
    display.display();
  }
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(00, display.width()-1, i, BLACK);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, BLACK);
    display.display();
  }
  for (int8_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, BLACK);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, BLACK);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-10, i, BLACK);
    display.display();
  }
  delay(250);
 
  display.clearDisplay();
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-100, i, BLACK);
    display.display();
  }
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-10, i, display.height()-1, BLACK); 
    display.display();
  }
  delay(250);
}
cs


소스는 setup() 에서 여러가지 도형 및 문자를 출력하는 function을 순차적으로 실행하고 있다. 각 function 들을 자세히 보면 어떻게 도형과 문자 그리고 애니메이션을 만드는지 알 수 있을 것이다. 복잡한 부분은 라이브러리와 되어 있어서 자세히 살펴보면 별로 어려운 부분은 없다. 대부분의 기능들이 예를 들어 display.clearDisplay(); 같이 간단하게 제어가 가능하게 되어있다.





■ 추가사항 (2017.04.20) : 위의 소스에서 텍스트 표시하는 부분만 잘라서 정리해 보았다. 아무래도 이 디스플레이를 가지고 그래픽 보다는 텍스트 표시 용도로 사용할 경우가 많을 것으로 보여서 정리해 보았다. 


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
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#define PIN_BL 2   //백라이트 제어를 위한 핀연결
 
//SCLK, DIN, DC, CE, RST 핀연결
Adafruit_PCD8544 display = Adafruit_PCD8544(34576);
 
void setup()
{
  //백라이트를 ON 함, HIGH = Turn Backlight OFF, LOW = Turn Backlight ON
  pinMode(PIN_BL,OUTPUT); 
  digitalWrite(PIN_BL,LOW); 
 
  //디스플레이 초기화
  display.begin();
 
  //디스플레이 Contrast 조절 (값이 올라가면 진해짐)
  display.setContrast(60);
 
  //텍스트 디스플레이
  display.clearDisplay();             //디스플레이 지우기
  display.setTextSize(1);             //텍스트 사이즈 조절
  display.setTextColor(BLACK);        //텍스트 색
  display.setCursor(0,0);             //커서 좌표
  display.println("Hello, world!");   //표시 텍스트
  display.setTextColor(WHITE, BLACK); // 'inverted' text (배경 까맣게 글자 하얗게)
  display.println(3.141592);          //숫자 표시
  display.setTextSize(2);             //텍스트 사이즈 조절
  display.setTextColor(BLACK);        //텍스트 색
  display.print("0x");                //표시 텍스트
  display.println(0xDEADBEEF, HEX);   //HEX 쓰기
  display.display();                  //위의 설정내용 표시
}
 
void loop()
{
 
}
cs

주석을 나름대로 상세하게 달아 보았다.


실행결과

반응형
Posted by 대네브 (deneb)

댓글을 달아 주세요

  1. iceky

    여러가지 배워갑니다.
    혹시 hd4478a00 lcd 관련해서 정보 다루는 법을 알 수 있을까요? 찾아봐도 딱 해당하는 거랑 맞는게 없네요.
    제가 가지고 있는 핀이 세로배열에 갯수도 많은데 보통 검색해서 나오는건 가로배열의 핀갯수도 적은것만이네요.

    2017.05.21 21:14 [ ADDR : EDIT/ DEL : REPLY ]
    • 글쎄요. 저도 처음 들어보는 LCD네요.
      구글링 해봐도 별로 정보가 없네요.
      이럴 경우는 직접 데이터시트를 보고
      시도해 보는 수 밖에 없을 듯 합니다.

      잠깐 구글링해보니 https://forum.arduino.cc/index.php?topic=102990.msg772844#msg772844 이런 정보도 있긴 하네요...

      참고하시길

      2017.05.21 22:17 신고 [ ADDR : EDIT/ DEL ]
  2. saki

    1602 lcd를 사용하고 있습니다. 여기에 아두이노 우노랑 여러 센서들이랑 연동해서 하고있는데요.
    각 센서별로 조건부로 lcd에 글자를 출력은 할 수 있는데요. 이 글자들을 움직이게 하고싶은데 어떻게 해야 하는지 모르겠습니다. 한쪽방향에서 다른방향으로 밀리는 식으로요.
    그리고 센서별로 전부 글자들이 출력되야 하는 상황이 생길때 하나의 센서 글자가 출력되어 밀려서 사라지고 다음 센서에 해당하는게 출력되고 이런식으로 짜보고 싶은데요.
    어떤식으로 코드작성을 해야하는지 감을 못잡아 질문드립니다. 답변 부탁드리겠습니다.

    2017.05.30 00:41 [ ADDR : EDIT/ DEL : REPLY ]