DUAL LED VU미터 타워 Rev.1 제작기

참치(TUNA) 7 Comments 2016-06-04 13:22

RESIZE_IMG_9572.JPG

 

LED Dual Volume Unit Meter Tower Rev.1 @ 2015.11

 

 

작년 11월에 만든 LED VU 미터 타워가 오랫동안 소식 무감각였는데.. 시간 있을 때 잠깐 제작기를 포스팅한다 !

우선 VU미터가 뭐하는거냐면.. 소리크기를 측정한것을 다음 사진과 같이 (게이)바 LED 따위로 표현해주는것인데..

 

RESIZE_P7070335.JPG.2560x2560_q85.jpg

 

위 쪼매난 VU미터를 크고 아름답게 만든것이 아래 사진속에서 소리에 따라 찰지게 요동치는 LED (게이)바가 되시겠다 !

 

anigif.gif

 

 

 

 

 

준비물

*VU미터가 스트레오이므로 총 2대 제작.

 

 

0. 예산

 

10만언 정도 잡으면 충분. 예산이 없다구요?! 딱랩&캐시를 사용하세요! 연 이자 444페센트 !

 

 

 

 

 

1. 회로도

 

0949.PNG

[ 사진 클릭하면 크게 볼 수 있을지도.. ]

 

그리느라 귀찮아 죽는줄 알았네

 

D1은 문턱전압이 높은 일반 정류 다이오드 사용하면 안 되고 1N5819와 같은 쇼트키 다이오드를 사용해야 하고, 일반 정류 다이오드 사용해도 무방하나, 작은 음량은 측정 안될지도...

 

회로도 우측면 가운데에 이상하게 붙여 넣은 회로도가 있는데, ATmega328에서 나온 LED 관련 포트를 R2 저항을 거쳐 TR에 연결,
TR 컬렉터에 연결된 R1 저항을 LED (-) 극에 연결하고 나머지 극성은 (+)에 연결하면 해결.

 

R1은 사용하는 LED의 VF에 따라 상이하므로 필히 데이터시트 확인 후 저항값 선정하시기 바람.. 전압은 MCU VCC 전압 5VDC에 맞추면 된다.

LED 저항 계산기 좌표 필요하신 분을 위해 http://ledcalc.com/ 또는 http://www.hebeiltd.com.cn/?p=zz.led.resistor.calculator 

 

 

아두이노 사용하시는 분은 오디오 입력 측과 LED 드라이빙 회로 쪽만 만들어서 쓰시면 된다 !

 

더이상의자세한설명은생략한다.jpg

 

 


 

 

2. 아크릴 판재


이건 만드는 사람에 따라 크기가 상이할 수 있는데.. 일단 너무 크면 LED 빛이 이상하게 퍼져서 한 곳에 편중되고 너무 작으면 눈이 좀 아프다..
따라서 빛이 한 곳에 편중되지 않고 첫 번째 사진처럼 매우 멋있게 빛난다.. 필자 같은 경우 아래와 같은 수치를 사용했다..

 

2-1. 기판 고정시킬 아크릴 판재 110mm x 80mm x 5T * 4개
2-2. 실제 LED 바가 될 아크릴 판재 90mm x 60mm x 10T * 26개 (여분 2개)

 

이건 우리의 위대한 머신 마트 커스텀 아크릴을 사용하면 된다. 다른 곳보다 약간 비쌀 수 있는데, 확실히 내구성이 강해서 드릴질 할 때 잘 안 깨진다 카더라

좌표 http://www.devicemart.co.kr/35452 

 

아 참고로 기판을 고정시킬 아크릴 판재는 본인이 만들 보드 크기에 따라 결정하시면 된다.
크기에 대해 감이 잘 안 잡힌다면 일단 종이 위해 실제 크기를 그리고 몇 개 오려서 배치해보자.. 고라면 전 보다 감이 훨씬 잘 잡힐 것이다..

 

 

 

 

 

3. 마이컴

 

아두이노 사용자 배려를 위해 아두이노 우노에 사용된 칩과 동일한 ATmega328P-PU를 사용한다. 

따라서 Microchip 社에 보기좋게 잡아먹힌 Atmel 社의 AVR Studio에서 작성한 AVR 코드가 Arduino IDE 하고 호환된다.

 

1448086733190.jpg

 

 

 

 

 

 

4. LED

 

RESIZE_IMG_9471.JPG

 

위 사진처럼 이쁘게 빛이 내려면 일반 LED는 빛이 약해서 안되고.. 고휘도 LED를 써야 이쁘고 멋지게 빛이 나므로 반드시 고휘도 LED를 사용하자

 

필자가 사용한 고휘도 LED 좌표

 

블루: http://www.ic114.com/AJAXWWW/SITE/sc/00V0.aspx?ID_P=P0082816

