Skip to content
Home » 도트 매트릭스 프로그램 | Led 도트 매트릭스 디스플레이 및 Stm32 || 할 || 큐브Mx || 케일 126 개의 베스트 답변

도트 매트릭스 프로그램 | Led 도트 매트릭스 디스플레이 및 Stm32 || 할 || 큐브Mx || 케일 126 개의 베스트 답변

당신은 주제를 찾고 있습니까 “도트 매트릭스 프로그램 – LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일“? 다음 카테고리의 웹사이트 https://kk.taphoamini.com 에서 귀하의 모든 질문에 답변해 드립니다: https://kk.taphoamini.com/wiki/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 Controllers Tech 이(가) 작성한 기사에는 조회수 9,987회 및 좋아요 110개 개의 좋아요가 있습니다.

Table of Contents

도트 매트릭스 프로그램 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일 – 도트 매트릭스 프로그램 주제에 대한 세부정보를 참조하세요

Purchase the Products shown in this video from :: https://www.amazon.in/controllerstech
________________________________________________________________________________________

How to interface DOT MATRIX display with STM32 using CubeMX
To Download the code and for more information, visit
https://www.controllerstech.com/led-dot-matrix-and-stm32/
Check out more VIDEOS on MODULES/SENSORS with STM32 https://www.youtube.com/playlist?list=PLfIJKC1ud8ghLqcJla44AaidnTQokjEX1
******* SUPPORT US BY DONATING******
https://paypal.me/controllertech
*******Join the Membership*******
https://www.youtube.com/channel/UCkdqtSMnhYuMsJkyHOxiPZQ/join
Join the Discord Server https://discord.gg/D32JE5wKyD
Join the Telegram Group https://t.me/controllerstechdiscuss
Follow me on Instagram https://www.instagram.com/controllerstech/
For more info, visit https://www.controllerstech.com

도트 매트릭스 프로그램 주제에 대한 자세한 내용은 여기를 참조하세요.

8×8 Dot Matrix Calculator

8×8 Dot Matrix Calculator … 8051 8×8 도트 매트릭스 LED모듈 패턴 계산을 하기위한 도구입니다. 값 반전: 현재 계산된 결과 값에 ~(인버터)를 한 값 입니다. 복사하기: …

+ 여기에 보기

Source: dotmatrix.5corpion.dev

Date Published: 9/15/2021

View: 9584

8X8 도트매트릭스 제어하기 – 코코아팹

도트매트릭스는 출력 장치 중 하나로써 숫자, 문자, 이미지를 표시하기 위해 사용되는 방법 중 하나입니다. 가로 세로에 수백개의 점(LED)을 매트릭스 …

+ 자세한 내용은 여기를 클릭하십시오

Source: kocoafab.cc

Date Published: 6/20/2022

View: 9580

[아두이노] 8×8 도트 매트릭스 LED의 활용 (8×8 dot matrix led)

[아두이노] 8×8 도트 매트릭스 LED의 활용 (8×8 dot matrix led). 대네브 2015. 9. 17. 13:36 … 8×8 문자, 아이콘 만들기 프로그램 다운로드:.

+ 여기에 더 보기

Source: deneb21.tistory.com

Date Published: 11/22/2022

View: 6094

도트매트릭스 8×8 차례대로 켜기 / ㄹ 모양으로 흐르게 하기 – study

도트매트릭스 8×8 차례대로 켜기 / ㄹ 모양으로 흐르게 하기. sj0020 2020. 12. 9. 16:41. https://kogun.tistory.com/12 · AVR(ATmaga128)로 LED 매트릭스 장난하기.

+ 여기를 클릭

Source: sj0020.tistory.com

Date Published: 7/10/2022

View: 9981

도트 매트릭스 LED 생성기 – OnWorks

Dot Matrix LED Generator는 Ubuntu, Fedora, Debian, Kali Linux와 같은 온라인 Linux를 통해 OnWorks … 이러한 파일 관리자에서 이 응용 프로그램을 업로드합니다.

+ 여기에 표시

Source: www.onworks.net

Date Published: 7/7/2022

View: 2895

아두이노 – 도트 매트릭스 제어하기, dot matrix – postpop

도트 매트릭스를 사용하여 하트 캐릭터와 HELLO WORLD 문자를 한 글자씩 표시해보고 더 나아가 LED 전광판처럼 HELLO WORLD 전체 문자열이 오른쪽에서 …

+ 여기를 클릭

Source: postpop.tistory.com

Date Published: 8/21/2022

View: 7787

LED DOT MATRIX 8×8 Generator Program – Pinterest

LED DOT MATRIX 8×8 Generator Program Led Matrix, Arduino Projects, Triumph Bonneville, Microcontrollers. Visit. Save. From. 123microcontroller.com …

+ 더 읽기

Source: www.pinterest.com

Date Published: 4/1/2022

View: 7590

아두이노로 LED matrix 제어하기 #10 : Dot control 2 – TurtleShell

Arduino LedControl Library : 도트 단위로 LED 제어하기 #2 우선 이전 글에 이어서, … 몇 가지 예제를 실행하는 프로그램 전체 소스입니다.

+ 여기에 자세히 보기

Source: turtleshell.kr

Date Published: 12/11/2021

View: 1025

주제와 관련된 이미지 도트 매트릭스 프로그램

주제와 관련된 더 많은 사진을 참조하십시오 LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일
LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일

주제에 대한 기사 평가 도트 매트릭스 프로그램

  • Author: Controllers Tech
  • Views: 조회수 9,987회
  • Likes: 좋아요 110개
  • Date Published: 2019. 1. 9.
  • Video Url link: https://www.youtube.com/watch?v=hHBZi2K69QM

[아두이노] 8×8 도트 매트릭스 LED의 활용 (8×8 dot matrix led)

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

/* * Show messages on an 8×8 led matrix, * scrolling from right to left. * * Uses FrequencyTimer2 library to * constantly run an interrupt routine * at a specified frequency. This * refreshes the display without the * main loop having to do anything. * */ #include < FrequencyTimer2.h > //표현할 문자를 2진수로 정의 새로운 문자 추가 가능. #define SPACE { \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } \ } #define H { \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 } \ } #define E { \ { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 } \ } #define L { \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 }, \ { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 } \ } #define O { \ { 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 }, \ { 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 }, \ { 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 }, \ { 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 } \ } #define W { \ { 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },\ { 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 },\ { 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 },\ { 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 },\ { 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 },\ { 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 },\ { 0 , 0 , 1 , 1 , 0 , 1 , 0 , 0 },\ { 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 },\ } #define R { \ { 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 },\ { 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },\ { 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },\ { 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 },\ { 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 },\ { 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 },\ { 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },\ { 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 },\ } #define D { \ { 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 },\ { 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 },\ { 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 },\ { 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 },\ { 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 },\ { 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 },\ { 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 },\ { 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 },\ } byte col = 0 ; byte leds[ 8 ][ 8 ]; // pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1) int pins[ 17 ] = { – 1 , 5 , 4 , 3 , 2 , 14 , 15 , 16 , 17 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 }; // col[xx] of leds = pin yy on led matrix int cols[ 8 ] = {pins[ 13 ], pins[ 3 ], pins[ 4 ], pins[ 10 ], pins[ 06 ],pins[ 11 ], pins[ 15 ], pins[ 16 ]}; // row[xx] of leds = pin yy on led matrix int rows[ 8 ] = {pins[ 9 ], pins[ 14 ], pins[ 8 ], pins[ 12 ], pins[ 1 ],pins[ 7 ], pins[ 2 ], pins[ 5 ]}; //표현할 글자 수 const int numPatterns = 11 ; //표현할 문자 패턴, numPatterns 의 갯수에 맞게 표시 byte patterns[numPatterns][ 8 ][ 8 ] = { //H,E,L,L,O,SPACE H,E,L,L,O,W,O,R,L,D,SPACE }; int pattern = 0 ; void setup() { // sets the pins as output for ( int i = 1 ; i < = 16 ; i + + ) { pinMode(pins[i], OUTPUT); } // set up cols and rows for ( int i = 1 ; i < = 8 ; i + + ) { digitalWrite(cols[i - 1 ], LOW); } for ( int i = 1 ; i < = 8 ; i + + ) { digitalWrite(rows[i - 1 ], LOW); } clearLeds(); // Turn off toggling of pin 11 FrequencyTimer2::disable(); // Set refresh rate (interrupt timeout period) FrequencyTimer2::setPeriod( 2000 ); // Set interrupt routine to be called FrequencyTimer2::setOnOverflow(display); setPattern(pattern); } void loop() { pattern = + + pattern % numPatterns; slidePattern(pattern, 60 ); } void clearLeds() { // Clear display array for ( int i = 0 ; i < 8 ; i + + ) { for ( int j = 0 ; j < 8 ; j + + ) { leds[i][j] = 0 ; } } } void setPattern( int pattern) { for ( int i = 0 ; i < 8 ; i + + ) { for ( int j = 0 ; j < 8 ; j + + ) { leds[i][j] = patterns[pattern][i][j]; } } } void slidePattern( int pattern, int del) { for ( int l = 0 ; l < 8 ; l + + ) { for ( int i = 0 ; i < 7 ; i + + ) { for ( int j = 0 ; j < 8 ; j + + ) { leds[j][i] = leds[j][i + 1 ]; } } for ( int j = 0 ; j < 8 ; j + + ) { leds[j][ 7 ] = patterns[pattern][j][ 0 + l]; } delay(del); } } // Interrupt routine void display() { digitalWrite(cols[col], LOW); // Turn whole previous column off col + + ; if (col = = 8 ) { col = 0 ; } for ( int row = 0 ; row < 8 ; row + + ) { if (leds[col][ 7 - row] = = 1 ) { digitalWrite(rows[row], LOW); // Turn on this led } else { digitalWrite(rows[row], HIGH); // Turn off this led } } digitalWrite(cols[col], HIGH); // Turn whole column on at once (for equal lighting times) } Colored by Color Scripter

