프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

3x3x3 LED cube 만들기

2014-08-26 14:16:48

개요

개요

2차원적인 브레드 보드 표면에서만 LED를 표현하는것이 아닌 LED를 쌓아올려서 입체적인 3x3x3 LED cube를 만들어보자.
외국이나 국내 사이트에서 다양한 LED cube의 완성품을 볼 수 있으며 3x3x3에서부터 8x8x8까지 다양한 크기와 다양한 모양을 뽐내는 큐브를 볼 수 있다.



튜토리얼에서의 LED는 2차원적인 matrix공간에서 단순히 켜고 끄는 역할만 하였다면, 이번 프로젝트에서는 하나의 차원을 늘려서 입체적인 나만의 신호를 만들고 출력해 볼 수 있다.

만들때는 이게 뭐야 이럴 수 있겠지만 막상 만들고 나면 감탄사가 나오게 되는 매력이 있는 프로젝트라고 생각한다.
이번 프로젝트에서는 LED를 쌓아올리기 위해  납땜질이 필요하고 약간의 회로지식이 필요하다.




동영상



필요한 사전지식

LED

부품 목록

NO 부품명 수량 상세정보
1 아두이노 보드 1  
2 브레드 보드나 전자회로기판 1  
3 LED 27  
4 저항 3 330Ω
5 케이블 15~20  


부품명 아두이노 보드 브레드 보드or
전자회로기판
LED 저항 케이블
부품사진

하드웨어 making

브레드보드

3x3x3 LED 큐브를 만들기 위해서는 다음과 같은 프레임을 3개를 만들어 줘야한다. 
+극을 90도 접어서 다른 LED의  +극과 연결하여 준다.
-극은 아래로 내려서 다른 -극과 연결될 수 있도록 한다.
-극과 +극은 서로 닿지 않도록 주의해서 납땜질을 한다.


위와 같은 프레임을 3개 제작하였다면 -극을 브레드보드나 회로 기판에 꽂아서 아두이노와 연결한다.
아두이노의 -극을 디지털핀에 차례대로 9개를 꽂는다.


-극을 다 꽂았다면 이젠 +극을 연결할 차례이다. -극이 빌딩에서 각 방의 호실을 나타낸다면 +극은 빌딩의 층을 나타낸다. 
정면에서 봤을때 +극은 같은 층의 +극과 납땜을 통해 연결하여 준다.
 
각층의 연결은 저항과 같이 아래와 연결해 준다. 
Layer1은 1층을 연결한 +극을 나타내고 Layer2는 2층을 연결한 +극이고 Layer3는 3층을 연결한 +극이다.
위 브레드보드와 아래 브레드보드의 연결을 모두마치면 +극과 -극의 연결이 모두 끝난다.



전자 회로도

소프트웨어 coding


int layer1 = A0;
int layer2 = A1;
int layer3 = A2;
int D2 = 2;
int D3 = 3;
int D4 = 4;
int D5 = 5;
int D6 = 6;
int D7 = 7;
int D8 = 8;
int D9 = 9;
int D10 = 10;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(D2, OUTPUT); pinMode(D3, OUTPUT); pinMode(D4, OUTPUT);
  pinMode(D5, OUTPUT); pinMode(D6, OUTPUT); pinMode(D7, OUTPUT);
  pinMode(D8, OUTPUT); pinMode(D9, OUTPUT); pinMode(D10, OUTPUT);  
  pinMode(layer1, OUTPUT); pinMode(layer2, OUTPUT); pinMode(layer3, OUTPUT);   
}

// the loop routine runs over and over again forever:
void loop() {
  
  digitalWrite(layer1, HIGH); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, HIGH); digitalWrite(layer3, LOW); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, HIGH); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  delay(500);
  
  //east
  digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
  digitalWrite(D2, LOW); digitalWrite(D3, LOW); digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, LOW); digitalWrite(D6, LOW); digitalWrite(D7, LOW);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, LOW); digitalWrite(D9, LOW); digitalWrite(D10, LOW);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  delay(500);
  
  //west
  digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, LOW); digitalWrite(D9, LOW); digitalWrite(D10, LOW);
  delay(500);
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, LOW); digitalWrite(D6, LOW); digitalWrite(D7, LOW);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, LOW); digitalWrite(D3, LOW); digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  delay(500);
  
  //south
  digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
  digitalWrite(D2, LOW); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, LOW); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, LOW); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, HIGH); digitalWrite(D3, LOW); digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH); digitalWrite(D6, LOW); digitalWrite(D7, HIGH);
  digitalWrite(D8, HIGH); digitalWrite(D9, LOW); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, LOW);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, LOW);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  delay(500);  
  
  //north
  digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
  digitalWrite(D2, HIGH); digitalWrite(D3, HIGH); digitalWrite(D4, LOW);
  digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, LOW);
  digitalWrite(D8, HIGH); digitalWrite(D9, HIGH); digitalWrite(D10, LOW);  
  delay(500); 
  digitalWrite(D2, HIGH); digitalWrite(D3, LOW); digitalWrite(D4, HIGH);
  digitalWrite(D5, HIGH); digitalWrite(D6, LOW); digitalWrite(D7, HIGH);
  digitalWrite(D8, HIGH); digitalWrite(D9, LOW); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(D2, LOW); digitalWrite(D3, HIGH); digitalWrite(D4, HIGH);
  digitalWrite(D5, LOW); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
  digitalWrite(D8, LOW); digitalWrite(D9, HIGH); digitalWrite(D10, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  delay(500);  
  
  for(int i=0; i<2; i++) {
    digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
    digitalWrite(D2, HIGH); digitalWrite(D3, LOW); digitalWrite(D4, HIGH);
    digitalWrite(D5, LOW); digitalWrite(D6, LOW); digitalWrite(D7, LOW);
    digitalWrite(D8, HIGH); digitalWrite(D9, LOW); digitalWrite(D10, HIGH);
    delay(500);  
    digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH);  
    digitalWrite(D2, LOW); digitalWrite(D3, HIGH); digitalWrite(D4, LOW);
    digitalWrite(D5, HIGH); digitalWrite(D6, HIGH); digitalWrite(D7, HIGH);
    digitalWrite(D8, LOW); digitalWrite(D9, HIGH); digitalWrite(D10, LOW);
    delay(500);  
  }
  
  //all ON OFF
  for(int i=0; i<2; i++) {
    digitalWrite(layer1, HIGH); digitalWrite(layer2, HIGH); digitalWrite(layer3, HIGH); 
    digitalWrite(D2, LOW); digitalWrite(D3, LOW); digitalWrite(D4, LOW);
    digitalWrite(D5, LOW); digitalWrite(D6, LOW); digitalWrite(D7, LOW);
    digitalWrite(D8, LOW); digitalWrite(D9, LOW); digitalWrite(D10, LOW);
    delay(500);  
    digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
    delay(500);  
  }
}
위의 소스는 동영상에서 재생한 큐브의 소스이다. 
코드가 길어 보이지만 하드웨어적인 연결수준에 비해 정말 간단하게 이루어져 있고 정렬되어 비슷한 문구가 계속적으로 반복되는 쉬운 소스이다.
소스의 대부분이 digitalWrite()으로 이루어져 있다. 여러개를 묶어놨을때는 특정한 모양을 나타내며 깜빡거리지만 하나하나 떨어뜨려 봤을 경우에는 단순한 LED의 깜빡임이기 때문에 digitalWrite()만으로도 가능하다. 