그린: http://www.ic114.com/AJAXWWW/SITE/sc/00V0.aspx?ID_P=P0083225

레드: http://www.ic114.com/AJAXWWW/SITE/sc/00V0.aspx?ID_P=P0046208

 

아크릴 바 하나에 LED 두 개가 딱 적절하다 카더라

 

 

 

 

 

5. 지지대

 

사람으로 치면 척추가 되는 부분인데, 너무 얇으면 아크릴 무게 때문에 홀라당 자빠질 수 있으니.. 7 ~ 10파이 정도가 적당.

자세한 사항은 후술.

 

 

 

 

 

 

제작

 

 

RESIZE_IMG_9423.JPG

 

우리의 위대한 머신마트에 주문한 아크릴이 도착하고..

앞서 언급한 것처럼 기판 고정용 110mm x 80mm x 5T 4개에.. LED 바 90mm x 60mm x 10T 26개(여분 2개)

 

 

 

 

RESIZE_IMG_9427.JPG

 

RESIZE_IMG_9428.JPG

 

아크릴에 구멍 뚫을 위치를 지정해주고 흥겹게 구멍을 뚫어준다.. 

뚫을 때 우선 작은 구멍 뚫어놓고 점점 늘려가는 것이 좋은데, 그런건 귀찮으니 처음부터 큰 구멍으로 뚫어도 안 깨지고 잘 뚫린다 카더라

 

 

 

 

 

 

 

RESIZE_IMG_9440.JPG

 

LED 가 들어갈 자리는 지지대 박을 큰 구멍 두 개 사이에 적절히 뚫으면 된다.

 

 

 

 

 

 

 

RESIZE_IMG_9444.JPG

 

아크릴 LED 바는 총 13개에 20mm 간격으로 배치되고, 기판 지지대까지 합쳐서 LED VU 미터 타워 총 높이가 450mm 정도 된다.

그럼 LED VU미터의 척추는 440 ~ 450mm 정도로 맞추면 해결.

 

 

 

 

 

 

 

 

RESIZE_IMG_9446.JPG

 

이건 딱히 요령이나 팁은 없고... ㅋ 그냥 열심히 넣고 돌리면 된다..

 

 

 

 

RESIZE_IMG_9460.JPG

 

RESIZE_IMG_9475.JPG

 

LED는 구멍에 잘 넣고 글루건이나 투명 실리콘으로 고정시킨 뒤 LED (+)는 공통으로 땜하고 (-)는 나중에 선을 연결할 수 있도록 적절한 길이로 잘라놓자.

 

 

 

 

 

 

RESIZE_IMG_9480.JPG

 

LED 불이 잘들 들어오는지 확인.. (+) 극 공통이므로 (+) 극에 집게 전선 물려놓고 (-) 극에 대보기만 하면 된다.

 

 

 

 

 

 

RESIZE_IMG_9488.JPG

 

RESIZE_IMG_9518.JPG

 

RESIZE_IMG_9522.JPG

 

기판은 이런씩으로 고정했고..

여기서.. 기판 아크릴 판 고정하기 전에 커넥터 먼저 연결해놓고 하는 것이 정신건강에 좋다.. 고정시켜놓은 상태에서 커넥터 꽂으려니 멘탈이..

 

 

 

 

 

RESIZE_IMG_9529.JPG

 

RESIZE_IMG_9500.JPG

 

기판에서 나온 선들을 각 LED에 연결해주고 케이블 타이로 정리해주면 깔끔.

 

 

 

 

 

 

 

 

Firmware 작성

 

우리의 위대한 MIT (지잡대) 라이센스를 적용했다 ! 그 빌어먹을 GNU GPL 라이센스는 질색이더라 !

출처만 잘 남겨주시면 감사감사...

 

/* The MIT License (MIT)
 * 
 * Copyright (c) 2016 TUNA (tuna@hv-l.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */

#define F_CPU 16000000UL


#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>


#define SAMPLING_NUM    100
#define SENSITIVITY     10

int ledLevelNow = 0;
int ledLevelOld = 0;

uint32_t ledLevelCount = 0;


uint8_t barLed[14][2] = {
    /* PORTB, PORTD */
    /* Port No. 10, 9, 19, 18, 17, 16, 15, 14, 13, 12, 11, 6, 5, 4, 3, 2 */
    { 0b00000000, 0b00000000 }, // 0
    { 0b00000010, 0b00000000 }, // 1
    { 0b00000010, 0b01000000 }, // 2
    { 0b00000110, 0b01000000 }, // 3
    { 0b00000110, 0b01100000 }, // 4
    { 0b00001110, 0b01100000 }, // 5
    { 0b00101110, 0b01100000 }, // 6
    { 0b00111110, 0b01100000 }, // 7
    { 0b00111110, 0b01110000 }, // 8
    { 0b00111111, 0b01110000 }, // 9
    { 0b00111111, 0b01111000 }, // 10
    { 0b00111111, 0b11111000 }, // 11
    { 0b00111111, 0b11111100 }, // 12
    { 0b00111111, 0b11111110 }  // 13
};



