November 5, 2024

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[39호]4x4x4 RGB LED CUBE Tetris

2016 ictmain

2016 ICT 융합 프로젝트 공모전 참가상

4x4x4 RGB LED CUBE Tetris

글 | 동서대학교 이성빈, 김지환, 서성욱, 권병욱

 

심사평
뉴티씨 매우 재미있는 작품으로 생각되며, 만드는 동안도 재미있게 작업했을 것 같다. 학습하는데 이만한 작품도 많이 없을 것으로 생각되며, 실용적이지는 않지만, 작품의 완성도는 만점을 주었다. 보고서도 잘 작성하였지만, 좀 더 내용을 자세히 적을 수 있었다면 좋았을 것으로 보인다.
칩센 유튜브 등에서 많이 나오는 주제다. 심지어 음악에 맞춰 visualize 되는 작품도 본적이 있어 자연스럽게 비교가 된다.
위드로봇 3차원 LED 큐브를 게임과 접목한 작품입니다. 전체적으로 동작하는 시스템을 구현한 부분을 높이 평가하며, 테트리스보다 직관적인 게임이나 활용처를 찾는다면 좀 더 나은 작품이 될 것 같습니다.

작품 개요
3D LED 큐브란 수많은 LED를 3차원으로 배열 하여 소프트웨어로 각 LED의 켜짐과 꺼짐을 제어함으로써 3차원 디스플레이가 되게 하는 기술이다.
최근, 각종 디지털 관련 전시회에서 작품으로 나타나며 인터넷상에도 제작법이 여러 사이트에 공개되어 많은 사람들이 변형된 작품을 제안하고 있다. 당장 유투브, 구글에 검색해 보아도 많은 작품들이 검색되어 나온다. 이 작품들은 대게 LED 큐브 작동을 베이스로 하여 개개인의 패턴을 중점으로 하여 많은 사람들의 이목을 집중 시키는데 목표로 한다.

3x3x3, 4x4x4, 8x8x8, 16x16x16 등 여러가지 모양으로 제작되는데 이 큐브들의 공통점으로는 제작자가 입력한 방식으로만 움직인다는 공통점이 있었다. 대게 패턴을 보여주는데 이 패턴을 작동하는 방식으로 립모션, 프로세싱 등을 이용하여 사용자 인터렉션에 따라 조금씩 움직임이 변화를 줄 수 있지만 실질적으로는 제작자를 제외하고 직접 조작하는데 어려움이 있다고 보고 있다.
그리하여 본 프로젝트에서는 누구나 직접 큐브를 조작할 수 있으며 사용자 인터렉션을 극대화시키는 방안을 생각하던 중 사용자가 가장 다가가기 쉬우며 흥미롭게 조작하는 방식으로 게임을 접목시켜 보기로 하였다.
3D 게임을 접목시키기로 한 후 마땅한 게임을 찾는 도중 가장 대중적으로 알고 있으며 남녀노소 누구나 해보았던 테트리스를 큐브에 맞게 재해석하여 접목시키기로 하였다.

작품 설명
주요 동작 및 특징
본 프로젝트에서는 BARE CONDUCTIVE TOUCH BOARD라는 전도성 터치보드를 이용하여 컨트롤판을 커스텀화 제작한다.
제작된 컨트롤판을 터치하게 되면 개별적인 고유 값이 Processing으로 전달이 되며 큐브에 정보를 전송하게 해준다.
각 이벤트 처리는 아두이노에서 자체적으로 하며 Proceesing에서는 큐브를 컨트롤하는 아두이노와 사용자 컨트롤판을 제어하는 역할을 수행 하며 여러 가지 사운드를 제공한다.
본 프로젝트 Cube Tetris의 규칙은 다음과 같다.
1. START를 누르면 Red/Green/Blue 중 랜덤으로 1층에 생성
2. 화살표를 이용하여 4층에서 나온 섞을 색을 이동
3. 합치고 싶은 색 위에서 DOWN을 눌러 색을 해당 층에 혼합
4. Red/Green/Blue를 합쳐 흰색을 만들게 되면 불이 꺼짐
5. 블록 생성 후 5초 동안 DOWN을 누르지 않으면 자동DOWN
6. 중복이 된 색을 넣으면 그 위층에 쌓임
7. 4층까지 모두 쌓이게 된다면 실패
8. 정해진 개수만큼 불을 끄게 된다면 성공

본 프로젝트에서 다루는 Tetris와 기존의 Tetris와의 차이점으로는 입체와 평면의 차이로써 시작점이 일치하지 않다는 점과 다각도에서 보아야 한다는 점이 있다. 또한 기존의 Tetris 에서는 층 별 설계를 잘 하여야 하지만 본 프로젝트의 Tetris에서는 자신이 어떠한 색을 어디에 두어야 하는지 기억력과 순발력을 요구한다.

