Arduino LED Matrix Spectrum Effect - Audio Spectrum Visualizer Project Part.1
Lucy Archive
Lucy 2023
2020. 8. 23. 00:45

아두이노 우노 : LED Matrix Spectrum Effect

필요해서 하는 것은 아니지만, LED 매트릭스로 오디오 스펙트럼과 같은 효과를 직접 만들어 보고 싶었습니다. 이번 포스트는 아두이노 오디오 스펙트럼 만들기를 위한 첫 번째 단계로

8x8 LED Matrix 에서 기본적인 스펙트럼 효과

를 만드는 코드를 소개합니다. 

오디오 스펙트럼 구현

Audio Spectrum Visualizer 를 만들기 위해 아래의 단계가 필요하다고 예상하고 진행하면서 포스트를 진행해 나갈 예정입니다. 최대한 가능한한 아두이노의 코드만으로 구현을 하려고 합니다. 직장과 육아로 언제 할 수 있을지 모르겠지만, 천천이라고 관련 포스트를 작성해서 올릴 예정입니다. 최종적으로는 RGB LED Matrix 로 구현해보고 싶지만, 진행 상황을 보고 결정해야 할 것 같습니다.

Audio Spectrum VisualizerAudio Spectrum Visualizer

구현 단계

  • 8x8 LED Matrix 에서 기본적인 Spectrum 효과 구현
  • 32x8 LED Matrix 로 확장 후 동작 테스트
  • 32x8 LED Matrix 에서 Spectrum 효과 구현 및 퍼포먼스 체크
  • 마이크 또는 오디오 입력 데이터 신호 수집
  • 오디오 신호 FFT 처리
  • 오디오 신호 FFT 처리 값을 32x8 LED Matrix 의 Spectrum 효과로 반영

예상 되는 문제점

  • Arduino Uno 보드에서 Arduino Code 로만 작성할 경우 구현 할 수 있는 한계
  • 직장 생활과 육아로 부족한 시간이 없음, 아기가 잘 때만 작업을 할 수 있어 오디오를 틀 수가 없음


Hardware

준비물

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

  • Arduino Uno x 1 EA
  • 8x8 LED Matrix x 1 EA
  • Resistor x 8EA
  • Bread Board x 1EA
  • Jumper WIres

회로도 및 연결

아두이노 8x8 LED Matrix 연결 회로도아두이노 8x8 LED Matrix 연결 회로도

회로도 참고사항은 아래와 같습니다.

  • Arduino Uno 와 LED Matrix 연결 핀은 모두 출력 포트로 설정
  • 저는 LED Matrix 출력 방법을 한 행(Row)씩 출력하는 방법을 사용하고 있어, Column 핀에 저항을 연결

예제1 : Spectrum Effect basic

예제1은 오디오가 FFT 처리되어 오디오의 각 주파수 대역별로 진폭 처리한 데이터가 있다고 가정하고, LED Matrix 에 스펙트럼 효과를 만드는 예제입니다. 스펙트럼의 높이 값은 Random() 함수를 사용하여 구현 하였습니다. 

코드

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
#define SCROLLTIME 100 // 새로운 스펙트럼이 반영되는 스피드
 
/* 8x8 LED Matrix Pin Mapping */
#define C1 9
#define C2 12
#define C3 7
#define C4 13
#define C5 A2
#define C6 6
#define C7 3
#define C8 A5
#define R1 2
#define R2 11
#define R3 10
#define R4 A4
#define R5 8
#define R6 A3
#define R7 4
#define R8 5
 