도트매트릭스 8×8 차례대로 켜기 / ㄹ 모양으로 흐르게 하기

2. 도트 매트릭스에 대해서 행과 열 개념을 이해하셔야 도트 매트릭스를 켤 수 있습니다. 이부분에 대해서 레포트 작성해주세요.

3. 도트매트릭스의 불빛 하나를 켜서 ㄹ 모양으로 불빛이 움직이게 프로그램을 작성해주세요.

4. 도트매트릭스에 0~9까지 숫자를 찍어서 나타나게 해주세요.

도트 매트릭스 LED 생성기

이것은 최신 릴리스가 88_Dox_Matrix_Gen.rar로 다운로드될 수 있는 Dot Matrix LED Generator라는 Linux 앱입니다. 워크스테이션용 무료 호스팅 제공업체 OnWorks에서 온라인으로 실행할 수 있습니다.

OnWorks와 함께 Dot Matrix LED Generator라는 이 앱을 무료로 다운로드하여 온라인으로 실행하십시오.

이 앱을 실행하려면 다음 지침을 따르세요.

– 1. 이 애플리케이션을 PC에 다운로드했습니다.

– 2. 파일 관리자 https://www.onworks.net/myfiles.php?username=XXXXX에 원하는 사용자 이름을 입력합니다.

– 3. 이러한 파일 관리자에서 이 응용 프로그램을 업로드합니다.

– 4. 이 웹사이트에서 OnWorks Linux 온라인 또는 Windows 온라인 에뮬레이터 또는 MACOS 온라인 에뮬레이터를 시작합니다.

– 5. 방금 시작한 OnWorks Linux OS에서 원하는 사용자 이름으로 파일 관리자 https://www.onworks.net/myfiles.php?username=XXXXX로 이동합니다.

– 6. 응용 프로그램을 다운로드하여 설치하고 실행합니다.

아두이노 – 도트 매트릭스 제어하기, dot matrix

아두이노에 8 x 8 도트 매트릭스를 연결하고 제어해보자.

도트 매트릭스를 사용하여 하트 캐릭터와 HELLO WORLD 문자를 한 글자씩 표시해보고 더 나아가 LED 전광판처럼 HELLO WORLD 전체 문자열이 오른쪽에서 왼쪽으로 이동하면서 표시되도록 코딩해보자.

연결

아두이노 2 번핀 -> 도트 매트릭스 9 번핀

아두이노 3 번핀 -> 도트 매트릭스 10 번핀

아두이노 4 번핀 -> 도트 매트릭스 11 번핀

아두이노 5 번핀 -> 도트 매트릭스 12 번핀

아두이노 6 번핀 -> 도트 매트릭스 13 번핀

아두이노 7 번핀 -> 도트 매트릭스 14 번핀

아두이노 8 번핀 -> 도트 매트릭스 15 번핀

아두이노 9 번핀 -> 도트 매트릭스 16 번핀

아두이노 A5(19) 번핀 -> 도트 매트릭스 8 번핀

아두이노 A4(18) 번핀 -> 도트 매트릭스 7 번핀

아두이노 A3(17) 번핀 -> 도트 매트릭스 6 번핀

아두이노 A2(16) 번핀 -> 도트 매트릭스 5 번핀

아두이노 10 번핀 -> 도트 매트릭스 4 번핀

아두이노 11 번핀 -> 도트 매트릭스 3 번핀

아두이노 12 번핀 -> 도트 매트릭스 2 번핀

아두이노 13 번핀 -> 도트 매트릭스 1 번핀

아두이노 – 도트 매트릭스 연결, 사진의 원안처럼 돌기가 나와있는 곳이 도트 매트릭스 전면부이고 왼쪽부터 핀번호1 ~ 8이다.

도트 매트릭스의 핀 부위에 돌기가 나와 있는 면이 전면이다. 전면을 기준으로 왼쪽 핀부터 핀번호 1 ~ 8번이고 위쪽으로 이동해서 우측부터 9번 ~ 16번 순으로 가게 된다. 상기 연결도를 참조하여 연결을 해보자.

도트 매트릭스 제어 코드를 살펴보기에 앞서 아래 기초 이론을 알아야 이해하기 쉽다.

LED: 발광 다이오드

전류: 두 전극 사이의 전위차에 의해 발생하는 흐름(5V – 0V : 전위차 5 발생, 전류는 5V -> 0V로 흐른다)

다이오드의 특성: 순방향으로 전류가 흐를 때 저항이 작고 역방향으로 전류가 흐를 때는 저항이 크다.

아래 그림의 LED는 순방향으로는 전류가 잘 흐르지만, 역방향은 전류가 거의 흐르지 않게 된다.

애노드(anode): 전류가 들어가는 전극, 양극

캐소드(cathode): 전류가 나오는 전극, 음극

도트 매트릭스 보는 방법

전면부를 아래로 하고 위에서 내려다봤을 때(상기 우측 그림) 위쪽이 1행(ROW1), 아래쪽이(돌기 있는 곳) 8행(ROW8)이고 왼쪽이 1열(COL1), 오른쪽이 8열(COL8)이다.

상기 그림에서 1행을 제어하기 위해서는 핀번호 9번을 제어를 해야 하고 8행을 제어하기 위해서는 핀번호 5번을 제어해야 한다. 마찬가지로 1열을 제어하기 위해서는 핀번호 13번, 8열을 제어하기 위해서는 핀번호 16번을 제어해야 한다. 만약 1행 1열을 제어하고 싶다면 핀번호 9번과 13번을 제어하면 된다.

여기서 살펴보아야 할게 상기 왼쪽 그림의 순방향에 따른 기호표를 살펴보고 오른쪽 그림의 기호표와 비교해보자. 행을 제어하는 모든 핀은 LED의 애노드에 연결되어 있고 열을 제어하는 모든 핀은 LED의 캐소드에 연결되어 있느것을 확인할 수 있다. 즉 애노드에 5V(HIGH)를 주고 캐소드에 0V(LOW)를 주게 되면 애노드와 캐소드 사이에 전위차가 발생하여 전류가 흐르게 되고 LED는 발광하게 된다. 여기서 다시 캐소드에 5V(HIGH)를 주게 되면 양단에 5V가 걸리게 되어 전위차가 0이 되므로 전류는 흐르지 않게 되고 LED는 발광하지 않는다. 만약 행을 제어하는 핀에 0V를 주고 열을 제어하는 핀에 5V를 주게 되면 전위차가 5 발생하지만 역방향 전류가 발생하게 된다. 역방향 전류는 거의 흐르지 않는 다이오드의 특성상 전류가 흐르지 않게 되어 이때에도 LED는 발광하지 않게 된다. 간단하게 얘기하자면 행과 열을 제어하는 핀에 상시 5V(HIGH)를 걸어주고(LED가 꺼진 상태) 열을 제어하는 핀에 필요에 따라 0V(LOW)로 변경해 주어 LED를 켜고 끄는 제어를 할 수 있게 된다.

더 자세히 살펴보자.

9번 핀에 5V를 걸어주면 1행 8개 LED에 5V가 걸리게 된다. 이때 13번 핀에 0V를 걸어주면 1행 1열의 LED가 켜지고 다시 5V를 걸어주면 LED가 꺼지게 된다. 또한 3번 핀에 0V 걸어주면 1행 2열의 LED가 켜지고 5V를 걸어주면 LED가 꺼지는 방식으로 1열 전체를 제어할 수 있게 된다.

이제 아두이노의 핀번호와 도트 매트릭스의 핀번호를 매칭 시켜보자.

도트 매트릭스의 행을 제어하기 위해 8비트 자료형 rowPin[8] 배열을 선언해주고 {1행-9, 2행-14, …. 8행-5}에 맞도록 연결도의 핀번호를 기입해준다.

연결도에서 1행을 제어하는 도트 매트릭스의 9번 핀에 연결된 것은 파란색 아두이노 2번 핀이다.

2행을 제어하는 토트 매트릭스의 14번 핀에 연결된 것은 회색 아두이노 7번 핀이다.

3행을 제어하는 토트 매트릭스의 8번 핀에 연결된 것은 회색 아두이노 19(A5)번 핀이다.

8행을 제어하는 도트 매트릭스의 5번 핀에 연결된 것은 노란색 아두이노 16(A2)번 핀이다.

상기 내용을 배열로 표현하면 아래와 같다.

uint8_t rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행-9, 2행-14, 3행-8, 4행-12, 5행-1, 6행-7, 7행-2, 8행-5}

열의 배열도 상기와 같은 방식으로 표현하면 아래와 같다.

uint8_t colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9};

도트 매트릭스를 사용하는 데 있어서 가장 혼란스럽게 만드는 핀 연결 및 핀번호 매칭이 완료되었다. 이제 아두이노의 기본 예제를 살펴보고 도트 매트릭스의 좌표 한 개부터 시작하여 열 단위, 행 단위를 제어해 보자.

좌표 한 개 제어

/* 아두이노 – 도트 매트릭스 핀 연결

byte rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행, 2행, 3행, 4행, 5행, 6행, 7행, 8행}

byte colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9}; // {1열, 2열, 3열, 4열, 5열, 6열, 7열, 8열}

*/

#define row 2 // 행 제어 핀번호

#define col 9 // 열제어 핀번호

void setup() {

pinMode(row, OUTPUT); // 행 제어 핀 출력 설정

pinMode(col, OUTPUT); // 열제어 핀 출력 설정

digitalWrite(row, HIGH); // row 핀 제어 – 1행 전원 공급

}

void loop() {

digitalWrite(col, LOW); // col핀 제어-1열 전원 차단 -> 0V -> 전위차 발생 -> 전류 흐름, LED ON

delay(1000);

digitalWrite(col, HIGH); // col핀 제어-1열 전원 공급 -> 5V -> 전위차 없음 -> 전류 흐르지 않음, LED OFF

delay(1000);

}

코딩한 코드를 아두이노에 업로드하면 1행 8열의 도트가 점멸하는 것을 볼 수 있다.