uint8_t dotLed[14][2] = {
    /* PORTB, PORTD */
    { 0b00000000, 0b00000000 }, // 0
    { 0b00000010, 0b00000000 }, // 1
    { 0b00000000, 0b01000000 }, // 2
    { 0b00000100, 0b00000000 }, // 3
    { 0b00000000, 0b00100000 }, // 4
    { 0b00001000, 0b00000000 }, // 5
    { 0b00100000, 0b00000000 }, // 6
    { 0b00010000, 0b00000000 }, // 7
    { 0b00000000, 0b00010000 }, // 8
    { 0b00000001, 0b00000000 }, // 9
    { 0b00000000, 0b00001000 }, // 10
    { 0b00000000, 0b10000000 }, // 11
    { 0b00000000, 0b00000100 }, // 12
    { 0b00000000, 0b00000010 }  // 13
};


void initGPIO()
{
    PORTB = 0x00;
    PORTD = 0x00;
    DDRB = 0xFF;
    DDRD = 0xFF;
}

void initAdc()
{
    ADMUX |= (1<<REFS0);
    ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADEN);
}

uint16_t readAdc(uint8_t adcChannel)
{
    ADMUX = (ADMUX & 0xF0) | (adcChannel & 0x0F);
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));

    return ADC;
}


int main()
{
    initGPIO();
    initAdc();

    while (true)
    {
        for (int i = 0; i < SAMPLING_NUM; i++) ledLevelCount += readAdc(5);

        ledLevelCount /= SAMPLING_NUM;
        ledLevelNow = ledLevelCount / SENSITIVITY;

        if (ledLevelNow > 13) ledLevelNow = 13;
        if (ledLevelOld < ledLevelNow) _delay_ms(10);
        
        PORTB = barLed[ledLevelNow][0];
        PORTD = barLed[ledLevelNow][1];

        ledLevelOld = ledLevelNow;
    }
}

 

 

 

 

 

/* The MIT License (MIT)
 * 
 * Copyright (c) 2016 TUNA (tuna@hv-l.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */

#define F_CPU 16000000UL


#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>


#define SAMPLING_NUM    100
#define SENSITIVITY     10

int ledLevelNow = 0;
int ledLevelOld = 0;

uint32_t ledLevelCount = 0;


uint8_t barLed[14][2] = {
    /* PORTB, PORTD */
    /* Port No. 10, 9, 19, 18, 17, 16, 15, 14, 13, 12, 11, 6, 5, 4, 3, 2 */
    { 0b00000000, 0b00000000 }, // 0
    { 0b00000010, 0b00000000 }, // 1
    { 0b00000010, 0b01000000 }, // 2
    { 0b00000110, 0b01000000 }, // 3
    { 0b00000110, 0b01100000 }, // 4
    { 0b00001110, 0b01100000 }, // 5
    { 0b00101110, 0b01100000 }, // 6
    { 0b00111110, 0b01100000 }, // 7
    { 0b00111110, 0b01110000 }, // 8
    { 0b00111111, 0b01110000 }, // 9
    { 0b00111111, 0b01111000 }, // 10
    { 0b00111111, 0b11111000 }, // 11
    { 0b00111111, 0b11111100 }, // 12
    { 0b00111111, 0b11111110 }  // 13
};



uint8_t dotLed[14][2] = {
    /* PORTB, PORTD */
    { 0b00000000, 0b00000000 }, // 0
    { 0b00000010, 0b00000000 }, // 1
    { 0b00000000, 0b01000000 }, // 2
    { 0b00000100, 0b00000000 }, // 3
    { 0b00000000, 0b00100000 }, // 4
    { 0b00001000, 0b00000000 }, // 5
    { 0b00100000, 0b00000000 }, // 6
    { 0b00010000, 0b00000000 }, // 7
    { 0b00000000, 0b00010000 }, // 8
    { 0b00000001, 0b00000000 }, // 9
    { 0b00000000, 0b00001000 }, // 10
    { 0b00000000, 0b10000000 }, // 11
    { 0b00000000, 0b00000100 }, // 12
    { 0b00000000, 0b00000010 }  // 13
};


void initGPIO()
{
    PORTB = 0x00;
    PORTD = 0x00;
    DDRB = 0xFF;
    DDRD = 0xFF;
}

void initAdc()
{
    ADMUX |= (1<<REFS0);
    ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADEN);
}

uint16_t readAdc(uint8_t adcChannel)
{
    ADMUX = (ADMUX & 0xF0) | (adcChannel & 0x0F);
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));

    return ADC;
}