/* 8x8 LED Pin 출력 코드 작성을 간단하게 하기 위해 배열로 처리 */ 
int colPin[8= {C1, C2, C3, C4, C5, C6, C7, C8};
int rowPin[8= {R1, R2, R3, R4, R5, R6, R7, R8};
 
/* 8x8 LDM 출력 버퍼 */ 
byte displayData[8][8];
 
/* 새로운 스펙트럼이 반영되는 스피드 */ 
int scrollTime = SCROLLTIME;
 
void setup() {
    /* GPIO Init */
    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 로 초기화
    }
}
 
void loop() {
    unsigned long now = millis();
    static unsigned long pastTime;
    
    /* 새로운 스펙트럼이 반영 되는 시간에 호출 되는 함수*/
    if(now - pastTime >= scrollTime){
        pastTime = now;
        makeSpectrum();
    }
 
    /* 8x8 LDM 출력 버퍼의 데이터를 LDM으로 출력 */
    for(int i = 0 ; i < 8 ; i++)
    {
        for(int j = 0 ; j < 8 ; j++)
        {
            digitalWrite(colPin[j], displayData[i][j]); // Column 핀에 데이터 쓰기
        }
        digitalWrite(rowPin[i], LOW); // i LOW 켜기
        delayMicroseconds(100); // LED ON 시간 조정
        digitalWrite(rowPin[i], HIGH); // i LOW 끄기 -> 모든 LED 끄기
    }
}
 
/* 새로운 스펙트럼 데이터를 출력 버퍼에 저장 */
void makeSpectrum(){
    byte temp;
    for(int i = 0; i < 8 ; i++){
        temp = random(7);
        for(int j = 0; j < 8 ; j++){
            displayData[7-j][i] = 0;
            if(j <= temp) displayData[7-j][i] = 1;
        }
    }
}
cs

코드 설명

대부분의 코드는 하단에 링크한 8x8 LED Matrix 관련 포스트의 내용과 비슷하며, Spectrum 효과를 만들기 위해 66 Line 이후 스펙트럼 데이터를 만드는 함수를 작성하였습니다. 

  • 69 Line : temp 변수는 0 ~ 6 사이의 랜덤 값을 저장합니다.
  • 71 Line : 이전에 저장된 8x8 LED Matrix 출력버퍼인 displayData[] 배열의 값을 '0'으로 초기화 합니다.
  • 72 Line : 7-j 행의 에서 0~7열(Column) 중에 temp 값보다 낮는 열(Column)의 좌표 값이 1을 저장합니다.

실행 결과

Random 값으로 추출한 결과라서 정신없어 보이긴 하지만, 의도한 대로 LED Matrix 가 정상적으로 동작합니다.


예제2 : 스펙트럼 Max Hold 기능 추가

예제1의 스펙트럼에서 Max Hold 기능을 추가하였습니다. Max Hold는 일정 시간 동안 각 주파수 밴드의 최고 값을 저장하는 기능입니다. Max Hold 라는 명칭은 따로 없고, 제가 설명하기 위해 만들어낸 용어 입니다. 

코드

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
#define SCROLLTIME 100 // 새로운 스펙트럼이 반영되는 스피드
#define MAXHOLDTIME 3 // Maxhold 를 유지하는 간격
 
/* 8x8 LED Matrix Pin Mapping */
#define C1 9
#define C2 12
#define C3 7
#define C4 13
#define C5 A2
#define C6 6
#define C7 3
#define C8 A5
#define R1 2
#define R2 11
#define R3 10
#define R4 A4
#define R5 8
#define R6 A3
#define R7 4
#define R8 5
 
/* 8x8 LED Pin 출력 코드 작성을 간단하게 하기 위해 배열로 처리 */ 
int colPin[8= {C1, C2, C3, C4, C5, C6, C7, C8};
int rowPin[8= {R1, R2, R3, R4, R5, R6, R7, R8};
 
/* 8x8 LDM 출력 버퍼 */ 
byte displayData[8][8];
 
/* 새로운 스펙트럼이 반영되는 스피드 */ 
int scrollTime = SCROLLTIME;
int maxHoldTime = MAXHOLDTIME;
 
void setup() {
    /* GPIO Init */
    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 로 초기화
    }
}
 
void loop() {
    unsigned long now = millis();
    static unsigned long pastTime;
 
    /* 새로운 스펙트럼이 반영 되는 시간에 호출 되는 함수*/
    if(now - pastTime >= scrollTime){
        pastTime = now;
        makeSpectrum();
    }
 
    /* 8x8 LDM 출력 버퍼의 데이터를 LDM으로 출력 */
    for(int i = 0 ; i < 8 ; i++)
    {
        for(int j = 0 ; j < 8 ; j++)
        {
            digitalWrite(colPin[j], displayData[i][j]); // Column 핀에 데이터 쓰기
        }
        digitalWrite(rowPin[i], LOW); // i LOW 켜기
        delayMicroseconds(100);
        digitalWrite(rowPin[i], HIGH); // i LOW 끄기 -> 모든 LED 끄기
    }
}
 
/* 새로운 스펙트럼 데이터를 출력 버퍼에 저장 */
void makeSpectrum(){
    static int count;
    byte temp;
    static byte maxHold[8]; // 최대 값을 저장하기 위한 배열
 
    for(int i = 0; i < 8 ; i++){
        temp = random(7);
        if(maxHold[i] < temp) maxHold[i] = temp; // 최대 값을 저장
        for(int j = 0; j < 8 ; j++){
            displayData[7-j][i] = 0;
            if(j == maxHold[i]) displayData[7-j][i] = 1// 최대 갑과 같은 행의 데이터만 1로 설정
        }
    }
 
    count++;
    /* makeSpectrum 이 3번 실행 될떄마다 maxHold 의 값을 초기화 */ 
    if(count == maxHoldTime){
        count = 0;
        for(int i = 0;i < 8;i++) maxHold[i] = { 0, };
    }
}
cs

코드 설명

지난 코드에서 주요하게 추가되 내용은 68 Line 이하의 makerSpectrum() 함수 내부 입니다. 

  • 71 Line : 각 주파수 밴드의 최대 값을 저장할 배열을 선언
  • 75 Line : Random() 함수로 생성된 수의 최대 값을 저장
  • 77 Line : 8x8 LED Matrix 출력 버퍼 0으로 초기화
  • 78 Line : 8x8 LED Matrix 출력 버퍼의 각 열에서 최대값과 일치하는 행만 1로 초기화

실행 결과

위 코드를 실행하면 아래와 같이 최대 값만 LED 매트릭스에 출력됩니다.


마무리

본 포스트에서는 Audio Spectrum Visualizer Project 를 진행하기 위해 기본적인 8x8 LED Matirx 에서 Spectrum 효과 코드를 만들고, 소개를 하였습니다. 이 프로젝트를 완성하기 위해서

32x8 LED Matrix 사용법, Audio 신호 입력 방법, Audio 신호 FFT 처리

를 추가적으로 진행하면서 후속 포스트를 이어 나갈 예정입니다. 

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

관련포스트

👉 아두이노 프로젝트 Audio Spectrum Visualizer 관련글 목록 보기

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

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

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