#define row 2의 핀 번호 2를 원하는 행 번호에 맞게 변경해주고 #define col 9의 핀번호 9를 열 번호에 맞게 변경해주면 해당 좌표의 도트가 점멸하도록 제어할 수 있다. 아두이노와 도트 매트릭스의 모든 핀이 연결된 상태이지만 상기 코드에서는 행과 열의 제어 출력 핀을 한 개씩만 핀 모드에서 설정해 주었으므로 전체 도트를 제어하지 못하고 한 좌표만 제어를 하게 된다.

아두이노에 연결된 모든 핀을 핀 모드에서 OUTPUT으로 설정해주고 전체 도트를 제어해보자

for 루프를 사용하여 미리 정의된 행과 열 배열의 모든 핀을 OUTPUT으로 설정해준다.

for (int i = 0; i < 8; i++) { pinMode(rowPin[i], OUTPUT); // 모든 행 제어 핀 모드 OUTPUT 설정 pinMode(colPin[i], OUTPUT); // 모든 열 제어 핀 모드 OUTPUT 설정 } 특정 행 제어 핀에 500 밀리초 간격으로 5V(HIGH), 0V(LOW)를 주어 5V가 걸려있을 때에는 열 제어 핀의 상태 값에 따라 도트의 LED가 켜지고 꺼질 수 있도록 준비상태를 부여하고 0V가 걸려 있을 때에는 열 제어 핀의 상태 값에 상관없이 특정 행의 모든 도트가 OFF 상태가 되어 리프레시 상태(다음 상태 값을 켜기 위한 준비)가 되도록 해준다. for (int i = 0; i < 8; i++) { // 행 제어 핀 전체 켜고 끄기 digitalWrite(rowPin[i], HIGH); // 모든 행 제어 핀에 전원 공급, LED ON 준비(열 제어 핀 상태에 따라 ON) delay(500); // 전원 공급 상태 유지 시간 digitalWrite(rowPin[i], LOW); // 모든 행 제어 핀에 전원 차단, 열 제어 핀 상태에 상관없이 OFF) } 열의 상태를 제어하기 위해 변수 byte pattern = 0b11111111;를 설정해주고 아래와 같이 입력값을 갖는 사용자 함수를 설정하여 setonoff(pattern); 형식으로 pattern값을 적용하도록 해준다. void setonoff(byte state) { // 입력값을 갖는 사용자 함수 for(int i = 0; i < 8; i++) { // 8개 열의 상태 값을 pattern 변수에서 추출 bool a = state >> i & 0x01? LOW : HIGH; // bool 자료형 사용 변숫값 변경 비트 마스크

digitalWrite(colPin[i], a); // 열 제어 핀 0b11111111 비트 값에 맞게 설정

}

}

변수 pattern에서 열의 비트 상태 값을 추출하기 위해 삼항 연산자를 이용하는 비트 마스크를 사용하였다. 비트 마스크에 대해 자세히 알고 싶다면 이전 글 아두이노 – 비트 마스크, bit mask를 참조하길 바란다.

byte rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행, 2행, 3행, 4행, 5행, 6행, 7행, 8행} byte colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9}; // {1열, 2열, 3열, 4열, 5열, 6열, 7열, 8열} byte pattern = 0b11111111; // 8개 열의 상태값 정의 void setup() { for (int i = 0; i < 8; i++) { pinMode(rowPin[i], OUTPUT); // 모든 행 제어 핀모드 OUTPUT 설정 pinMode(colPin[i], OUTPUT); // 모든 열 제어 핀모드 OUTPUT 설정 } } void loop() { setonoff(pattern); // 8개 열의 상태값을 pattern 변수에서 추출한뒤 설정하는 사용자 함수 for (int i = 0; i < 8; i++) { // delay(500); 시간 간격으로 아래로 한칸씩 행 이동행 제어핀 전체 켜고 끄기 digitalWrite(rowPin[i], HIGH); // 해당 행 제어핀에 전원공급, LED ON 준비(열 제어핀 상태에 따라 ON) delay(500); // 전원공급 상태 유지 시간 digitalWrite(rowPin[i], LOW); // 해당 행 제어핀에 전원차단, 열 제어핀 상태에 상관없이 OFF) } } void setonoff(byte state) { // 입력값을 갖는 사용자 함수 for(int i = 0; i < 8; i++) { // 8개 열의 상태값을 pattern 변수에서 추출 bool a = state >> i & 0x01? LOW : HIGH; // bool 자료형 사용 변수값 변경 비트 마스크 digitalWrite(colPin[i], a); // 열 제어핀 0b11111111 비트값에 맞게 설정 } }

상기 코드를 업로드하면 “0b11111111″의 상태 값에 따라 1열이 모두 켜진 상태에서 delay(500); 시간 간격에 따라 행이 위에서 아래로 변경되는 것을 확인할 수 있다. 여기에서 열의 상태 값인 이진수 “0b11111111″을 다른 값으로 변경해주면(0b11101011, 0b11111000…) 그 비트 값을 반영하여 표시되는 것을 볼 수 있다. 즉, 아래 그림처럼 1행의 8개 열을 모두 출력하고 다음 2행의 8개 열, …. 8행의 8개 열을 출력하는 것을 반복하게 된다. 반복하는 주기가 빠르게 되면 전체 8개행 모든 도트가 동시에 작동하는 것처럼 느끼게 될 것이다.

배열을 이용하여 행이 바뀌는 것에 따라 열의 상태 값 또한 바뀌도록 변경해 보자.

byte pattern = 0b11111111; 변수를 8개의 배열로 변경해주고 각 배열 요소에 이진수 상태 값을 아래와 같이 입력해준다.

byte pattern[8] = {0b01000010,0b10100101,0b10011001,0b10000001,0b10000001,0b01000010,0b00100100,0b00011000};

loop() 함수의 행 변경 for() 루프 코드 내에 행 변경 인자인 “i” 값에 연동하도록 setonoff(pattern[i]);와 같이 열 변경 함수를 위치시키게 되면 행이 위에서 아래로 변경될 때마다 행 번호에 해당하는 열 상태 값이 반영되어 도트 매트릭스에 표시되는 것을 볼 수 있다.

byte rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행, 2행, 3행, 4행, 5행, 6행, 7행, 8행} byte colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9}; // {1열, 2열, 3열, 4열, 5열, 6열, 7열, 8열} byte pattern[8] = {0b01000010,0b10100101,0b10011001,0b10000001,0b10000001,0b01000010,0b00100100,0b00011000}; void setup() { for (int i = 0; i < 8; i++) { pinMode(rowPin[i], OUTPUT); // 모든 행 제어 핀모드 OUTPUT 설정 pinMode(colPin[i], OUTPUT); // 모든 열 제어 핀모드 OUTPUT 설정 } } void loop() { for (int i = 0; i < 8; i++) { // delay(500); 시간 간격으로 아래로 한칸씩 행 이동행 제어핀 전체 켜고 끄기 setonoff(pattern[i]); // 8개 열의 상태값을 pattern 변수에서 추출한뒤 설정하는 사용자 함수 digitalWrite(rowPin[i], HIGH); // 해당 행 제어핀에 전원공급, LED ON 준비(열 제어핀 상태에 따라 ON) delay(500); // 전원공급 상태 유지 시간 digitalWrite(rowPin[i], LOW); // 해당 행 제어핀에 전원차단, 열 제어핀 상태에 상관없이 OFF) } } void setonoff(byte state) { for(int i = 0; i < 8; i++) { // 8개 열의 상태값을 pattern 변수에서 추출 bool a = state >> i & 0x01? LOW : HIGH; // bool 자료형 사용 변수값 변경 비트 마스크 digitalWrite(colPin[i], a); // 열 제어핀 0b11111111 비트값에 맞게 설정 } }

상기 코드에서 delay(500);을 delay(1);로 변경하고 업로드하면 빠르게 각 행마다 열 값을 쓰게 되어 눈으로 보기에는 정지된 하트 문자처럼 보이게 된다.

아두이노 기본 예제를 살표 보자.

아두이노 IDE에서 파일 -> 예제 -> Display -> RowColumnScanning 스케치를 불러오면 가변저항 두 개를 연결하여 X축(열)과 Y축(행)을 제어하도록 코드가 제시되어 있다. 또한 아두이노와 도트 매트릭스를 연결방법을 제시하는 글이 있는 아두이노 참조 사이트를 확인할 수 있다.

이 예제에서 가변저항 대신 시리얼 모니터에서 X, Y값을 입력하여 제어하도록 해보자. 아래와 같이 가변저항 관련 코드를 시리얼 모니터 제어용 코드로 코딩해 주었다.

// 가변저항 제어 코드

x = 7 – map(analogRead(A0), 0, 1023, 0, 7);

y = map(analogRead(A1), 0, 1023, 0, 7);

// 시리얼 모니터 제어 코드

if (Serial.available() > 0) { // read the sensors for X and Y values:

String temp = Serial.readStringUntil(‘

‘);

if (temp.indexOf(“,”) != -1) {

String x_temp = temp.substring(0, temp.indexOf(“,”));

String y_temp = temp.substring(temp.indexOf(“,”) + 1, temp.length());

x = x_temp.toInt();

y = y_temp.toInt();

}

}

또한 예제 코드에서는 좌표값이 변동될 경우를 대비해서 loop() 함수가 스캔할 때마다 현재 도트를 끄도록 하기 위해 pixels[x][y] = HIGH; 코드를 사용하였으나 이는 좌표 값의 변동이 없을 때에도 매 스캔마다 무조건 꺼졌다 켜지도록 하고 있다. 물론 꺼지고 켜지는 시간이 극히 짧아 눈으로 인지할 수는 없다. 이를 시리얼 모니터에 의해 좌표값이 전송될 때에만 현재 도트를 끄도록 위치를 조정해 주었다.