void setup()
{

}

void loop()
{
    initGPIO();
    initAdc();

    while (true)
    {
        for (int i = 0; i < SAMPLING_NUM; i++) ledLevelCount += readAdc(5);

        ledLevelCount /= SAMPLING_NUM;
        ledLevelNow = ledLevelCount / SENSITIVITY;

        if (ledLevelNow > 13) ledLevelNow = 13;
        if (ledLevelOld < ledLevelNow) _delay_ms(10);
        
        PORTB = barLed[ledLevelNow][0];
        PORTD = barLed[ledLevelNow][1];

        ledLevelOld = ledLevelNow;
    }
}

 

 

 

 

 

C언어가 가능하단 가정하게 간단히 코드를 설명드리면,

 

 

for (int i = 0; i < SAMPLING_NUM; i++) ledLevelCount += readAdc(5);

ledLevelCount /= SAMPLING_NUM;
ledLevelNow = ledLevelCount / 10;

 

113 ~ 115줄에서 ADC 샘플링 횟수만큼 평균치내어 신명나게 춤추는 우리의 노래파형을 안정화시키고

 

116줄은 앞서 평균치된 값을 LED를 몇 Level 정도 Display 할것인지 결정하는 부분인데, 

SENSITIVITY가 낮을수록 Level 반응이 커지는데, 그만큼 정확도가 높아질수도, 작아질수도 있으므로 적당히 조절하는것이 중요.

 

 

if (ledLevelNow > 13) ledLevelNow = 13;
if (ledLevelOld < ledLevelNow) _delay_ms(10);

PORTB = barLed[ledLevelNow][0];
PORTD = barLed[ledLevelNow][1];

 

118줄은 앞서 연산된 값이 Overflow됬을때 바로 잡아주고,

119줄은 이전 Sound Level 이 현재 Sound Level 보다 작으면 Delay를 줘서 자연스러운 LED Level을 연출 할 수 있게하였다.. (희망사항)

121 ~ 122줄은 앞서 연산되고, 필터링된 정수 데이터 0 ~ 13 값을 가지고 LED 점등을 제어한다.

 

 

42줄은 Sound Level에 따른 LED 점등 Level을 배열로 만들어두었다.

 

uint8_t barLed[14][2] = {
    /* PORTB, PORTD */
    /* Port No. 10, 9, 19, 18, 17, 16, 15, 14, 13, 12, 11, 6, 5, 4, 3, 2 */
    { 0b00000000, 0b00000000 }, // 0
    { 0b00000010, 0b00000000 }, // 1
    { 0b00000010, 0b01000000 }, // 2
    { 0b00000110, 0b01000000 }, // 3
    { 0b00000110, 0b01100000 }, // 4
    { 0b00001110, 0b01100000 }, // 5
    { 0b00101110, 0b01100000 }, // 6
    { 0b00111110, 0b01100000 }, // 7
    { 0b00111110, 0b01110000 }, // 8
    { 0b00111111, 0b01110000 }, // 9
    { 0b00111111, 0b01111000 }, // 10
    { 0b00111111, 0b11111000 }, // 11
    { 0b00111111, 0b11111100 }, // 12
    { 0b00111111, 0b11111110 }  // 13
};

 

0b00... 로 시작하는 bit에서 0b를 빼고보면 00000000, 00000000와 매칭되어 있다. 즉 순서대로 Port No. 와 매칭되어 있다.

즉 10000000, 01000000 가 되면 10번포트는 ON되고, 9 ~ 14번포트는 OFF, 13번 포트 OFF, 11번 포트 ON, 나머지 6 ~ 2포트는 OFF 이런씩이다.

 

LED는 밑에서 위로 켜지게 프로그램밍 되어 있으므로 Sound Level이 2이면 15, 12번에 연결된 LED 1, 2가 점등할것이고,

Sound Level이 3이면 16, 15, 12연결된 LED 3, 1, 2이 점등하는씩으로 동작.

 

그러니까, LED가 연결된 포트와 매칭시키면 되는일.. 어때요, 참쉽죠?

 

 

 

 

작동영상

 

 

일전에 TEST포스트로 투척한 영상.. 노래에 맞춰 신명나게 춤추는 Dual LED VU미터 타워이다 !

어디.. 고전압 손땐지 꽤 오래됬는데.. 나중에 음악에 맞춰 동작하는 테슬라코일 옆에 VU미터 타워 세워놓고 돌릴 생각도...

 

 

차후 버전은 LED 색깔 좀 변하게 만들어봐야겠다.. 그게 언제될지는 모르겠지만... ㅋ

아무튼 LED VU미터 타워 Rev.1 제작기 포스팅은 여기서 마무리..

 


Lab / Electronics