아두이노 강좌 #26 8x8 LED 매트릭스 문자열 스크롤 하기
Lucy Archive
Lucy 2023
2020. 8. 22. 03:20

아두이노 우노 LED 매트릭스 스크롤아두이노 우노 LED 매트릭스 스크롤

Arduino Uno 8x8 LED Dot Matrix Stroll String

이번 포스트에서는

8x8 LED 매트릭스를 사용하여 문자열을 스크롤 하는 예제

를 소개합니다. 지난 포스트에서 문자 하나를 스크롤 하는 예제를 참고하시면 이번 예제 코드 이해하는데 도움이 될 것 같습니다. 관련 포스트는 하단을 참고해주세요.


Hardware

준비물

본 예제의 구성품은 아래와 같습니다.

  • Arduino Uno x 1EA
  • 8x8 LED Dot Matrix x 1EA
  • Resistor x 8EA
  • Bread Board and Jumperwires

회로도 및 연결

Arduino Uno 8x8 LED MatrixArduino Uno 8x8 LED Matrix 연결 회로도 및 연결 예시

회로 연결은 지난 포스트와 동일합니다. 하드웨어 연결 주의 사항은 지난 포스트를 참고해주세요.

예제1 : 문자열 출력

코드

하단의 font[] 배열은 아래의 Github의 font8x8_basic.h 파일을 참조하였습니다. 예제2에서 시리얼로 입력 받은 문자열을 출력하기 위해 ASCII 코드가 모두 포함된 배열을 미리 사용하였습니다.

참조 링크 : https://github.com/dhepper/font8x8/blob/master/font8x8_basic.h

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
#define BUFFERSIZE 40
#define SCROLLTIME 140
#define INITIALSTRING "8x8 LED Matrix Scroll String"
 
// Coloumn Pin 할당
#define C1 9
#define C2 12
#define C3 7
#define C4 13
#define C5 A2
#define C6 6
#define C7 3
#define C8 A5
// Row Pin 할당
#define R1 2
#define R2 11
#define R3 10
#define R4 A4
#define R5 8
#define R6 A3
#define R7 4
#define R8 5
 
// Bit 추출 메크로 : data 에서 loc 번째 비트 부터 area 영역 만큼 추출
// ex) extract_bits( 0b00000010, 1, 2) 결과 1 -> 0b00000010 데이터의 2번째 비트 1크기 만큼 추출  
#define extract_bits(data, area, loc)   (((data) >> (loc)) & (area))
 