전체 구성도

39 ict 444 tetris (6)
1. Touch Board에서 이벤트 발생
2. 프로세싱으로 이벤트 값 전송
3. 이벤트값을 해석 후 Arduino로 값 전송
4. Arduino에서 이벤트 처리
5. Arduino에서 이벤트 처리 후 결과 Processing으로 리턴
6. Processing 리턴 값에 대한 사운드 발생

개발 환경
(1) Arduino
큐브의 RGB 전구 RED, BLUE, GREEN 3가지 색을 개별적으로 컨트롤 한다. 개별적 컨트롤 하는 방식으로 Charlie Plexing 기법을 사용하였다.
Charlie Plexing 기법이란 적은 I/O핀으로 많은 LED를 다루는 기술 이다. 핀당 제어가 가능한 ELD의 수로는 (N^2-N)의 공식으로 성립하게 되며 본 프로젝트의 4X4X4큐브에서 LED 개수 64개는 아두이노의 16개의 핀으로 제어가 된다.

핀과 연결이 되면 C++파일을 이용하여 Mapping Table을 만든 후 헤더에 추가한다.

LED를 개별적으로 켤 경우 drawLed 함수를 이용하여 x, y, z값과 색상 밝기를 입력하면 그 위치가 켜지는 방식이며 이 drawLed를 활용하여 drawBox, drawWall, drawLine등 큐브를 3차원으로 컨트롤 하는 함수를 cubeplex 클래스에 미리 구현하여 헤더에 추가한다.

RGB 각각을 기본 색상으로만 이루어진 PrimaryColor, 두 가지 색을 합친 SecondaryColor, 그리고 모든 색상이 있는 nextColor의 배열에 추가 되며 각각의 어레이 위치에는 매크로 함수를 이용하여 고유 값이 저장 되어 있으며 다른 색상을 원한다면 위 함수를 호출 해 주는 것으로 색상이 변하게 된다.

큐브에 있는 모든 메모리를 해제하는 ClearBuffer가 있으며 이전의 함수의 메모리를 해제하는 FlushBuffer 두 가지 함수가 있다.

하나의 이벤트를 행한 후 FlushBuffer를 호출하지 않을 경우 다음 이벤트에서 이중으로 이벤트가 발생할 수 있기 때문에 항상 이벤트의 마지막에 Flush Buffer를 호출해 주어야 한다.

(2) Processing
컨트롤판에서 사용하는 BARE CONDUCTIVE TOUCH BOARD의 이벤트 값을 받아와 Arduino에 전송해 준다. 이 때 전송받는 이벤트 값은 키보드에 있는 알파벳 값을 고유값으로 들어오게 되며 Arduino에 전송되는 값은 모두 int형으로 고유값을 변환하여 보내주게 된다. 또한 블록이 생성되면 Thread를 이용하여 5초가 지나게 되면 다운되는 이벤트를 보내주게 되는데, 이를 Arduino에서 구현하지 않는 이유로는 아두이노에서 기본적으로 Thread를 지원하지 않으며 메인 프로세스외에 서브 프로세스로 Thread를 구현 하였을 때 정상적으로 작동하지 않는 문제점도 있었기 때문에 제어 역할을 하는 Processing에서 구현하는 방식을 채택 하였다.
또한 Processing에서는 Arduino에서 생기는 이벤트에 대한 사운드 역할도 함께 한다. 예를 들어 블록이 없어지는 이벤트, 새로운 블록이 생성되는 이벤트, 실패 그리고 성공 이벤트 등 모든 이벤트에 대한 사운드는 Processing에서 제공 한다.

단계별 제작 과정
1. 4층 높이의 RGB LED 기둥 제작
2. 제작된 기둥을 기판에 부착
3. 기판 뒷부분 공통 색상 다리 연결
4. 연결된 선을 아두이노에 연결
5. 아두이노에 소스 이식 하여 작동 여부 확인
6. Processing – Arduino 연결
7. Processing을 이용한 큐브 개별 컨트롤
8. Processing – Touch Board 연결
9. 시리얼 통신 이벤트 전달
10. 큐브 이벤트 동작 확인

기타 자료
회로도

39 ict 444 tetris (1)

위 그림과 같이 Z축으로 한 개씩 쌓아 가지만 90°씩 돌려 서로 다른 다리가 맞물리도록 쌓아간다.

39 ict 444 tetris (2)

1층 RGB 전구를 기준으로 각 R, G, B, GND 다리를 공통적으로 모아 한쪽으로 배선을 빼낸다.
배선 번호와 아두이노핀 연결은 다음 표와 같다.