digitalWrite()에서 Layer1, Layer2, Layer3은 +핀을 나타내고, 나머지 D2부터 D10까지는 -핀의 번호를 나타낸다. 
이 소스에서는 +핀은 HIGH값을 줄때 LED를 켜게 하고 -핀은 LOW을 줄때 LED를 켜게 한다.

  digitalWrite(layer1, HIGH); digitalWrite(layer2, LOW); digitalWrite(layer3, LOW); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, HIGH); digitalWrite(layer3, LOW); 
  digitalWrite(D6, HIGH);
  delay(500);
  digitalWrite(layer1, LOW); digitalWrite(layer2, LOW); digitalWrite(layer3, HIGH); 
  digitalWrite(D6, HIGH);
  delay(500);
위의 소스를 보면 처음에는 layer1만 HIGH값을 주었고, 두 번째에는 layer2에 HIGH값을 주고 세 번째에는 layer3에 HIGH값을 주었다.
결과만을 보게 되면 1층에 불이 들어오고 500ms 후에 2층에 불이 들어오고 또 500ms 후에 3층에 불이 들어오게 된다.
다만 layer는 층에 불이 들어올 수 있게 전류를 공급하는 역할만 하게 되고 그 전류를 가지고 LED를 켤 것인지 안 켤 것인지에 대한 결정은 -극의 핀에서 결정하게 된다. 
위 소스에서는 D6에 HIGH값을 주어 D6을 제외한 나머지 LED에는 불이 들어올 수 있게 하였다. 

3x3x3 LED 큐브를 꾸미는데에는 답이 존재하지 않는다. 그렇기 때문에 자신이 직접 해보고 원하는 방향으로 코딩하는것이 옳은 방향이라 생각한다.
단순히 Delay때마다 각 층마다 불만 켰다 껏다 해줘도 자신만의 프로젝트가 되기 때문에 스스로가 직접 꾸며보자.
코딩 난이도 또한 초급수준이기 때문에 방법을 익힌다면 30분안으로 큐브를 이쁘게 꾸밀 수 있을 것이다.

기술문서

  • 부품목록
  • 회로도
  • 브레드보드 레이아웃
  • 스케치

수박쨈

아두이노, LED
profile

나두이노 2014-11-22 21:35:31

저도 만들어 봤는데, 코딩이 관건이죠.
어떻게 하느냐에따라 휘황찬란하게 빛나는데 코딩을 깔끔하게 하기가 힘드네요

profile

수박쨈 2014-11-24 13:41:48

사실 기판에 납땜을 통해 깔끔하게 하는것이 정석이지만 여기서는 최대한 납땜을 피하기위해 브레드보드에 억지로 꽂아서 만들었다는 느낌이 들죠...........ㅜ
3x3x3정도는 쉬프트레지스터 없이 가능하지만 커질수록 쉬프트레지스터를 사용하여 코딩을 해야하고
코딩을 통해 패턴을 만드는 경우는 저처럼 노가다식으로 만들지 않더라도 
다양한 방법으로 깔끔하게 코딩하는 경우도 많이 봤습니다.
역시나 LEDcube는 독창적인 패턴이 키포인트인듯 합니다!_!

profile

김선호 2015-03-30 23:38:53

그런데 이렇게 회로를 만들면

1 0 0
0 0 0
0 0 0
-------------
0 1 0
0 0 0
0 0 0

이렇게 LED를 켤수 없지 않나요?

profile

김수현 2016-01-28 01:23:26

와 예쁘네요~

profile

임명기 2016-09-28 19:09:34

멋져요..잘봤습니다

profile

윤동빈 2016-11-01 18:51:58

좋은 프로젝트네요ㅎ

profile

장초반 2019-04-02 00:47:11

안녕하세요 왜 +핀은 HIGH값을 줄때 LED를 켜게 하고 -핀은 LOW을 줄때 LED를 켜게 하는지 궁금합니다. ( 하익값을 주면 커지고 로우값을 주면 꺼지는게 아닌가요?)