int colPin[8= {C1, C2, C3, C4, C5, C6, C7, C8};
int rowPin[8= {R1, R2, R3, R4, R5, R6, R7, R8};
 
const byte font[128][8= {
    { 0x000x000x000x000x000x000x000x00},   // U+0000 (nul)
    { 0x000x000x000x000x000x000x000x00},   // U+0001
    { 0x000x000x000x000x000x000x000x00},   // U+0002
    { 0x000x000x000x000x000x000x000x00},   // U+0003
    { 0x000x000x000x000x000x000x000x00},   // U+0004
    { 0x000x000x000x000x000x000x000x00},   // U+0005
    { 0x000x000x000x000x000x000x000x00},   // U+0006
    { 0x000x000x000x000x000x000x000x00},   // U+0007
    { 0x000x000x000x000x000x000x000x00},   // U+0008
    { 0x000x000x000x000x000x000x000x00},   // U+0009
    { 0x000x000x000x000x000x000x000x00},   // U+000A
    { 0x000x000x000x000x000x000x000x00},   // U+000B
    { 0x000x000x000x000x000x000x000x00},   // U+000C
    { 0x000x000x000x000x000x000x000x00},   // U+000D
    { 0x000x000x000x000x000x000x000x00},   // U+000E
    { 0x000x000x000x000x000x000x000x00},   // U+000F
    { 0x000x000x000x000x000x000x000x00},   // U+0010
    { 0x000x000x000x000x000x000x000x00},   // U+0011
    { 0x000x000x000x000x000x000x000x00},   // U+0012
    { 0x000x000x000x000x000x000x000x00},   // U+0013
    { 0x000x000x000x000x000x000x000x00},   // U+0014
    { 0x000x000x000x000x000x000x000x00},   // U+0015
    { 0x000x000x000x000x000x000x000x00},   // U+0016
    { 0x000x000x000x000x000x000x000x00},   // U+0017
    { 0x000x000x000x000x000x000x000x00},   // U+0018
    { 0x000x000x000x000x000x000x000x00},   // U+0019
    { 0x000x000x000x000x000x000x000x00},   // U+001A
    { 0x000x000x000x000x000x000x000x00},   // U+001B
    { 0x000x000x000x000x000x000x000x00},   // U+001C
    { 0x000x000x000x000x000x000x000x00},   // U+001D
    { 0x000x000x000x000x000x000x000x00},   // U+001E
    { 0x000x000x000x000x000x000x000x00},   // U+001F
    { 0x000x000x000x000x000x000x000x00},   // U+0020 (space)
    { 0x180x3C0x3C0x180x180x000x180x00},   // U+0021 (!)
    { 0x360x360x000x000x000x000x000x00},   // U+0022 (")
    { 0x360x360x7F0x360x7F0x360x360x00},   // U+0023 (#)
    { 0x0C0x3E0x030x1E0x300x1F0x0C0x00},   // U+0024 ($)
    { 0x000x630x330x180x0C0x660x630x00},   // U+0025 (%)
    { 0x1C0x360x1C0x6E0x3B0x330x6E0x00},   // U+0026 (&)
    { 0x060x060x030x000x000x000x000x00},   // U+0027 (')
    { 0x180x0C0x060x060x060x0C0x180x00},   // U+0028 (()
    { 0x060x0C0x180x180x180x0C0x060x00},   // U+0029 ())
    { 0x000x660x3C0xFF0x3C0x660x000x00},   // U+002A (*)
    { 0x000x0C0x0C0x3F0x0C0x0C0x000x00},   // U+002B (+)
    { 0x000x000x000x000x000x0C0x0C0x06},   // U+002C (,)
    { 0x000x000x000x3F0x000x000x000x00},   // U+002D (-)
    { 0x000x000x000x000x000x0C0x0C0x00},   // U+002E (.)
    { 0x600x300x180x0C0x060x030x010x00},   // U+002F (/)
    { 0x3E0x630x730x7B0x6F0x670x3E0x00},   // U+0030 (0)
    { 0x0C0x0E0x0C0x0C0x0C0x0C0x3F0x00},   // U+0031 (1)
    { 0x1E0x330x300x1C0x060x330x3F0x00},   // U+0032 (2)
    { 0x1E0x330x300x1C0x300x330x1E0x00},   // U+0033 (3)
    { 0x380x3C0x360x330x7F0x300x780x00},   // U+0034 (4)
    { 0x3F0x030x1F0x300x300x330x1E0x00},   // U+0035 (5)
    { 0x1C0x060x030x1F0x330x330x1E0x00},   // U+0036 (6)
    { 0x3F0x330x300x180x0C0x0C0x0C0x00},   // U+0037 (7)
    { 0x1E0x330x330x1E0x330x330x1E0x00},   // U+0038 (8)
    { 0x1E0x330x330x3E0x300x180x0E0x00},   // U+0039 (9)
    { 0x000x0C0x0C0x000x000x0C0x0C0x00},   // U+003A (:)
    { 0x000x0C0x0C0x000x000x0C0x0C0x06},   // U+003B (//)
    { 0x180x0C0x060x030x060x0C0x180x00},   // U+003C (<)
    { 0x000x000x3F0x000x000x3F0x000x00},   // U+003D (=)
    { 0x060x0C0x180x300x180x0C0x060x00},   // U+003E (>)
    { 0x1E0x330x300x180x0C0x000x0C0x00},   // U+003F (?)
    { 0x3E0x630x7B0x7B0x7B0x030x1E0x00},   // U+0040 (@)
    { 0x0C0x1E0x330x330x3F0x330x330x00},   // U+0041 (A)
    { 0x3F0x660x660x3E0x660x660x3F0x00},   // U+0042 (B)
    { 0x3C0x660x030x030x030x660x3C0x00},   // U+0043 (C)
    { 0x1F0x360x660x660x660x360x1F0x00},   // U+0044 (D)
    { 0x7F0x460x160x1E0x160x460x7F0x00},   // U+0045 (E)
    { 0x7F0x460x160x1E0x160x060x0F0x00},   // U+0046 (F)
    { 0x3C0x660x030x030x730x660x7C0x00},   // U+0047 (G)
    { 0x330x330x330x3F0x330x330x330x00},   // U+0048 (H)
    { 0x1E0x0C0x0C0x0C0x0C0x0C0x1E0x00},   // U+0049 (I)
    { 0x780x300x300x300x330x330x1E0x00},   // U+004A (J)
    { 0x670x660x360x1E0x360x660x670x00},   // U+004B (K)
    { 0x0F0x060x060x060x460x660x7F0x00},   // U+004C (L)
    { 0x630x770x7F0x7F0x6B0x630x630x00},   // U+004D (M)
    { 0x630x670x6F0x7B0x730x630x630x00},   // U+004E (N)
    { 0x1C0x360x630x630x630x360x1C0x00},   // U+004F (O)
    { 0x3F0x660x660x3E0x060x060x0F0x00},   // U+0050 (P)
    { 0x1E0x330x330x330x3B0x1E0x380x00},   // U+0051 (Q)
    { 0x3F0x660x660x3E0x360x660x670x00},   // U+0052 (R)
    { 0x1E0x330x070x0E0x380x330x1E0x00},   // U+0053 (S)
    { 0x3F0x2D0x0C0x0C0x0C0x0C0x1E0x00},   // U+0054 (T)
    { 0x330x330x330x330x330x330x3F0x00},   // U+0055 (U)
    { 0x330x330x330x330x330x1E0x0C0x00},   // U+0056 (V)
    { 0x630x630x630x6B0x7F0x770x630x00},   // U+0057 (W)
    { 0x630x630x360x1C0x1C0x360x630x00},   // U+0058 (X)
    { 0x330x330x330x1E0x0C0x0C0x1E0x00},   // U+0059 (Y)
    { 0x7F0x630x310x180x4C0x660x7F0x00},   // U+005A (Z)
    { 0x1E0x060x060x060x060x060x1E0x00},   // U+005B ([)
    { 0x030x060x0C0x180x300x600x400x00},   // U+005C (\)
    { 0x1E0x180x180x180x180x180x1E0x00},   // U+005D (])
    { 0x080x1C0x360x630x000x000x000x00},   // U+005E (^)
    { 0x000x000x000x000x000x000x000xFF},   // U+005F (_)
    { 0x0C0x0C0x180x000x000x000x000x00},   // U+0060 (`)
    { 0x000x000x1E0x300x3E0x330x6E0x00},   // U+0061 (a)
    { 0x070x060x060x3E0x660x660x3B0x00},   // U+0062 (b)
    { 0x000x000x1E0x330x030x330x1E0x00},   // U+0063 (c)
    { 0x380x300x300x3e0x330x330x6E0x00},   // U+0064 (d)
    { 0x000x000x1E0x330x3f0x030x1E0x00},   // U+0065 (e)
    { 0x1C0x360x060x0f0x060x060x0F0x00},   // U+0066 (f)
    { 0x000x000x6E0x330x330x3E0x300x1F},   // U+0067 (g)
    { 0x070x060x360x6E0x660x660x670x00},   // U+0068 (h)
    { 0x0C0x000x0E0x0C0x0C0x0C0x1E0x00},   // U+0069 (i)
    { 0x300x000x300x300x300x330x330x1E},   // U+006A (j)
    { 0x070x060x660x360x1E0x360x670x00},   // U+006B (k)
    { 0x0E0x0C0x0C0x0C0x0C0x0C0x1E0x00},   // U+006C (l)
    { 0x000x000x330x7F0x7F0x6B0x630x00},   // U+006D (m)
    { 0x000x000x1F0x330x330x330x330x00},   // U+006E (n)
    { 0x000x000x1E0x330x330x330x1E0x00},   // U+006F (o)
    { 0x000x000x3B0x660x660x3E0x060x0F},   // U+0070 (p)
    { 0x000x000x6E0x330x330x3E0x300x78},   // U+0071 (q)
    { 0x000x000x3B0x6E0x660x060x0F0x00},   // U+0072 (r)
    { 0x000x000x3E0x030x1E0x300x1F0x00},   // U+0073 (s)
    { 0x080x0C0x3E0x0C0x0C0x2C0x180x00},   // U+0074 (t)
    { 0x000x000x330x330x330x330x6E0x00},   // U+0075 (u)
    { 0x000x000x330x330x330x1E0x0C0x00},   // U+0076 (v)
    { 0x000x000x630x6B0x7F0x7F0x360x00},   // U+0077 (w)
    { 0x000x000x630x360x1C0x360x630x00},   // U+0078 (x)
    { 0x000x000x330x330x330x3E0x300x1F},   // U+0079 (y)
    { 0x000x000x3F0x190x0C0x260x3F0x00},   // U+007A (z)
    { 0x380x0C0x0C0x070x0C0x0C0x380x00},   // U+007B ({)
    { 0x180x180x180x000x180x180x180x00},   // U+007C (|)
    { 0x070x0C0x0C0x380x0C0x0C0x070x00},   // U+007D (})
    { 0x6E0x3B0x000x000x000x000x000x00},   // U+007E (~)
    { 0x000x000x000x000x000x000x000x00}    // U+007F
};
 
byte displayData[8]; // 최종 8x8 출력 할 데이터
byte stringBuffer[BUFFERSIZE][8]; // 스크롤 할 데이터를 저장할 버퍼
 
int iTextLenth;
int scrollTime = SCROLLTIME; // scrollTime 만큼 한 글자씩 시프트
 
void setup(){
 
    String initialString = INITIALSTRING;
    iTextLenth = initialString.length();
    
    for(int i = 0 ; i < 8 ; i++)
    {
        pinMode(colPin[i], OUTPUT);
        digitalWrite(colPin[i], LOW); // Column 핀은 LOW 로 초기화
        pinMode(rowPin[i], OUTPUT);
        digitalWrite(rowPin[i], HIGH); // Row 핀은 HIGH 로 초기화
    }
    
    for(int i = 1 ; i < iTextLenth+1 ; i++){
        for(int j = 0 ; j < 8 ; j++){
            stringBuffer[i][j] = font[initialString.charAt(i-1)][j];
        }
    }
}
 
void loop() {
    unsigned long now = millis();
    static unsigned long pastTime;
 
    /*
        scrollTime 시간 마다 실행되는 if문
        scrollTime 마다 최종 출력 데이터 displayData 를 한칸씩 시프트합니다.
    */
    if(now - pastTime >= scrollTime){
        pastTime = now;
        static int count;
        static int index;
 
        for(int i = 0 ; i < 8 ; i++){
            displayData[i] = (stringBuffer[index][i] >> count) | (stringBuffer[index+1][i] << 8 - count);
        }
        count++;
        if(count == 8) {
            count = 0;
            index++;
            if(index == iTextLenth + 1) index = 0;
        }
    }
 
    for(int i = 0 ; i < 8 ; i++)
    {
        for(int j = 0 ; j < 8 ; j++)
        {
            digitalWrite(colPin[j], extract_bits(displayData[i],0x01,j)); // Coloumn 핀에 데이터 쓰기
        }
        digitalWrite(rowPin[i], LOW); // i 행 활성화
        delayMicroseconds(100);
        digitalWrite(rowPin[i], HIGH); // i 행 비활성화
    }
}
cs

코드 설명

지난 포스트의 코드에서 추가된 내용은 아래와 같습니다.

  • 1~3 Line
    • BUFFERSIZE : 최대 출력 가능 문자열의 크기
    • SCROLLTIME : 문자열 한칸씩 쉬프트 되는 스피드 조정 - 낮을 수록 빠른 속도
    • INITIALSTRING : 부팅 시 초기 출력 메세지
  • 31 Line font[] 배열 : ascii 인덱스에 따라 8x8 문자 도트데이터
  • 183 Line : stringBuffer[i][j] = font[initialString.charAt(i-1)][j];
    • initialString.charAt(i) : String 변수 initialString 의 i 번째 문자를 말하며, font[] 배열의 인덱스 값을 지정합니다.
    • stringBufferinitialString 문자열의 8x8 도트 데이터를 저장합니다.

실행 결과

위 프로그램을 실행하면 INITIALSTRING 에 선언된 문자열을 출력 합니다.

예제2 : 시리얼에서 문자열 입력 받아 출력

코드

예제1의 코드에서 시리얼 통신으로 문자열을 입력 받아 8x8 Matrix 에 출력하는 예제 입니다. 시리얼 통신으로 문자열을 입력 받는 방법은 지난 포스트의 문장 단위로 시리얼 입력 받는 방법 포스트의 방법을 응용하였습니다. 아래 코드를 보시고, 코드 설명이 필요하신 분은 하단의 링크 포스트를 참조해주세요.

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
#define BUADRATE 115200
#define BUFFERSIZE 40
#define SCROLLTIME 140
 
// Coloumn Pin 할당
#define C1 9
#define C2 12
#define C3 7
#define C4 13
#define C5 A2
#define C6 6
#define C7 3
#define C8 A5
// Row Pin 할당
#define R1 2
#define R2 11
#define R3 10
#define R4 A4
#define R5 8
#define R6 A3
#define R7 4
#define R8 5
 
// Bit 추출 메크로 : data 에서 loc 번째 비트 부터 area 영역 만큼 추출
// ex) extract_bits( 0b00000010, 1, 2) 결과 1 -> 0b00000010 데이터의 2번째 비트 1크기 만큼 추출  
#define extract_bits(data, area, loc)   (((data) >> (loc)) & (area))
 
int colPin[8= {C1, C2, C3, C4, C5, C6, C7, C8};
int rowPin[8= {R1, R2, R3, R4, R5, R6, R7, R8};
 
const byte font[128][8= {
    { 0x000x000x000x000x000x000x000x00},   // U+0000 (nul)
    { 0x000x000x000x000x000x000x000x00},   // U+0001
    { 0x000x000x000x000x000x000x000x00},   // U+0002
    { 0x000x000x000x000x000x000x000x00},   // U+0003
    { 0x000x000x000x000x000x000x000x00},   // U+0004
    { 0x000x000x000x000x000x000x000x00},   // U+0005
    { 0x000x000x000x000x000x000x000x00},   // U+0006
    { 0x000x000x000x000x000x000x000x00},   // U+0007
    { 0x000x000x000x000x000x000x000x00},   // U+0008
    { 0x000x000x000x000x000x000x000x00},   // U+0009
    { 0x000x000x000x000x000x000x000x00},   // U+000A
    { 0x000x000x000x000x000x000x000x00},   // U+000B
    { 0x000x000x000x000x000x000x000x00},   // U+000C
    { 0x000x000x000x000x000x000x000x00},   // U+000D
    { 0x000x000x000x000x000x000x000x00},   // U+000E
    { 0x000x000x000x000x000x000x000x00},   // U+000F
    { 0x000x000x000x000x000x000x000x00},   // U+0010
    { 0x000x000x000x000x000x000x000x00},   // U+0011
    { 0x000x000x000x000x000x000x000x00},   // U+0012
    { 0x000x000x000x000x000x000x000x00},   // U+0013
    { 0x000x000x000x000x000x000x000x00},   // U+0014
    { 0x000x000x000x000x000x000x000x00},   // U+0015
    { 0x000x000x000x000x000x000x000x00},   // U+0016
    { 0x000x000x000x000x000x000x000x00},   // U+0017
    { 0x000x000x000x000x000x000x000x00},   // U+0018
    { 0x000x000x000x000x000x000x000x00},   // U+0019
    { 0x000x000x000x000x000x000x000x00},   // U+001A
    { 0x000x000x000x000x000x000x000x00},   // U+001B
    { 0x000x000x000x000x000x000x000x00},   // U+001C
    { 0x000x000x000x000x000x000x000x00},   // U+001D
    { 0x000x000x000x000x000x000x000x00},   // U+001E
    { 0x000x000x000x000x000x000x000x00},   // U+001F
    { 0x000x000x000x000x000x000x000x00},   // U+0020 (space)
    { 0x180x3C0x3C0x180x180x000x180x00},   // U+0021 (!)
    { 0x360x360x000x000x000x000x000x00},   // U+0022 (")
    { 0x360x360x7F0x360x7F0x360x360x00},   // U+0023 (#)
    { 0x0C0x3E0x030x1E0x300x1F0x0C0x00},   // U+0024 ($)
    { 0x000x630x330x180x0C0x660x630x00},   // U+0025 (%)
    { 0x1C0x360x1C0x6E0x3B0x330x6E0x00},   // U+0026 (&)
    { 0x060x060x030x000x000x000x000x00},   // U+0027 (')
    { 0x180x0C0x060x060x060x0C0x180x00},   // U+0028 (()
    { 0x060x0C0x180x180x180x0C0x060x00},   // U+0029 ())
    { 0x000x660x3C0xFF0x3C0x660x000x00},   // U+002A (*)
    { 0x000x0C0x0C0x3F0x0C0x0C0x000x00},   // U+002B (+)
    { 0x000x000x000x000x000x0C0x0C0x06},   // U+002C (,)
    { 0x000x000x000x3F0x000x000x000x00},   // U+002D (-)
    { 0x000x000x000x000x000x0C0x0C0x00},   // U+002E (.)
    { 0x600x300x180x0C0x060x030x010x00},   // U+002F (/)
    { 0x3E0x630x730x7B0x6F0x670x3E0x00},   // U+0030 (0)
    { 0x0C0x0E0x0C0x0C0x0C0x0C0x3F0x00},   // U+0031 (1)
    { 0x1E0x330x300x1C0x060x330x3F0x00},   // U+0032 (2)
    { 0x1E0x330x300x1C0x300x330x1E0x00},   // U+0033 (3)
    { 0x380x3C0x360x330x7F0x300x780x00},   // U+0034 (4)
    { 0x3F0x030x1F0x300x300x330x1E0x00},   // U+0035 (5)
    { 0x1C0x060x030x1F0x330x330x1E0x00},   // U+0036 (6)
    { 0x3F0x330x300x180x0C0x0C0x0C0x00},   // U+0037 (7)
    { 0x1E0x330x330x1E0x330x330x1E0x00},   // U+0038 (8)
    { 0x1E0x330x330x3E0x300x180x0E0x00},   // U+0039 (9)
    { 0x000x0C0x0C0x000x000x0C0x0C0x00},   // U+003A (:)
    { 0x000x0C0x0C0x000x000x0C0x0C0x06},   // U+003B (//)
    { 0x180x0C0x060x030x060x0C0x180x00},   // U+003C (<)
    { 0x000x000x3F0x000x000x3F0x000x00},   // U+003D (=)
    { 0x060x0C0x180x300x180x0C0x060x00},   // U+003E (>)
    { 0x1E0x330x300x180x0C0x000x0C0x00},   // U+003F (?)
    { 0x3E0x630x7B0x7B0x7B0x030x1E0x00},   // U+0040 (@)
    { 0x0C0x1E0x330x330x3F0x330x330x00},   // U+0041 (A)
    { 0x3F0x660x660x3E0x660x660x3F0x00},   // U+0042 (B)
    { 0x3C0x660x030x030x030x660x3C0x00},   // U+0043 (C)
    { 0x1F0x360x660x660x660x360x1F0x00},   // U+0044 (D)
    { 0x7F0x460x160x1E0x160x460x7F0x00},   // U+0045 (E)
    { 0x7F0x460x160x1E0x160x060x0F0x00},   // U+0046 (F)
    { 0x3C0x660x030x030x730x660x7C0x00},   // U+0047 (G)
    { 0x330x330x330x3F0x330x330x330x00},   // U+0048 (H)
    { 0x1E0x0C0x0C0x0C0x0C0x0C0x1E0x00},   // U+0049 (I)
    { 0x780x300x300x300x330x330x1E0x00},   // U+004A (J)
    { 0x670x660x360x1E0x360x660x670x00},   // U+004B (K)
    { 0x0F0x060x060x060x460x660x7F0x00},   // U+004C (L)
    { 0x630x770x7F0x7F0x6B0x630x630x00},   // U+004D (M)
    { 0x630x670x6F0x7B0x730x630x630x00},   // U+004E (N)
    { 0x1C0x360x630x630x630x360x1C0x00},   // U+004F (O)
    { 0x3F0x660x660x3E0x060x060x0F0x00},   // U+0050 (P)
    { 0x1E0x330x330x330x3B0x1E0x380x00},   // U+0051 (Q)
    { 0x3F0x660x660x3E0x360x660x670x00},   // U+0052 (R)
    { 0x1E0x330x070x0E0x380x330x1E0x00},   // U+0053 (S)
    { 0x3F0x2D0x0C0x0C0x0C0x0C0x1E0x00},   // U+0054 (T)
    { 0x330x330x330x330x330x330x3F0x00},   // U+0055 (U)
    { 0x330x330x330x330x330x1E0x0C0x00},   // U+0056 (V)
    { 0x630x630x630x6B0x7F0x770x630x00},   // U+0057 (W)
    { 0x630x630x360x1C0x1C0x360x630x00},   // U+0058 (X)
    { 0x330x330x330x1E0x0C0x0C0x1E0x00},   // U+0059 (Y)
    { 0x7F0x630x310x180x4C0x660x7F0x00},   // U+005A (Z)
    { 0x1E0x060x060x060x060x060x1E0x00},   // U+005B ([)
    { 0x030x060x0C0x180x300x600x400x00},   // U+005C (\)
    { 0x1E0x180x180x180x180x180x1E0x00},   // U+005D (])
    { 0x080x1C0x360x630x000x000x000x00},   // U+005E (^)
    { 0x000x000x000x000x000x000x000xFF},   // U+005F (_)
    { 0x0C0x0C0x180x000x000x000x000x00},   // U+0060 (`)
    { 0x000x000x1E0x300x3E0x330x6E0x00},   // U+0061 (a)
    { 0x070x060x060x3E0x660x660x3B0x00},   // U+0062 (b)
    { 0x000x000x1E0x330x030x330x1E0x00},   // U+0063 (c)
    { 0x380x300x300x3e0x330x330x6E0x00},   // U+0064 (d)
    { 0x000x000x1E0x330x3f0x030x1E0x00},   // U+0065 (e)
    { 0x1C0x360x060x0f0x060x060x0F0x00},   // U+0066 (f)
    { 0x000x000x6E0x330x330x3E0x300x1F},   // U+0067 (g)
    { 0x070x060x360x6E0x660x660x670x00},   // U+0068 (h)
    { 0x0C0x000x0E0x0C0x0C0x0C0x1E0x00},   // U+0069 (i)
    { 0x300x000x300x300x300x330x330x1E},   // U+006A (j)
    { 0x070x060x660x360x1E0x360x670x00},   // U+006B (k)
    { 0x0E0x0C0x0C0x0C0x0C0x0C0x1E0x00},   // U+006C (l)
    { 0x000x000x330x7F0x7F0x6B0x630x00},   // U+006D (m)
    { 0x000x000x1F0x330x330x330x330x00},   // U+006E (n)
    { 0x000x000x1E0x330x330x330x1E0x00},   // U+006F (o)
    { 0x000x000x3B0x660x660x3E0x060x0F},   // U+0070 (p)
    { 0x000x000x6E0x330x330x3E0x300x78},   // U+0071 (q)
    { 0x000x000x3B0x6E0x660x060x0F0x00},   // U+0072 (r)
    { 0x000x000x3E0x030x1E0x300x1F0x00},   // U+0073 (s)
    { 0x080x0C0x3E0x0C0x0C0x2C0x180x00},   // U+0074 (t)
    { 0x000x000x330x330x330x330x6E0x00},   // U+0075 (u)
    { 0x000x000x330x330x330x1E0x0C0x00},   // U+0076 (v)
    { 0x000x000x630x6B0x7F0x7F0x360x00},   // U+0077 (w)
    { 0x000x000x630x360x1C0x360x630x00},   // U+0078 (x)
    { 0x000x000x330x330x330x3E0x300x1F},   // U+0079 (y)
    { 0x000x000x3F0x190x0C0x260x3F0x00},   // U+007A (z)
    { 0x380x0C0x0C0x070x0C0x0C0x380x00},   // U+007B ({)
    { 0x180x180x180x000x180x180x180x00},   // U+007C (|)
    { 0x070x0C0x0C0x380x0C0x0C0x070x00},   // U+007D (})
    { 0x6E0x3B0x000x000x000x000x000x00},   // U+007E (~)
    { 0x000x000x000x000x000x000x000x00}    // U+007F
};
 
byte displayData[8]; // 최종 8x8 출력 할 데이터
byte stringBuffer[BUFFERSIZE][8]; // 스크롤 할 데이터를 저장할 버퍼
 
int iTextLenth;
int scrollTime = SCROLLTIME; // scrollTime 만큼 한 글자씩 시프트
 
String myString; 
 
bool recFlag = false// 시리얼로 문자열 입력 받은 경우 활성화 되는 Flag
bool changeFlag = false// LED Matrix 에 출력할 데이터가 변경되어야 하는 경우 활성화 되는 Flag
 
void setup() {
 
    String initialString = "INPUT STRING";
    iTextLenth = initialString.length();
    
    for(int i = 0 ; i < 8 ; i++)
    {
        pinMode(colPin[i], OUTPUT);
        digitalWrite(colPin[i], LOW); // Column 핀은 LOW 로 초기화
        pinMode(rowPin[i], OUTPUT);
        digitalWrite(rowPin[i], HIGH); // Row 핀은 HIGH 로 초기화
    }
    
    for(int i = 1 ; i < iTextLenth+1 ; i++){
        for(int j = 0 ; j < 8 ; j++){
            stringBuffer[i][j] = font[initialString.charAt(i-1)][j];
        }
    }
    
    Serial.begin(BUADRATE);
    while(!Serial
    {
        ;
    }
    Serial.println("8x8 LED Dot Matrix Program Start..");
    delay(500);
    Serial.print("Input String >> ");
}
 
void loop() {
 
    /*
        시리얼 통신으로 문자열을 입력 받은 경우 실행되는 if문
    */
    if(recFlag == true)
    {
        recFlag = false;
        iTextLenth = myString.length();
 
        for(int i = 0 ; i < BUFFERSIZE ; i++){
            for(int j = 0; j < 8; j++){
                stringBuffer[i][j] = 0;
            }
        }
        for(int i = 1 ; i < iTextLenth+1 ; i++){
            for(int j = 0 ; j < 8 ; j++){
                stringBuffer[i][j] = font[myString.charAt(i-1)][j];
            }
        }
 
        Serial.println("String Output Completed!");
        Serial.print("Input String >> ");
        myString = "";
        changeFlag = true;
    }
 
    unsigned long now = millis();
    static unsigned long pastTime;
 
    /*
        scrollTime 시간 마다 실행되는 if문
        scrollTime 마다 최종 출력 데이터 displayData 를 한칸씩 시프트합니다.
    */
    if(now - pastTime >= scrollTime){
        pastTime = now;
        static int count;
        static int index;
        if(changeFlag == 1){
            changeFlag = 0;
            count = 0;
            index = 0;
        }
        for(int i = 0 ; i < 8 ; i++){
            displayData[i] = (stringBuffer[index][i] >> count) | (stringBuffer[index+1][i] << 8 - count);
        }
        count++;
        if(count == 8) {
            count = 0;
            index++;
            if(index == iTextLenth + 1) index = 0;
        }
    }
 
    for(int i = 0 ; i < 8 ; i++)
    {
        for(int j = 0 ; j < 8 ; j++)
        {
            digitalWrite(colPin[j], extract_bits(displayData[i],0x01,j)); // Coloumn 핀에 데이터 쓰기
        }
        digitalWrite(rowPin[i], LOW); // i 행 활성화
        delayMicroseconds(100);
        digitalWrite(rowPin[i], HIGH); // i 행 비활성화
    }
}
 
void serialEvent() // 엔터가 입력되기 까지의 문자를 myString 에 저장하고 recFlag 를 초기화
{
    char myChar = (char)Serial.read();
    myString += myChar;
    if(myChar == '\n')
    {
        recFlag = true;
    }
}
cs

코드 설명

이전의 코드에서 추가된 내용 중에 주요한 내용은 아래와 같습니다. 

  • 268 Line serialEvent()
    • 시리얼 통신이 수신 되면 호출되는 인터럽트 콜백 함수 입니다.
    • 시리얼 통신으로 문자를 입력 받으면 문자열 변수 myString 에 차곡차곡 저장
    • 엔터가 입력되면 recFlag 를 활성화
  • 207 ~ 227 line if문
    • 시리얼 통신으로 엔터가 입력되면 실행되는 if문
    • LED Matrix 에 출력할 데이터를 저장하고 있는 stringBuffer 를 초기화
    • stringBuffer 에 시리얼 통신으로 입력 받은 문자열을 입력

실행 결과

위의 코드를 실행하면 아래 영상과 같이 시리얼 통신으로 입력한 문자열이 LED Dot Matrix 로 출력되는 것을 확인 할 수 있습니다.

한계점

위와 같은 프로그램 코딩 방식으로 진행시 주요한 문제는 아래와 같습니다. 

  • Arduino Uno 보드의 동적 메모리 2048 Byte 중에서 1690 Byte 사용으로 메모리 여유가 없음
  • 코드가 길어서 코드 가독성이 떨어짐

마무리

이번 포스트에서

Arduino Uno 보드를 사용하여 8x8 LED 매트릭스에 문자열을 출력하는 방법

을 소개하였습니다. 이 같은 방법으로 코드 작성시 메모리 여유가 없고, 코드가 길어져 가독성이 떨어지는 문제가 있었습니다. 추후 포스트에서 이를 보완할 수 있는 방법에 대해 작성할 예정입니다. 

끝까지 읽어 주셔서 감사합니다.^^

관련포스트

👉 아두이노 LED Matrix 관련글 목록 보기

👉 아두이노 디스플레이 장치 관련글 목록 보기

👉 아두이노 관련글 전체 목록 보기