안녕하세요! 아두이노 UNO와 74HC595 시프트 레지스터로 48×8 프로그래머블 스크롤링 LED 매트릭스를 만드는 프로젝트입니다. 제 첫 아두이노 프로젝트로, 선생님의 도전 과제였습니다. 당시 LED 깜빡이는 법도 몰랐지만, 인내심과 이해만 있으면 초보자도 가능합니다. 회로도는 온라인에서 찾아 참고했고, 시프트 레지스터와 멀티플렉싱을 공부하며 진행했습니다.
회로도
부품 준비
5mm 8×8 공통 캐소드 LED 매트릭스를 온라인 구매.
프로토타입 제작
회로도상 1개 시프트 레지스터가 8개 행 제어, 열은 8열마다 1개씩 시프트 레지스터 사용. 즉, 8×8 모듈 하나 만들 줄 알면 열 제어 부분만 복제해 원하는 열 수만큼 확장 가능. 8열 추가마다 74HC595 1개 추가.
납땜 및 확장
행/열 제어부를 별도 도트 기판에 만들고 와이어/헤더로 연결. 8×8 성공하면 열용 시프트 레지스터를 데이지체인(공통 클럭)으로 연결해 확장. 행 제어는 1개 시프트 레지스터로 충분, 열 수 제한 없음.
후반부 제작 및 케이스
3D 프린터가 없어 지역 목수에게 케이스 의뢰. 예상보다 커서 Fusion 360 등으로 설계 후 3D 프린트 권장. 전원/USB 구멍 뚫음.
코드 설명
코드는 첨부 파일에 있습니다. 행을 스캔하며 열 라인에 적절한 로직 레벨 공급. 스크롤 속도와 메시지 결정. 기본 오른쪽→왼쪽 스크롤, 약간 수정으로 다른 방향 가능.
결과
작동 영상 확인 가능.
감사합니다! :)
코드
48×8 LED 매트릭스 아두이노 코드 (C/C++)
/*////////////////////////////////////////////////////////////////////////////////
* 6개 이상 8x8 LED 매트릭스에 스크롤 문자 표시 아두이노 코드
* 매트릭스 개수는 코드 약간 수정으로 증가 가능
* 각 문장에 주석으로 편집 설명
* Coded by Prasanth K S
* Contact: kksjunior@hotmail.com
*////////////////////////////////////////////////////////////////////////////////
char msg[] = "WELCOME WIZ"; // 표시할 텍스트 수정
int scrollspeed = 5; // 스크롤 속도(낮을수록 빠름)
int x, y;
// 열 제어 핀
int clockPin1 = 2; // 74HC595 Clock Pin 11
int latchPin1 = 3; // 74HC595 Latch Pin 12
int dataPin1 = 4; // 74HC595 Data Pin 14
// 행 제어 핀
int clockPin2 = 5;
int latchPin2 = 6;
int dataPin2 = 7;
// 비트맵: 8행, 6존(6개 매트릭스)
byte bitmap[8][7];
int numZones = sizeof(bitmap) / 8; // 1존 = 8×8 매트릭스(8열 그룹)
int maxZoneIndex = numZones - 1;
int numCols = numZones * 8;
// 폰트 정의 (5×7, 컬럼 단위)
byte alphabets[][8] = {
{0,0,0,0,0}, // @ = SPACE
{31, 36, 68, 36, 31}, // A
{127, 73, 73, 73, 54}, // B
{62, 65, 65, 65, 34}, // C
{127, 65, 65, 34, 28}, // D
{127, 73, 73, 65, 65}, // E
{127, 72, 72, 72, 64}, // F
{62, 65, 65, 69, 38}, // G
{127, 8, 8, 8, 127}, // H
{0, 65, 127, 65, 0}, // I
{2, 1, 1, 1, 126}, // J
{127, 8, 20, 34, 65}, // K
{127, 1, 1, 1, 1}, // L
{127, 32, 16, 32, 127}, // M
{127, 32, 16, 8, 127}, // N
{62, 65, 65, 65, 62}, // O
{127, 72, 72, 72, 48}, // P
{62, 65, 69, 66, 61}, // Q
{127, 72, 76, 74, 49}, // R
{50, 73, 73, 73, 38}, // S
{64, 64, 127, 64, 64}, // T
{126, 1, 1, 1, 126}, // U
{124, 2, 1, 2, 124}, // V
{126, 1, 6, 1, 126}, // W
{99, 20, 8, 20, 99}, // X
{96, 16, 15, 16, 96}, // Y
{67, 69, 73, 81, 97} // Z
};
void setup() {
pinMode(latchPin1, OUTPUT); pinMode(clockPin1, OUTPUT); pinMode(dataPin1, OUTPUT);
pinMode(latchPin2, OUTPUT); pinMode(clockPin2, OUTPUT); pinMode(dataPin2, OUTPUT);
// 비트맵 클리어
for (int row = 0; row < 8; row++)
for (int zone = 0; zone <= maxZoneIndex; zone++)
bitmap[row][zone] = 0;
}
// 비트맵을 매트릭스에 표시
void RefreshDisplay() {
for (int row = 0; row < 8; row++) {
int rowbit = 1 << row;
digitalWrite(latchPin2, LOW);
shiftOut(dataPin2, clockPin2, MSBFIRST, rowbit);
digitalWrite(latchPin1, LOW);
for (int zone = maxZoneIndex; zone >= 0; zone--)
shiftOut(dataPin1, clockPin1, MSBFIRST, bitmap[row][zone]);
digitalWrite(latchPin1, HIGH);
digitalWrite(latchPin2, HIGH);
delayMicroseconds(300);
}
}
// 픽셀 on/off
void Plot(int col, int row, bool isOn) {
int zone = col / 8;
int colBitIndex = col % 8;
byte colBit = 1 << colBitIndex;
if (isOn) bitmap[row][zone] |= colBit;
else bitmap[row][zone] &= ~colBit;
}
// 메시지 문자별 컬럼 플롯, 표시, 좌시프트 스크롤
void XProcess() {
for (int charIndex = 0; charIndex < (sizeof(msg) - 1); charIndex++) {
int alphabetIndex = msg[charIndex] - '@';
if (alphabetIndex < 0) alphabetIndex = 0;
// 문자당 5컬럼 + 2컬럼 공백
for (int col = 0; col < 7; col++) {
for (int row = 0; row < 8; row++) {
bool isOn = 0;
if (col < 5) isOn = bitRead(alphabets[alphabetIndex][col], 7 - row) == 1;
Plot(numCols - 1, row, isOn); // 최우측 컬럼에 그리기, 아래 시프트 루프에서 왼쪽으로 스크롤
}
for (int refreshCount = 0; refreshCount < scrollspeed; refreshCount++)
RefreshDisplay();
// 비트맵 한 컬럼 좌시프트 (실제로는 우시프트지만 표시상 좌스크롤)
for (int row = 0; row < 8; row++) {
for (int zone = 0; zone < numZones; zone++) {
bitmap[row][zone] >>= 1;
if (zone < maxZoneIndex)
bitWrite(bitmap[row][zone], 7, bitRead(bitmap[row][zone + 1], 0));
}
}
}
}
}
void loop() { XProcess(); }