const int row[8] = {2, 7, 19, 5, 13, 18, 12, 16}; const int col[8] = {6, 11, 10, 3, 17, 4, 8, 9}; int pixels[8][8]; // 좌표값 이차원 배열 선언 int x = 4; // x, y 좌표 초기값 -> 6행, 6열 int y = 4; void setup() { Serial.begin(9600); for (int thisPin = 0; thisPin < 8; thisPin++) { pinMode(col[thisPin], OUTPUT); pinMode(row[thisPin], OUTPUT); digitalWrite(col[thisPin], HIGH); // 열 제어핀에 5V(HIGH)를 주어 확실하게 토트가 OFF 되도록 함 } for (int x = 0; x < 8; x++) { // 이차원배열 모든 좌표값을 HIGH 로 초기화 for (int y = 0; y < 8; y++) { // refreshScreen() 함수에 의해 pixels[x][y] = HIGH; // 열 상태 값은 HIGH로 변경됨 } } } void loop() { readSensors(); // 좌표 값 읽기 refreshScreen(); // 좌표 값 쓰기 } void readSensors() { if (Serial.available() > 0) { // x, y 좌표값 읽기 String temp = Serial.readStringUntil(‘

‘); if (temp.indexOf(“,”) != -1) { pixels[x][y] = HIGH; // 새 좌표값을 읽기 전에 이전 좌표의 도트 끄기 String x_temp = temp.substring(0, temp.indexOf(“,”)); String y_temp = temp.substring(temp.indexOf(“,”) + 1, temp.length()); x = x_temp.toInt(); y = y_temp.toInt(); } } pixels[x][y] = LOW; // 이차원배열 인데스 x,y에 LOW값 입력, refreshScreen() 함수에 의해 } // y열의 상태 값 LOW, 해당 도트 켜짐 void refreshScreen() { for (int x = 0; x < 8; x++) { // 8개 행 제어 digitalWrite(row[x], HIGH); // 한개 행 5V 걸어서 열 상태값에 따라 켜지고 꺼지도록 준비 for (int y = 0; y < 8; y++) { // 8개 열 제어 int thisPixel = pixels[x][y]; // 현재 행열 상태값 HIGH 또는 LOW 저장 digitalWrite(col[y], thisPixel); // 현재 열 제어핀에 상태값 쓰기 - 열 전체 도트 영향 받음 if (thisPixel == LOW) { // 만약 현재 열에 LOW 값이 있으면 다음행으로 넘어갈 때 꺼진상태를 유지하기위해 digitalWrite(col[y], HIGH); // 현재 열이 꺼지도록 초기화 한다. } } digitalWrite(row[x], LOW); // 현재 행에 0V를 주어 다음 행 제어시 영향을 받지 않도록 한다. } } 상기 코드를 업로드하고 시리얼 모니터에서 전송 옵션을 "새 글"로 한 상태에서 "0,0"을 입력하면 1행 1열 도트가 켜지고 "6,6"을 입력하면 7행 7열, "2,5"입력하면 3행 6열의 도트가 켜지는 것을 볼 수 있다. 핵심 코드 분석 void refreshScreen() { for (int x = 0; x < 8; x++) { // 8개 행 제어 digitalWrite(row[x], HIGH); // 한 개 행 5V 걸어서 열 상태 값에 따라 켜지고 꺼지도록 준비 for (int y = 0; y < 8; y++) { // 8개 열 제어 int thisPixel = pixels[x][y]; // 현재 행열 상태 값 HIGH 또는 LOW 저장 digitalWrite(col[y], thisPixel); // 현재 열 제어 핀에 상태 값 쓰기 - 열 전체 도트 영향 받음 if (thisPixel == LOW) { // 만약 현재 열에 LOW 값이 있으면 다음행으로 넘어갈 때 꺼진 상태를 유지하기 위해 digitalWrite(col[y], HIGH); // 현재 열을 모두 다시 꺼지도록 초기화한다. } } digitalWrite(row[x], LOW); // 행 값을 끈다. } } 상기 코드는 아래 행 제어 코드에 따라 행이 변경될 때마다 해당 행에 HIGH를 주어 열제어 코드의 상태 값에 따라 도트 가 켜지고 꺼지도록 준비하고 열제어 코드의 실행이 완료되면 다시 LOW로 변경하여 다음 열을 제어할 때 영향을 받지 않도록 해준다. for (int x = 0; x < 8; x++) { // 행 제어 코드 digitalWrite(row[x], HIGH); // 행에 5V를 걸어주어 토트를 켤 준비를 한다. 열 제어 코드 digitalWrite(row[x], LOW); // 행에 0V를 주어 다음 행 제어 시 영향을 받지 않도록 한다. } 해당 행에 HIGH인 상태에서 아래 열제어 코드에 따라 열의 상태 값을 한 개씩 확인하고 써준다. for (int y = 0; y < 8; y++) { // 8개 열 제어 int thisPixel = pixels[x][y]; // 현재 행열 상태 값 HIGH 또는 LOW 저장 digitalWrite(col[y], thisPixel); } 이 코드에서 만약 좌표 5, 5가 LOW였다면 digitalWrite(col[5], LOW); 가 되어 6행 6열의 도트에 불이 들어오게 된다. 즉 초기값 HIGH에서 현재 상태 값 LOW로 변경되어 토트가 켜지게 되는 것이다. 위 코드처럼 LOW인 상태에서 코드가 종료된다면 행 제어 코드에 의해 다음 행으로 넘어갈 때 digitalWrite(col[5], LOW); 인 상태로 들어가게 되어 7행 6열의 도트에도 불이 들어온 상태로 진입한 뒤 현재 상태 값 HIGH를 반영한 뒤에야 digitalWrite(col[5], HIGH);가 되어 도트가 꺼지게 된다. 즉 초기값이 LOW인 상태에서 진입한 뒤 현재 상태 값 HIGH로 변경되어 꺼지게 되는 것이다. 이를 방지하기 위해 아래 코드가 포함되어야만 픽셀 하나만 제어를 할 수 있다. 상기 스케치에서 아래 코드를 주석 처리해보고 확인해 보자. if (thisPixel == LOW) { // 만약 현재 열에 LOW 값이 있으면 digitalWrite(col[y], HIGH); // 현재 열을 모두 다시 꺼서 좌표의 도트만 잠깐 켜지도록 한다. } 도트 매트릭스에 HELLO WORLD 한 글자씩 표시해 보자. 아래 사이트에서 코드를 참조하고 이전 예제 코드를 적용하였다. http://www.86duino.com/?p=8300 //여러 줄을 묶은 매크로 '\' 이용, '\' 뒤에 어떤것도 없어야됨 #define SPACE { \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0} \ } #define H { \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0} \ } #define E { \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0} \ } #define L { \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0} \ } #define O { \ {0, 0, 0, 1, 1, 0, 0, 0}, \ {0, 0, 1, 0, 0, 1, 0, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 0, 1, 0, 0, 1, 0, 0}, \ {0, 0, 0, 1, 1, 0, 0, 0} \ } #define W { \ {1, 0, 0, 0, 0, 0, 0, 1},\ {1, 0, 0, 0, 0, 0, 1, 0},\ {1, 0, 0, 0, 0, 0, 1, 0},\ {0, 1, 0, 1, 0, 0, 1, 0},\ {0, 1, 0, 1, 0, 1, 0, 0},\ {0, 1, 0, 1, 0, 1, 0, 0},\ {0, 0, 1, 1, 0, 1, 0, 0},\ {0, 0, 0, 1, 1, 0, 0, 0},\ } #define R { \ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 0, 1, 0, 0, 0, 0, 0},\ {1, 0, 0, 1, 0, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 0, 0, 0, 0, 1, 0, 0},\ } #define D { \ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 1, 0, 0, 1, 1, 0, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 1, 1, 0, 0},\ {1, 1, 1, 1, 1, 0, 0, 0},\ } byte rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행, 2행, 3행, 4행, 5행, 6행, 7행, 8행} byte colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9}; // {1열, 2열, 3열, 4열, 5열, 6열, 7열, 8열} const int numPatterns = 11; //표현할 글자 수 unsigned long startTime = 0; byte patterns[numPatterns][8][8] = { //표현할 문자 패턴, numPatterns 의 갯수에 맞게 표시 H,E,L,L,O,W,O,R,L,D,SPACE //H,E,L,L,O,SPACE }; void setup() { for (byte i = 0; i < 8; i++) { pinMode(rowPin[i], OUTPUT); pinMode(colPin[i], OUTPUT); } } void loop() { setonoff(); } void setonoff() { for (byte i = 0; i < numPatterns; i++, startTime = millis()) { // 1초후 단어간 이동, 시간 초기화 while (millis() - startTime < 900) { // 1초 동안 문자 표시 for (byte j = 0; j < 8; j++) { // row 위치 조정 for (byte k =0; k < 8; k++) { // col 위치 조정 boolean a = !patterns[i][j][k]; // 3차원 배열값 가져오기 digitalWrite(colPin[k], a); // col 핀 제어 } digitalWrite(rowPin[j], HIGH); // row 핀 제어 delay(1); digitalWrite(rowPin[j], LOW); } } delay(100); // 단어간 구분 - 껏다 킴 } } 핵심 코드 분석 byte patterns[numPatterns][8][8] = { //표현할 문자 패턴, numPatterns의 개수에 맞게 표시 H,E,L,L,O,W,O,R,L,D,SPACE //H,E,L,L,O,SPACE }; 3차원 배열을 정의하는 데에 있어 2차원 배열 매크로를 사용하였다. 3차원 배열은 코딩할 때 다음과 같이 높이(또는 층의 수)x가로x세로 형태이로 이루어지고 아래와 같이 정의한다. 자료형 배열 이름[높이 또는 층의 수][면의 행 크기][면의 열 크기]; int numArr[2][3][4] = { { { 11, 22, 33, 44 }, { 55, 66, 77, 88 }, { 99, 110, 121, 132 } }, { { 111, 122, 133, 144 }, { 155, 166, 177, 188 }, { 199, 1110, 1121, 1132 } } }; // 3차원 배열에 값 저장 및 읽기 numArr[1][1][2] = 0; // 2층의 2번째 배열에서 인덱스 2번에 값 저장 177 -> 0

int temp = numArr[0][1][2] // 1층의 2번째 배열에서 인덱스 2번의 값 일고 대입 -> 77

상기 코드의 면에 해당하는 2차원 배열 요소 { { 11, 22, 33, 44 }, { 55, 66, 77, 88 }, { 99, 110, 121, 132 } }를 매크로를 이용하여 문자형태(H,E,L,L,O…. )로 정의하였다. 정의된 각 문자의 자리에 2차원 배열이 치환되게 된다.

#define H { \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 1, 1, 1, 1, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0}, \

{0, 1, 0, 0, 0, 0, 1, 0} \

}