39 ict 444 tetris (1)

소스코드
(1) Arduino

if(Seral.available()>0) {
int b = Serial.read();
Serial.print(b);
int r = b;
if(Start == false){
if(r==0||r==3)
{
moveY(r);
}
if(r==1||r==2){
MoveX(r);
}
if(r==4){
DownKey();
}
}
if(r==5){
planarFlop3D();
starter();
}
if(r==6){
Rcolor=-7;
clearBuffer();
flushBuffer();
Tstatus=true;

Processing – Arduino간 시리얼 통신

Serial 통신으로 이벤트 값이 전달되었을 경우 int형으로 값을 읽어온다. 읽어온 값에 의해 다음 이벤트를 호출하게 된다.

39 ict 444 tetris (2)

void MoveY(int a){
if(a==0){
if(Ry!=3){
drawLed(-7,Rx,Ry,Rz);
flushbuffer();
Ry++;
drawLed(Rcolor, Rx, Ry, Rz);
flushBuffer();
delay(200);
}
}
else if(a==3){
if(Ry ! =0){
drawLed(-7,Rx,Ry,Rz);
flushbuffer();
Ry–;
drawLed(Rcolor, Rx, Ry, Rz);
flushBuffer();
delay(200);
}
}
}

Y축 이동 이벤트

void MoveX(int t){
if(t==1){
if(Rx!=0){
drawLed(-7,Rx,Ry,Rz);
flushBuffer();
Rx–;
DrawLed(Rcolor,Rx, Ry,Rz);
flushBuffer();
delay(200);
}
}
else if(t==2){
if(Rx!=3){
drawLed((-7,Rx,Ry,Rz);
flushBuffer();
Rx++;
DrawLed(Rcolor,Rx, Ry,Rz);
flushBuffer();
delay(200);
}
}
}

X축 이동 이벤트

블록 이동 이벤트로 상승/감소 이벤트를 체크 후 끝점에 위치하고 있는지 확인한다. 만약 끝점에 있지 않은 경우 상승/감소를 하게 되며 끝점에 있다면 이벤트 처리를 하지 않고 넘어가게 된다.

void DownKey(){
int ta=0; //합쳐야 될 z축 값
int hap=0; //합침 유무 확인
for(int i=2; i>=0; i–){
drawLed(Rcolor,Rx,Ry,i+1);
flushBuffer();
delay(100);
drawLed(-7,Rx,Ry,i_1);
flushBuffer();
if(PresentLed[Rx][Ry][i] !=-7){
int Pcolor=PresentLed[Rx][Ry][i];
switch(Pcolor{

Down키 이벤트 호출

Down 이벤트가 호출되었을 경우 Z축 최상위인 3을 제외하며 한 층씩 내려가며 비교하게 된다. 만약 LED가 켜져 있는 경우 Switch 문을 이용하여 비교하게 된다.

39 ict 444 tetris (5)39 ict 444 tetris (4)

현재 Led가 켜져 있는 층의 Color 값과 블록의 Color 값을 비교하여, 기존의 층에 있는 Color에 섞여있지 않은 값이 들어오게 된다면 그 층에 색이 섞여서 반환하게 되며, 이미 있는 색상일 경우 그 위층에 블록의 Color 값을 반환하여 쌓이게 된다.

if(hap==0){
if(PresentLed[Rx][Ry][ta]==6){
drawLed(6, Rx, Ry, ta);
flushBuffer();
delay(300);
PresentLed[Rx][Ry][ta]=-7;
drawLed(-7, Rx, Ry, ta);
flushBuffer();
delay(300(;
Tcount++;
}
else{
drawLed(PresentLed[Rx][Ry][ta], Rx, Ry, ta);
flushBuffer();
}
}
else{
drawLed(PresentLed[Rx][Ry][ta+1], Rx, Ry, ta+1);
flushBuffer();
}
flushBuffer();
delay(300);

Tstatus=true;
}

변수 Hap이 0일 경우 색이 합쳐졌다는 의미이며 현재 층의 Led Color값이 6, 즉 흰색이 되게 되면 0.3초 동안 반짝이며 -7값으로 변경 되면서 꺼지게 된다. Led Color 값이 6이 아니라면 그 층에 색이 합쳐지게 된다.
만약 Hap이 1일 경우 색이 섞이면 안되므로 현재 층 보다 한 칸 위에 색이 쌓이게 된다.

void starter(){
Tcount =0;
flushBuffer();
clearBuffer();
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
for(int a=0; a<4; a++){
PresentLed[i][j][a]=-7;
}
}
}
for(int i=0; i<4; i++){
for(int j=0; J<4; J++){
int rrcolor=random(0,3);
PresentLed[i][j][0];
flushBuffer();
}
}
Start=false;
delay(1000);
}

starter 이벤트가 호출이 되면 현재 클리어한 블록 카운트를 초기화 하며 기존에 켜져있는 모든 LED를 끈다. 그 후 1층에 RED, BLUE, GREEN 중 1가지 색을 랜덤으로 배치하며 현재 start가 되었다는 값을 반환해준다.

void randomCreate(){

Rx = random(0,4);
Ry = random(0,4);
Rz = 3;
Rcolor = random(0,3);
drawLed(Rcolor, Rx, Ry, 3);
flushBuffer();v
Tstatus=false;
Serial,write(1);
}

게임이 시작하게 되면 randomCreate 함수를 호출하게 되는데 이 함수는 가장 위층에 랜덤 색상으로 하나의 LED를 켜주는 역할을 하며 현재 블록 하나가 컨트롤되고 있는 값을 반환하여 준다. 또 Serial 통신을 통해 프로세싱에 현재 블록이 컨트롤되고 있다는 이벤트를 전달하여 준다.

int Discrimination(){
flushBuffer();
if(Tcount!=3){
for(int i=0; i<4, i++){
for(int j=0; j<4; j++){
if(PresentLed[i][j][3]! = -7(
freurn 1;
}
}
}
return 0;
}
else
return 2;
}

Discrimination 함수는 게임 승패 여부를 확인하는 함수이다. 블록 하나가 다운되어 연산이 실행된 후 호출이 되며 Tcount는 클리어 한 블록의 개수를 나타낸다. 현재 코드에는 3개의 블록을 클리어하게 되면 게임이 승리로 끝나게 되므로 카운트가 Tcount 값이 3일 경우 반환을 2로 하여 게임이 승리하게 되며, Tcount 값이 3이 아니지만 Z축 4층에 LED가 켜져 있다면 실패로 간주한다. Tcount 값이 3이 아니며 4층에 켜져 있는 LED가 없다면 게임을 속행하게 된다.

(2) Processing

Serial Port;
Serial Port2;
void setup() {
size(1200, 600, P3D);
textureMode(NORMAL);’
fill(255);
prot = new Serial(this, Serial.list()[0], 9600);
}

Processing에서 아두이노와 Serial 통신을 위한 포트를 선언하여 준다.
Serial 통신이 다대일 통신이 가능함으로 배열을 통해 포트를 선언하여 설정한다.

void framesmanagement(){
int t=0;
t=port.read();
if(t==1){
Ft.start();
}
if (keyPressed) {
if((key== ‘T’ || key == ‘t’)) {
print(key);
delay(300);
port.write(5);
}
else if((key== ‘F’ || key== ‘f’)) {
print(key);
delay(300);
port.write(6);
}

Touch Board에서 이벤트값이 입력되었을 때 호출되는 함수이다.
t=port.read();는 아두이노에서 Serial 통신을 받아와 읽어오는 역할을 하며 블록이 생성 되었을때 아두이노에서 int형 1의 값이 넘어와 Thread를 시작하는 역할을 수행 한다. 이벤트 값은 키보드의 자판과 동일하게 입력되기 때문에 keyPressed함수로 키가 눌러졌는지 여부를 확인 후 어떤 키가 눌러졌는지 받는다. Touch Board의 키 값과 아두이노에 Serial 통신되는 값은 다음 표와 같다.

39 ict 444 tetris (5)

public class fillThread implements Runnable
{
Thread thread;
int pauseTime; //Time to wait between loops
int level = 0;
boolean filled=true;

public FillThread(int pt)
{

pauseTime = pt;
}
thread = new Thread(this);
thread.start();
}

public void run()
{
// do something threaded here
while(filled!=false) {

// Wait a little(give other threads time to run)
try {
Thread.sleep(1000);
level++;
if(level==4){
stop();
}
}

public void stop()
{
filled=false;
level=0;
thread = null;
}

Thread 동작하는 함수이다.
블록이 생성되어 Serial통신을 통해 생성되었다는 신호가 Processing에 도착하게 되면 함수가 호출된다.
위 함수에서는 블록이 다운되지 않고 5초가 흐르게 될 경우 다운 이벤트를 포트를 통해 전송하게 되고 Thread가 종료된다.

39 ict 444 tetris (3) 39 ict 444 tetris (4)

참고문헌
[1] http://sobisource.com/
[2] 말하고 듣고 대화하는 Physical Computing 아두이노 (한빛 아카데미)
[3] https://www.youtube.com/watch?v=maM-mrrYY3o

Leave A Comment

*