코코아팹은 누구나 창의적 아이디어를 현실로 만들어 낼 수 있도록
만들고, 공유하고, 배울 수 있는 터전이
되고자 합니다.
아이디와 비밀번호를 잊으셨나요?아이디 / 비밀번호 찾기
코코아팹 회원이 아니신가요? 회원가입
2014-12-04 10:35:56
연말 이맘때쯤 되면 많은 가게나 가정집에선 크리스마스 단장을 하게 되는데요.
이때 빠지지 않는 것이 크리스마스 트리인데 트리장식에 많이들 LED장식을 이용하죠. .
업데이트: 2015년도 크리스마스는 경기 때문인지 많이 썰렁한거 같아요. ^^;;; 집에서나마 간단히 만들어서 이런 썰렁한 분위기를 날려버리자? 음..ㅎㅎa"
LED다발을 돈주고도 살 수 있으나 조그만하게 나만의 개인용트리를 꾸미고 싶을때는
시중에서 파는 제품들은 대부분 커다란 트리를 타겟으로 만든 상품이라 크기가 거추장 스럽다.
2014년의 마지막 달을 맞아 ATtiny85를 이용해나만의 소형트리에 LED장식을 달아서 좀더 화려한 트리로 바꿔보자.
NO | 부품명 | 수량 | 상세설명 |
1 | 아두이노 | 1 | 오렌지 보드 |
2 | 브레드보드 | 1 | |
3 | ATtiny85 | 1 | |
4 | 점퍼 케이블 | 5~10 | 굵은선 |
5 | LED | 17 | 여러색으로 준비 |
부품명 | 아두이노 | 브레드보드 | ATtiny85 | 점퍼케이블 | LED |
부품 사진 |
LED장식의 경우에는 ATtiny85칩이 한정된 핀만을 가지고 있기 때문에 일반적인 방법으로는 10개가 넘는 LED를 제어하기가 불가능하다.
그렇게 때문에 찰리플렉싱이란 방법을 써서 여러 LED를 제어하였다.
찰리플렉싱을 인터넷에서 검색한다면 Maxim社에서 근무하는 Charlie Allen이라는 개발자가
최소의 입출력핀으로 많은양의 LED를 다루기위해 고안했다고 나와있다.
간단하게 결과만 얘기하면 찰리플렉싱이라는 방법을 쓰게 되면 n개의 핀수로 최대 n*(n-1)개의 핀을 제어가 가능하다.
여기서는 4개의 핀수로 4*3 = 12개의 LED를 제어하였다.
트리 위에 올라가는 별은 5개의 LED를 통해 만들었다.
같은 극끼리 모아서 앞 뒤로 납땜을 하여 입체감 있게 만들었다.
별에 들어가는 입출력핀은 ATtiny85에서 남는 핀에 꽂아주면 된다.
byte pins[] = {0,1,2,3}; //핀 번호 배열
const int NUMBER_OF_PINS = sizeof(pins)/ sizeof(pins[0]); //핀의 개수를 구한다. 4/1 = 4
const int NUMBER_OF_LEDS = NUMBER_OF_PINS * (NUMBER_OF_PINS-1); //LED의 개수를 찰리플렉싱으로 구한다. 4x3 = 12
byte pairs[NUMBER_OF_LEDS/2][2] = { {0,1}, {1,2}, {0,2},{0,3},{1,3},{2,3} }; //4개의 입출력핀이 짝을 이룰 수 있는 경우를 구한다.
void setup()
{
pinMode(4,OUTPUT); //별을 연결하는 핀모드 설정
}
void loop()
{
digitalWrite(4,HIGH); //별을 이루는 LED ON
// LED 12개를 100ms마다 차례대로 깜빡이게 한다.
for(int k = 0; k < 10; k++)
for(int i=0; i < NUMBER_OF_LEDS; i++)
{
lightLed(i); // light each LED in turn
delay(100);
}
// 0,2,4,6,8,10번의 LED와 1,3,5,7,9,11번 LED를 교대로 깜박이게 한다.
for(int k = 0; k < 5; k++)
{
for(int i=0; i < 50; i++)
{
lightLed(0);
delay(2);
lightLed(2);
delay(2);
lightLed(4);
delay(2);
lightLed(6);
delay(2);
lightLed(8);
delay(2);
lightLed(10);
delay(2);
}
for(int i=0; i < 50; i++)
{
lightLed(1);
delay(2);
lightLed(3);
delay(2);
lightLed(5);
delay(2);
lightLed(7);
delay(2);
lightLed(9);
delay(2);
lightLed(11);
delay(2);
}
}
}
// 매개변수에 해당되는 led를 켜는 함수
void lightLed(int led)
{
// 주어진 LED번호에 연관된 pins 배열상의 인덱스 indexA와 indexB를 얻는다.
int indexA = pairs[led/2][0];
int indexB = pairs[led/2][1];
// pins 배열에서 핀번호 값을 얻는다.
int pinA = pins[indexA];
int pinB = pins[indexB];
// pinA와 pinB가 아닌 핀은 Off상태로 만든다.
for(int i=0; i < NUMBER_OF_PINS; i++)
if( pins[i] != pinA && pins[i] != pinB)
{ // if this pin is not one of our pins
pinMode(pins[i], INPUT); // INPUT 상태로
digitalWrite(pins[i], LOW); // make sure pull-up is off
}
//pinA와 pinB를 On상태로 만든다.
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
if( led % 2 == 0)
{
digitalWrite(pinA,LOW);
digitalWrite(pinB,HIGH);
}
else
{
digitalWrite(pinB,LOW);
digitalWrite(pinA,HIGH);
}
}
위 소스의 기본 소스
위의 링크를 타고 가면 위 소스의 기본 소스를 가지고 있는 블로그로 이동하게 된다. 여기서 참고하여 핀을 3개에서 4개로 늘렸다.
소스는 길지만 사실상 주된 내용은 LED를 차례대로 깜빡이는 명령어를 몇차례 실시한뒤 정해진 LED그룹끼리 몇번 깜빡이는 것이 전부이다.
실질적으로도 loop()안에는 for문을 통해 여러번 LED를 켜고 끄고 반복하는 과정만 들어있으며
나머지 부분은 LED를 쉽게 켜고 끄고 하기 위한 과정으로 생각하면 된다.
찰리 플렉싱의 원리를 간단히 설명하면 밑에 보면 4개의 선이 있다.
1번핀에 HIGH값을 주고 2번핀에 LOW값을 주게 되면 이 값에 영향을 받는 LED는 A하나 뿐이다. 따라서 이 때는 A만 On이 되게 된다.
반대로 1번핀에 LOW값을 주고 2번핀에 HIGH값을 주게 되면 B만 영향을 받게 되어 B만 On상태로 변하게 된다.
만약 2번핀에 HIGH값을 주고 4번핀에 LOW값을 주게 되면 2번과 4번핀에 연결된 I와 J가 영향을 받게 된다. 하지만 2번핀이 HIGH이기 때문에 I만 불이 들어오게 된다.
결국 찰리플렉싱으로 조합이 가능한 수는 선의 개수에서 2개를 뽑아내는 조합과 같다.
하지만 한번에 조합에서 A와 B처럼 방향을 뒤바꿔서 할 수 있기 때문에 순열이 되어 4P2 = 4x3 = 12개가 된다.
이렇게 될 경우 한번에 하나의 불만 키는것밖에 되지 않을거라고 생각하는 분이 계실텐데,
이런 실행을 빠르게 한다면 눈에서는 인지 불가능한 딜레이로 불이 연속적으로 켜지게 되어 우리눈에는 동시에 여러개의 불이 켜지는 것처럼 보이게 된다.
아래와 같은 소스의 경우에도 delay를 2ms로 지정하였는데 이렇게 되면 우리눈에서는 2ms를 인식할 수 없어 여러개의 LED가 동시에 불이 켜지는 것처럼 보이게 된다.
이런 착시를 이용한다면 여러개의 LED를 소수의 핀을 통해 마음껏 제어가 가능하다.
for(int i=0; i < 50; i++) { lightLed(0); delay(2); lightLed(2); delay(2); lightLed(4); delay(2); lightLed(6); delay(2); lightLed(8); delay(2); lightLed(10); delay(2); }
수박쨈