// 한 줄로 표현하면 아래와 같다.

#define H { {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0},

{0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 0, 1, 0} }

상기 코드에서는 여러 줄을 묶어서 매크로로 정의하는 방법을 사용했다.

#define은 줄 바꿈이 일어날 때 \를 사용하여 여러 줄을 매크로로 만들 수 있다. 단, 맨 마지막 줄은 \를 사용하지 않아도 된다.

#define 매크로 이름 코드 1 \

코드 2 \

코드 3

따라서 마지막 줄 } 다음에는 \ 표시가 없다.

void setonoff() {

for (byte i = 0; i < numPatterns; i++, startTime = millis()) { // 1초 후 단어 간 이동, 시간 초기화 while (millis() - startTime < 900) { // 1초 동안 문자 표시 for (byte j = 0; j < 8; j++) { // row 위치 조정 for (byte k =0; k < 8; k++) { // col 위치 조정 boolean a = !patterns[i][j][k]; // 3차원 배열 값 가져오기 digitalWrite(colPin[k], a); // col 핀 제어 } digitalWrite(rowPin[j], HIGH); // row 핀 제어 delay(1); digitalWrite(rowPin[j], LOW); } } delay(100); // 단어 간 구분 - 껐다 킴 } } for 루프에서 조건을 만족하면 두 가지 연산을 실행하도록 되어 있다. i를 증가시키는 증감 연산(i++)과 밀리 초를 변수에 저장하는 대입 연산(startTime = millis())을 실행한다. for 루프 시작과 동시에 저장된 millis() 값에 지속되는 while 루프가 900 밀리 초동 안 소요하고 while루프를 빠져나오면 delay(100); 동안 더 소요되어 약 1초 뒤에 for 루프의 i값이 증가하게 된다. 그 1초의 시간 사이에 while 루프에 의해 900 밀리초 동안 도트 매트릭스에 3차원 배열의 층수에 해당하는 문자의 배열을 출력하고 delay(100);에 의해 모든 도트 매트릭스를 끔으로써 단어 간 구분을 하게 된다. delay(100); 코드를 삭제하거나 delay(1);로 변경하면 부드럽게 단어가 변경이 되나 LL처럼 연속되는 같은 단어의 구분이 되지 않게 된다. 필요에 따라 수정하면 된다. HELLO WORLD 문자열을 오른쪽에서 왼쪽으로 이동하여 표시되게 해 보자. 이전 코드에서는 각 문자(3차원 인덱스의 높이, 또는 층)를 기준으로 한 글자씩 출력해 주었다. 하지만 문자열의 이동을 표시하기 위해서는 문자 간 겹치는 구간이 생기게 되는데 이를 코딩할 때 코드로 구현해 주어야 한다. 문자열이 이동한다는 것은 3차원 배열 "patterns[i][j][k]"의 최초 1행 ~8행의 1회 출력(한문자 또는 3차원 인덱스 높이)하면 'H' 문자가 표시되고 그다음 1개 열이 이동하면 'H' 문자의 1열은 사라지고 다음 문자인 'E' 문자의 1열이 추가로 붙게 된다. 아래 그림처럼 'H' 문자와 'E'문자가 합쳐진 새로운 문자가 생성되고 이러한 작업이 총 문자수가 11개라면 한문자 당 이동 열 개수는 8이므로 11 x 8 = 88개가 되고, 이는 11개 문자의 문자열이 이동을 완료하는 3차원 배열의 높이 인덱스가 되게 된다. 즉, "8 x 8" 면 배열이 88개(높이 또는 층)가 있고 이 배열이 일정 시간 간격으로 도트 매트릭스에 표시되면 문자열이 이동하는 효과가 나타나게 되는 것이다. 3차원 배열 patterns[i][j][k]의 인덱스 변화 표 88개의 이차원 배열을 만들고 그 배열을 일정 간격으로 도트 매트릭스에 표시해 주어도 문자열이 이동하게 되지만 88개의 이차원 배열을 만드는 것 자체도 문제일 뿐만 아니라 문자가 바뀔 때마다 새로 전체 배열을 만들어 줘야 된다는 문제가 있게 된다. 상기 그림을 참조하여 새로운 문자가 생성될 때의 인덱스 변화 패턴을 분석하여 패턴을 표현하는 코드를 작성해 주면 새로운 배열을 생성하지 않고 문자에 대한 배열만을 이용하여 문자열이 이동하는 표현을 할 수 있게 된다. 88개의 층이 하나씩 증가할 때마다 인덱스 i값의 변화를 살펴보면 0층에서는 1행 ~ 8행의 1회 출력되는 동안 8개 열의 i값은 00000000(오랜지색 1행)이다. 출력이 완료되면 한 칸 왼쪽으로 이동하게 되는데 이때가 두 번째 층이 출력되는 부분이다. 이 층의 8개 열의 i값을 살펴보면 00000001(파란색 1행)이 된다. 이렇게 층이 증가할수록 i값의 위치가 한 칸씩 왼쪽으로 이동하다 8개 층의 출력이 완료되면 11111111이 되고 다음 층이 완료되면 11111112 이런 식으로 8개 층을 기준으로 문자 인덱스 숫자가 바뀌며 층수가 증가할수록 왼쪽으로 이동하게 된다. 좀 더 단순화시키면 아래와 같다. 0,0,0,0,0,0,0,0. 1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2, ~ 11,11,11,11,11,11,11,11 상기 숫자 배열이 있고 8개 칸이 있는 필터를 한 칸씩 우측으로 이동시켜서 보는 것과 같은 것이다. 이를 코드로 표현하면 아래와 같다. for (byte i = 0; i <= (patterns * 8); i++) { for (byte k = 0; k < 8; k++) { byte val = (i + k) / 8; } } 상기 코드에서 변수 i는 3차원 인덱스의 층수이고 k는 8개 칸의 필터가 된다(8개 묶음) 층수가 0일 때 val = 00000000 층수가 1일 때 val = 00000001 층수가 2일 때 val = 00000011 . . 아래 스케치를 업로드하고 출력되는 값을 확인해 보자. void setup() { Serial.begin(9600); byte patterns = 12; for (byte i = 0; i <= (patterns * 8); i++) { Serial.print(i); if (i < 10) Serial.print(" : "); else Serial.print(" : "); for (byte k = 0; k < 8; k++) { byte val = (i + k) / 8; Serial.print(val); } Serial.println(); } } void loop() { } 상기의 방법을 적용하여 이제 인덱스 k값의 변화를 살펴보자. 층수가 0일 때 val = 01234567 층수가 1일 때 val = 12345670 층수가 2일 때 val = 23456701 이 되어 층수가 증가할 때마다 0 ~ 7의 숫자가 한 칸씩 이동하면서 루프 하고 있다. 이를 코드로 표현하면 아래와 같다. for (byte i = 0; i <= (patterns * 8); i++) { // 글자 수 당 8열 for (byte k = 0; k < 8; k++) { byte val = (i+k) % 8; } } 아래 스케치를 업로드하고 출력되는 값을 확인해 보자. void setup() { Serial.begin(9600); byte patterns = 12; //표현할 글자 수 for (byte i = 0; i <= (patterns * 8); i++) { // 글자수당 8열 Serial.print(i); if (i < 10) Serial.print(" : "); else Serial.print(" : "); for (byte k = 0; k < 8; k++) { byte val = (i+k) % 8; Serial.print(val); } Serial.println(); } } void loop() { } 왼쪽으로 슬라이드 될 때에는 처음 시작이 SPACE부터 시작해야 'H'문자의 1열이 토트 매트릭스의 8열에서 나오기 시작한다. 따라서 SPACE 문자를 문자열 앞에 추가해 준다. const int numPatterns = 12; //표현할 글자 수 byte patterns[numPatterns][8][8] = { //표현할 문자 패턴, numPatterns의 개수에 맞게 표시 SPACE,H,E,L,L,O,W,O,R,L,D,SPACE //H,E,L,L,O,SPACE }; 이전에 HELLO WORLD를 한 글자씩 출력했던 코드에 상기에서 구현한 3차원 인덱스 변화 코드를 적용시켜보면 아래와 같다. void setonoff() { for (byte i = 0; i <= (numPatterns-1) * 8 ; i++, startTime = millis()) { // 전체 칸수, 시간 초기화 while (millis() - startTime < 60) { // 한 칸 이동 시간 for (byte j = 0; j < 8; j++) { // row 위치 조정 for (byte k =0; k < 8; k++) { // col 위치 조정 boolean a = !patterns[(i+k)/8][j][(i+k)%8]; // (i+k)/8: 열 한칸씩 이동, (i+k)%8: 이동만큼 열 위치 회전 digitalWrite(colPin[k], a); // col 핀 제어 } digitalWrite(rowPin[j], HIGH); // row 핀 제어 delay(1); digitalWrite(rowPin[j], LOW); } } } } 한문자씩 출력할 때에는 for 루프 변수 i가 문자수와 같았었지만 텍스트 이동 코드에서는 열 이동에 따른 새로 생성되는 층수가 포함된 숫자(문자수 x 8)로 변경해줘야 된다. 스페이스를 포함해서 문자수는 12개 이고 마지막 문자가 SPACE이다 하지만 실제 출력하고자 하는 문자는 11개가 되게 된다. 마지막 문자 SPACE 문자의 열까지 계속해서 열을 이동시킨다면 다음 13번째 문자가 있어야 되는데 13번째 문자는 없다. 따라서 전체 출력 열 개수는 12 x 8 = 96개가 아닌 11 x 8 = 88개가 된다. 즉 1개 문자는 공백이라고 보면 된다. 이를 적용한 코드는 "(numPatterns-1) * 8"이다. 또한 900 밀리초 동안 한 문자 출력이 유지되던 것을 1열 이동하는 시간에 맞게 밀리 초값을 조절해 주어야 한다. 아래 스케치를 업로드하고 밀리초 값을 변경해 텍스트 이동 속도를 조절해 보자. //여러 줄을 묶은 매크로 '\' 이용, '\' 뒤에 어떤것도 없어야됨, 표현할 문자를 2진수로 정의 새로운 문자 추가 가능. #define SPACE { \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0}, \ } #define H { \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0}, \ {0, 1, 0, 0, 0, 0, 1, 0} \ } #define E { \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0} \ } #define L { \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 0, 0, 0, 0, 0, 0}, \ {0, 1, 1, 1, 1, 1, 1, 0} \ } #define O { \ {0, 0, 0, 1, 1, 0, 0, 0},\ {0, 0, 1, 0, 0, 1, 0, 0},\ {0, 1, 0, 0, 0, 0, 1, 0},\ {0, 1, 0, 0, 0, 0, 1, 0},\ {0, 1, 0, 0, 0, 0, 1, 0},\ {0, 1, 0, 0, 0, 0, 1, 0},\ {0, 0, 1, 0, 0, 1, 0, 0},\ {0, 0, 0, 1, 1, 0, 0, 0},\ } #define W { \ {1, 0, 0, 0, 0, 0, 0, 1},\ {1, 0, 0, 0, 0, 0, 1, 0},\ {1, 0, 0, 0, 0, 0, 1, 0},\ {0, 1, 0, 1, 0, 0, 1, 0},\ {0, 1, 0, 1, 0, 1, 0, 0},\ {0, 1, 0, 1, 0, 1, 0, 0},\ {0, 0, 1, 1, 0, 1, 0, 0},\ {0, 0, 0, 1, 1, 0, 0, 0},\ } #define R { \ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 0, 1, 0, 0, 0, 0, 0},\ {1, 0, 0, 1, 0, 0, 0, 0},\ {1, 0, 0, 0, 1, 0, 0, 0},\ {1, 0, 0, 0, 0, 1, 0, 0},\ } #define D { \ {1, 1, 1, 1, 1, 0, 0, 0},\ {1, 1, 0, 0, 1, 1, 0, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 0, 1, 1, 0},\ {1, 1, 0, 0, 1, 1, 0, 0},\ {1, 1, 1, 1, 1, 0, 0, 0},\ } byte rowPin[8] = {2, 7, 19, 5, 13, 18, 12, 16}; // {1행, 2행, 3행, 4행, 5행, 6행, 7행, 8행} byte colPin[8] = {6, 11, 10, 3, 17, 4, 8, 9}; // {1열, 2열, 3열, 4열, 5열, 6열, 7열, 8열} unsigned long startTime = 0; const int numPatterns = 12; //표현할 글자 수 byte patterns[numPatterns][8][8] = { //표현할 문자 패턴, numPatterns 의 갯수에 맞게 표시 SPACE,H,E,L,L,O,W,O,R,L,D,SPACE //H,E,L,L,O,SPACE }; void setup() { for (byte i = 0; i < 8; i++) { pinMode(rowPin[i], OUTPUT); pinMode(colPin[i], OUTPUT); } } void loop() { setonoff(); } void setonoff() { for (byte i = 0; i <= (numPatterns-1) * 8 ; i++, startTime = millis()) { // 전체 칸수, 시간 초기화 while (millis() - startTime < 60) { // 한칸 이동 시간 for (byte j = 0; j < 8; j++) { // row 위치 조정 for (byte k =0; k < 8; k++) { // col 위치 조정 boolean a = !patterns[(i+k)/8][j][(i+k)%8]; // (i+k)/8: 열 한칸씩 이동, (i+k)%8: 이동만큼 열위치 회전 digitalWrite(colPin[k], a); // col 핀 제어 } digitalWrite(rowPin[j], HIGH); // row 핀 제어 delay(1); digitalWrite(rowPin[j], LOW); } } } } 관련 글 [arduino] - 아두이노 - 비트 연산자 [arduino] - 아두이노 - 비트 시프트 연산자 [arduino] - 아두이노 - 비트 마스크, bit mask [arduino] - 아두이노 - 도트 매트릭스 제어하기, dot matrix

LED DOT MATRIX 8×8 Generator Program

When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.

아두이노로 LED matrix 제어하기 #10 : Dot control 2

Arduino LedControl Library : 도트 단위로 LED 제어하기 #2 우선 이전 글에 이어서, 가로 및 세로 선 그리기 함수를 이용하여 사각형 모양의 선을 그리는 함수를 작성하겠습니다. 또, 이제 까지의 선 그리기 함수는 하나의 모듈을 대상으로 하는데, 이를 3개의 모듈로 확장하는 것까지 이번 글에서 처리하도록 하겠습니다.

사각형 모양 선 그리기 함수 만들기

이전 글에서 가로, 세로 방향으로 원하는 길이만큼 선을 그리는 함수를 작성하였고, 이제부터 두 함수를 참고하여 사각형 모양의 선을 그리는 함수를 작성하겠습니다.

void lineRect(int topX, int topY, int bottomX, int bottomY)

사각형 선 그리기 함수의 호출문은 위와 같이 작성하였습니다. 총 4개의 인수가 필요하며 각각 시작 좌표와 끝 좌표의 X, Y값입니다.

위와 같이 시작 점과 끝 점의 X, Y 좌표 4개의 인수가 필요합니다. setRow() 함수는 어느 행(row)에 출력할 지 인수로 지정해야 하는데, topX와 bottomX로 지정하면 되고, 마찬가지로 setColumn() 함수도 topY, bottomY를 출력할 위치로 지정하면 됩니다.

void loop() { lineRect(0, 0, 7, 7); delay(500); lineRect(1, 1, 6, 6); delay(500); lineRect(2, 2, 5, 5); delay(500); lineRect(3, 3, 4, 4); delay(500); }

loop() 함수에서 위와 같이 함수를 호출합니다. 시작점과 끝점이 1씩 줄거나 늘어나고 있는데, 사각형이 점점 중앙을 향해 모여드는 모습을 표현하도록 구성하였습니다.

// 선 그리기 – 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { byte data = B11111111; data = (data >> topY) & (data << (7 - bottomY)); lc.setRow(0, topX, data); } 우선, 위쪽 가로 선을 그리는 코드만 작성하였습니다. 가로 방향 선그리기 함수인 lineRow() 함수를 그대로 가져와서 인수명만 수정해도 원하는 결과를 볼 수 있습니다. topX 인수가 위쪽 라인이 출력될 row값에 해당하고 topY와 bottomY가 라인의 길이를 계산하는 데 사용됩니다. 결과 화면입니다. 각 사각형의 위 쪽 라인만 500밀리초 간격으로 차례대로 출력됩니다. // 선 그리기 - 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { byte data = B11111111; data = (data >> topY) & (data << (7 - bottomY)); lc.setRow(0, topX, data); lc.setRow(0, bottomX, data); } 6번 행을 추가하여 아래쪽 라인도 함께 그리도록 했습니다. 위, 아래 라인의 길이는 동일하기 때문에 따로 계산할 필요가 없고, 아래쪽 라인이 출력될 행(row)은 bottomX 변수값을 사용하면 됩니다. 결과 화면입니다. 같은 변수(data)를 사용해서 출력했기 때문에 대칭 모양을 보이고 있습니다. void loop() { lineRect(0, 0, 7, 7); delay(500); lc.clearDisplay(0); lineRect(1, 1, 6, 6); delay(500); lc.clearDisplay(0); lineRect(2, 2, 5, 5); delay(500); lc.clearDisplay(0); lineRect(3, 3, 4, 4); delay(500); lc.clearDisplay(0); } 세로 변 그리는 코드를 만들기 전에, 위와 같이 함수 호출후에 화면을 지워주도록 추가했습니다. 이 코드는 중첩하여 출력하는 기능이 없기 때문에 새로 출력하기 전에 이전 것은 지워줘야 합니다. // 선 그리기 - 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { // 출력전에 화면 지움 lc.clearDisplay(0); byte dataRow = B11111111; byte dataCol = B11111111; dataRow = (dataRow >> topY) & (dataRow << (7 - bottomY)); dataCol = (dataCol >> topX) & (dataCol << (7 - bottomX)); lc.setRow(0, topX, dataRow); lc.setRow(0, bottomX, dataRow); lc.setColumn(0, topY, dataCol); lc.setColumn(0, bottomY, dataCol); } 행과 열에 대한 데이터가 있어야 하므로 변수 하나를 추가하여 dataRow, dataCol로 이름 붙였습니다. 계산식은 행과 열이 동일하기에 복사한 후 변수명만 알맞게 고쳐주었고, 세로 방향이므로 setColumn() 함수를 추가하여 좌, 우 변을 출력하도록 했습니다. #include "LedControl.h" LedControl lc = LedControl(12,11,10,3); // void setup() { lc.shutdown(0, false); lc.shutdown(1, false); lc.shutdown(2, false); // lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // void loop() { int i, j; for (i = 0; i <= 7; i++) { lineRow(i, 0, 7); delay(100); } for (i = 0; i <= 7; i++) { lc.setRow(0, i, 0); delay(100); } for (i = 0; i <= 7; i++) { lineCol(i, 0, 7); delay(100); } for (i = 0; i <= 7; i++) { lc.setColumn(0, i, 0); delay(100); } for (i = 0; i <= 7; i++) { lineRow(i, 0, i); delay(100); } for (i = 0; i <= 7; i++) { lineRow(i, i, 7); delay(100); } for (i = 0; i <= 5; i++) { lc.clearDisplay(0); lineRect(i, i, 7 - i, 7 - i); delay(400); } } // 선 그리기 - 행 방향 void lineRow(int row, int startLed, int endLed) { byte data = B11111111; data = (data >> startLed) & (data << (7 - endLed)); lc.setRow(0, row, data); } // 선 그리기 - 열 방향 void lineCol(int col, int startLed, int endLed) { byte data = B11111111; data = (data >> startLed) & (data << (7 - endLed)); lc.setColumn(0, col, data); } // 선 그리기 - 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { byte dataRow = B11111111; byte dataCol = B11111111; dataRow = (dataRow >> topY) & (dataRow << (7 - bottomY)); dataCol = (dataCol >> topX) & (dataCol << (7 - bottomX)); lc.setRow(0, topX, dataRow); lc.setRow(0, bottomX, dataRow); lc.setColumn(0, topY, dataCol); lc.setColumn(0, bottomY, dataCol); } 여기까지 해서, 하나의 모듈을 대상으로 하는 가로, 세로, 네모 선 그리기 함수를 작성해 보았고, 이들을 조합하여 간단한 출력 예제를 작성하였습니다. 결과 화면은 아래 동영상을 보시면 됩니다. 세 개의 모듈에 가로 선 그리기 이제까지의 그리기 함수는 하나의 모듈을 대상으로 했습니다. 이제, 3개의 모듈을 하나의 화면으로 삼아 선을 그리는 함수를 작성해 보겠습니다. 먼저 가로 선 그리기 함수입니다. 모듈이 3개이기 때문에, 각 모듈에 그려질 데이터를 준비하기 위한 변수로 data[3]를 사용하고, 적절한 비트 연산 등을 이용해 각 변수를 채우도록 합니다. void lineRow(int row, int startLed, int endLed) { int i; byte data[3] = {B00000000, B00000000, B00000000}; // lc.setRow(0, row, data[0]); lc.setRow(1, row, data[1]); lc.setRow(2, row, data[2]); } for문 첨자로 쓰일 변수 i와 각 모듈의 데이터를 담을 byte type의 변수 data[3]을 선언하였습니다. 우선 모든 비트를 "0"으로 초기화한 후, 필요한 비트만 "1"로 세팅하도록 코딩할 것입니다. 모든 데이터가 처리된 후에는 setRow() 함수를 이용하여 각 모듈에 차례대로 출력해 줍니다. // 1번 모듈에 해당하는 데이터 구하기 for (i = startLed; (i <= 7) && (i <= endLed); i++) { data[0] = data[0] | B10000000 >> i; }

우선, 첫 번째 모듈에 출력할 데이터를 구하는 코드입니다. 마치 펜으로 선을 그리듯이, 시작점(startLed)에서 부터 비트를 “1”로 채워 나갑니다. 만약, 시작점이 첫 번째 모듈이 아닌 두, 세 번째 모듈이라면 저 for문은 실행하지 않습니다. 시작점이 for문 반복을 위한 변수 i의 초기값( i = startLed )이기 때문에, 첫 번째 모듈의 LED 범위를 벗어날 경우( i <= 7 ) for문을 아예 진입하지 않기 때문입니다. for문의 반복을 위한 조건은 두 가지입니다. i = 7 과 i <= endLed 가 AND 연산으로 연결되어 있기 때문에 둘 다 만족해야 합니다. 그리려는 선의 끝점이 첫 번째 모듈안에 있을 경우도 체크해야 하기 때문입니다. for문 안쪽은 딱 한 줄의 코드만 있습니다. 반복할 때마다 i 값이 증가하고 그 값만큼 비트 시프트를 실행합니다. 이렇게 하면 원하는 부분의 비트값을 "1"로 만들 수 있고, 이 값을 첫 번째 모듈을 위한 데이터(data[0])에 비트OR 연산으로 합쳐 주는 것입니다. // 2번 모듈에 해당하는 데이터 구하기 if (endLed >= 8) { for (i = (startLed – 8); (i <= 7) && (i <= (endLed - 8)); i++) { data[1] = data[1] | B10000000 >> i; } }

출력할 데이터가 2번 모듈에 걸쳐 있을 때만 실행되는 코드입니다. if문에서 끝 점이 2번 모듈이나 3번 모듈에 있는지( endLed >= 8 ) 체크합니다. 끝 점이 “7” 이하라면 그릴려는 선이 1번 모듈에만 있기 때문에 이 코드는 실행하지 않습니다. 나머지는 1번 모듈을 위한 위 쪽 코드와 동일합니다.

3개 모듈의 LED를 0번에서 23번까지 번호 붙여 코딩하고 있지만, 어느 한 모듈내에서는 0번에서 7번으로 변환해야 합니다. 두 번째 모듈도 8번에서 15번까지의 인덱스값을, 시작 점과 끝 점에서 “8”씩 빼서 0번 ~ 7번으로 변환해주었습니다.

// 선 그리기 – 행 방향 void lineRow(int row, int startLed, int endLed) { int i; byte data[3] = {B00000000, B00000000, B00000000}; // 1번 모듈에 해당하는 데이터 구하기 for (i = startLed; (i <= 7) && (i <= endLed); i++) { data[0] = data[0] | B10000000 >> i; } // 2번 모듈에 해당하는 데이터 구하기 if (endLed >= 8) { for (i = (startLed – 8); (i <= 7) && (i <= (endLed - 8)); i++) { data[1] = data[1] | B10000000 >> i; } } // 3번 모듈에 해당하는 데이터 구하기 if (endLed >= 16) { for (i = (startLed – 16); (i <= 7) && (i <= (endLed - 16)); i++) { data[2] = data[2] | B10000000 >> i; } } lc.setRow(0, row, data[0]); lc.setRow(1, row, data[1]); lc.setRow(2, row, data[2]); }

완성된 함수 코드입니다. 3번 모듈도 같은 방식으로 추가했습니다.

// 선 그리기 – 행 방향 void lineRow(int row, int startLed, int endLed) { int i; byte data[3] = {B00000000, B00000000, B00000000}; // 출력할 데이터 구하기 for ( i = startLed; i <= endLed; i++) { if (i <= 7) { data[0] = data[0] | B10000000 >> i; } else if (i <= 15) { data[1] = data[1] | B10000000 >> (i – 8); } else if (i <= 23) { data[2] = data[2] | B10000000 >> (i – 16); } } lc.setRow(0, row, data[0]); lc.setRow(1, row, data[1]); lc.setRow(2, row, data[2]); }

위 함수를 하나의 for문과 if문을 사용하여 좀 더 간단하게 표현한 코드입니다. 결과는 역시 동일합니다.

#include “LedControl.h” LedControl lc = LedControl(12,11,10,3); // void setup() { lc.shutdown(0, false); lc.shutdown(1, false); lc.shutdown(2, false); // lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // void loop() { int i; for (i = 0; i <= 7; i++) { lineRow(i, 0, 23); delay(60); } for (i = 0; i <= 7; i++) { lc.setRow(0, i, 0); lc.setRow(1, i, 0); lc.setRow(2, i, 0); delay(60); } for (i = 0; i <= 7; i = i + 2) { lineRow(i, 0, 23); delay(60); } for (i = 1; i <= 7; i = i + 2) { lineRow(i, 0, 23); delay(60); } for (i = 0; i <= 7; i = i + 2) { lc.setRow(0, i, 0); lc.setRow(1, i, 0); lc.setRow(2, i, 0); delay(60); } for (i = 1; i <= 7; i = i + 2) { lc.setRow(0, i, 0); lc.setRow(1, i, 0); lc.setRow(2, i, 0); delay(60); } for (i = 0; i <= 7; i++) { lineRow(i, 0, 7); delay(60); } for (i = 0; i <= 7; i++) { lineRow(i, 8, 15); delay(60); } for (i = 0; i <= 7; i++) { lineRow(i, 16, 23); delay(60); } lc.clearDisplay(2); for (i = 0; i <= 23; i++) { lineRow(0, 0, i); delay(60); } for (i = 23; i >= 0; i–) { lineRow(1, i, 23); delay(60); } for (i = 0; i <= 24; i++) { lineRow(2, i, 24); delay(60); } for (i = 23; i >= -1; i–) { lineRow(3, 0, i); delay(60); } for (i = 0; i <= 24; i++) { lineRow(4, i, i + 8); delay(60); } for (i = 0; i <= 24; i++) { lineRow(5, i, i + 5); delay(30); } for (i = 0; i <= 23; i++) { lineRow(6, 0, i); delay(30); } for (i = 0; i <= 24; i++) { lineRow(6, i, 24); delay(30); } for (i = 23; i >= 0; i–) { lineRow(7, i, 23); delay(30); } for (i = 23; i >= -1; i–) { lineRow(7, 0, i); delay(30); } lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // 선 그리기 – 행 방향 void lineRow(int row, int startLed, int endLed) { int i; byte data[3] = {B00000000, B00000000, B00000000}; // 출력할 데이터 구하기 for ( i = startLed; i <= endLed; i++) { if (i <= 7) { data[0] = data[0] | B10000000 >> i; } else if (i <= 15) { data[1] = data[1] | B10000000 >> (i – 8); } else if (i <= 23) { data[2] = data[2] | B10000000 >> (i – 16); } } lc.setRow(0, row, data[0]); lc.setRow(1, row, data[1]); lc.setRow(2, row, data[2]); }

몇 가지 예제를 실행하는 프로그램 전체 소스입니다. 결과는 아래 동영상을 확인하시면 됩니다.

세 개의 모듈에 세로 선 그리기

우선 모듈이 옆으로 붙어 있고 아래쪽은 없기 때문에 세로 선의 길이는 이전과 동일(0 ~ 7)합니다. 단지, 출력될 위치가 세 개의 모듈중 어느 곳인지만 체크하면 됩니다.

// 선 그리기 – 열 방향 void lineCol(int col, int startLed, int endLed) { byte data = B11111111; data = (data >> startLed) & (data << (7 - endLed)); if (col <= 7) { lc.setColumn(0, col, data); } else if (col <= 15) { lc.setColumn(1, col - 8, data); } else if (col <= 23) { lc.setColumn(2, col - 16, data); } } 세로 선을 그리는 함수의 전체 코드입니다. 표시된 부분만 추가됐을 뿐, 나머지는 이전의 코드와 동일합니다. 출력될 위치(int col)의 값을 따져서 몇 번째 모듈인지 확인하는 부분이 5번 행부터 11번 행까지 해당하며, 세 개의 모듈에 걸쳐 출력될 일이 없기 때문에 출력 코드도 단순합니다. #include "LedControl.h" // 3개 모듈 세로 선 그리기 LedControl lc = LedControl(12,11,10,3); // void setup() { lc.shutdown(0, false); lc.shutdown(1, false); lc.shutdown(2, false); // lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // void loop() { int i; for (i = 0; i <= 23; i++) { lineCol(i, 0, 7); delay(60); } for (i = 0; i <= 7; i++) { lc.setColumn(0, i, 0); delay(60); } for (i = 0; i <= 7; i++) { lc.setColumn(1, i, 0); delay(60); } for (i = 0; i <= 7; i++) { lc.setColumn(2, i, 0); delay(60); } for (i = 23; i >= 0; i–) { lineCol(i, 0, 7); delay(60); } for (i = 7; i >= 0; i–) { lc.setColumn(2, i, 0); delay(60); } for (i = 7; i >= 0; i–) { lc.setColumn(1, i, 0); delay(60); } for (i = 7; i >= 0; i–) { lc.setColumn(0, i, 0); delay(60); } for (i = 0; i <= 7; i++) { lineCol(i, 0, i); delay(60); } for (i = 8; i <= 15; i++) { lineCol(i, 0, 8 - (i - 8)); delay(60); } for (i = 16; i <= 23; i++) { lineCol(i, 0, i - 16); delay(60); } for (i = 0; i <= 7; i++) { lineCol(i, 0, 8 - i); delay(60); } for (i = 8; i <= 15; i++) { lineCol(i, 0, i - 8); delay(60); } for (i = 16; i <= 23; i++) { lineCol(i, 0, 8 - (i - 16)); delay(60); } for (i = 0; i < 4; i++) { lineCol(i, 3 - i, 4 + i); delay(30); } for (i = 0; i < 4; i++) { lineCol(i + 4, i, 7 - i); delay(30); } for (i = 0; i < 4; i++) { lineCol(i + 8, 3 - i, 4 + i); delay(30); } for (i = 0; i < 4; i++) { lineCol(i + 12, i, 7 - i); delay(30); } for (i = 0; i < 4; i++) { lineCol(i + 16, 3 - i, 4 + i); delay(30); } for (i = 0; i < 4; i++) { lineCol(i + 20, i, 7 - i); delay(30); } delay(500); lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // 선 그리기 - 열 방향 void lineCol(int col, int startLed, int endLed) { byte data = B11111111; data = (data >> startLed) & (data << (7 - endLed)); if (col <= 7) { lc.setColumn(0, col, data); } else if (col <= 15) { lc.setColumn(1, col - 8, data); } else if (col <= 23) { lc.setColumn(2, col - 16, data); } } 예제를 포함한 전체 소스입니다. 결과도 동영상으로 확인할 수 있습니다. 3개의 모듈에 사각 모양 선 그리기 함수 구현 선 그리기 함수의 마지막으로 사각 모양으로 선을 출력하는 함수를 만들겠습니다. 가로, 세로 선 그리기 함수를 합치기만 하면 되기 때문에 간단하게 만들 수 있습니다. // 선 그리기 - 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { int i; byte dataRow[3] = {B00000000, B00000000, B00000000}; byte dataCol = B11111111; // // } 우선 기본 구조는 모듈 하나를 위한 함수와 동일합니다. 가로, 세로 각각 출력 데이터를 위한 변수를 선언하고 초기화해주었습니다. // 선 그리기 - 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { int i; byte dataRow[3] = {B00000000, B00000000, B00000000}; byte dataCol = B11111111; // // 가로 방향 출력할 데이터 구하기 for ( i = topX; i <= bottomX; i++) { if (i <= 7) { dataRow[0] = dataRow[0] | B10000000 >> i; } else if (i <= 15) { dataRow[1] = dataRow[1] | B10000000 >> (i – 8); } else if (i <= 23) { dataRow[2] = dataRow[2] | B10000000 >> (i – 16); } } // 세로 방향 출력할 데이터 구하기 dataCol = (dataCol >> topY) & (dataCol << (7 - bottomY)); // } 가로, 세로 출력 데이터를 구하는 코드입니다. 각각의 함수에서 복사해 온 후, 변수 이름만 맞게 고쳐주었습니다. // 가로 방향 윗 변 출력하기 lc.setRow(0, topY, dataRow[0]); lc.setRow(1, topY, dataRow[1]); lc.setRow(2, topY, dataRow[2]); // 가로 방향 윗 변 출력하기 lc.setRow(0, bottomY, dataRow[0]); lc.setRow(1, bottomY, dataRow[1]); lc.setRow(2, bottomY, dataRow[2]); // 세로 방향 왼쪽 변 출력 if (topX <= 7) { lc.setColumn(0, topX, dataCol); } else if (topX <= 15) { lc.setColumn(1, topX - 8, dataCol); } else if (topX <= 23) { lc.setColumn(2, topX - 16, dataCol); } // 세로 방향 오른쪽 변 출력 if (bottomX <= 7) { lc.setColumn(0, bottomX, dataCol); } else if (bottomX <= 15) { lc.setColumn(1, bottomX - 8, dataCol); } else if (bottomX <= 23) { lc.setColumn(2, bottomX - 16, dataCol); } 화면 출력 코드입니다. 이전 함수와 동일하고 단지, 모듈이 3개여서 한 쪽변에 3번씩 출력하는 것만 다릅니다. 아래쪽 세로 방향 출력은 역시 위에서 만든 세로 선 그리기 함수에서 가져와 변수명만 고쳤습니다. #include "LedControl.h" // 3개 모듈 사각모양 선 그리기 LedControl lc = LedControl(12,11,10,3); // void setup() { lc.shutdown(0, false); lc.shutdown(1, false); lc.shutdown(2, false); // lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } // void loop() { int i, j; for (j = 0; j < 3; j++) { for (i = 0; i < 4; i++) { lineRect(0 + i, 0 + i, 23 - i, 7 - i); delay(100); lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } } for (i = 0; i < 24; i++) { lineRect(0 + i, 0, 3 + i, 3); delay(60); lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } for (i = 0; i < 7; i++) { lineRect(0, 0, 2 + i * 3, 0 + i); delay(60); lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } bool down = true; j = 0; for (i = 0; i < 24; i++) { if (down) { lineRect(0 + i, 0 + j, 2 + i, 2 + j); j++; if (j > 5) down = false; } else { j–; lineRect(0 + i, 0 + j, 2 + i, 2 + j); if ( j == 0) down = true; } delay(80); lc.clearDisplay(0); lc.clearDisplay(1); lc.clearDisplay(2); } } // 선 그리기 – 사각형 void lineRect(int topX, int topY, int bottomX, int bottomY) { int i; byte dataRow[3] = {B00000000, B00000000, B00000000}; byte dataCol = B11111111; // 가로 방향 출력할 데이터 구하기 for ( i = topX; i <= bottomX; i++) { if (i <= 7) { dataRow[0] = dataRow[0] | B10000000 >> i; } else if (i <= 15) { dataRow[1] = dataRow[1] | B10000000 >> (i – 8); } else if (i <= 23) { dataRow[2] = dataRow[2] | B10000000 >> (i – 16); } } // 세로 방향 출력할 데이터 구하기 dataCol = (dataCol >> topY) & (dataCol << (7 - bottomY)); // // 가로 방향 윗 변 출력하기 lc.setRow(0, topY, dataRow[0]); lc.setRow(1, topY, dataRow[1]); lc.setRow(2, topY, dataRow[2]); // 가로 방향 윗 변 출력하기 lc.setRow(0, bottomY, dataRow[0]); lc.setRow(1, bottomY, dataRow[1]); lc.setRow(2, bottomY, dataRow[2]); // 세로 방향 왼쪽 변 출력 if (topX <= 7) { lc.setColumn(0, topX, dataCol); } else if (topX <= 15) { lc.setColumn(1, topX - 8, dataCol); } else if (topX <= 23) { lc.setColumn(2, topX - 16, dataCol); } // 세로 방향 오른쪽 변 출력 if (bottomX <= 7) { lc.setColumn(0, bottomX, dataCol); } else if (bottomX <= 15) { lc.setColumn(1, bottomX - 8, dataCol); } else if (bottomX <= 23) { lc.setColumn(2, bottomX - 16, dataCol); } } 완성된 함수와 예제 소스입니다. 이전 글부터 여기까지 가로, 세로, 네모 모양의 선을 그리는 함수를 작성하였습니다. 먼저 하나의 모듈을 대상으로 출력하는 함수를 작성하고, 이번 글에서 3개의 모듈로 확장하였습니다. 특히, 비트 연산자를 통하여 출력 데이터를 준비하는 코드를 이용하여 도트(개별 LED) 단위로 출력하는 방법을 알아 보았습니다. 이상입니다.

키워드에 대한 정보 도트 매트릭스 프로그램

다음은 Bing에서 도트 매트릭스 프로그램 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일

  • stm32
  • stm32f103
  • hal
  • cube
  • led
  • dot
  • matrix
  • display
  • keil
  • uart

LED #도트 #매트릭스 #디스플레이 #및 #STM32 #|| #할 #|| #큐브Mx #|| #케일


YouTube에서 도트 매트릭스 프로그램 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 LED 도트 매트릭스 디스플레이 및 STM32 || 할 || 큐브Mx || 케일 | 도트 매트릭스 프로그램, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

See also  인텔 슈팅 스타 가격 | I9-13900K가 589달러?! 가격으로 공격하는 인텔 상위 200개 답변

Leave a Reply

Your email address will not be published. Required fields are marked *