[38호]카멜레온 DIY LED 이야기 ④
카멜레온 DIY LED 이야기 4
LED ART 1 : I ♥ U와 변색 카멜레온
글 | 신상석 ssshin@jcnet.co.kr
디바이스마트 매거진 독자 여러분, 안녕하세요. 앞으로 5회에 걸쳐 [카멜레온 DIY LED 이야기]를 진행할 신상석입니다. 이 이야기는 WS2812B라는 컬러 LED를 기반으로 제작된 [카멜레온 DIY LED] 시리즈를 이용하여 생활에 필요한 다양한 형상을 꾸며보고 이것을 다양한 컬러로 디스플레이 해보는 내용입니다. 앞으로 진행할 내용에 대하여 간단히 알아보면 다음과 같습니다. (약간 변경될 수도 있습니다.) 앞으로 즐겁고 유익한 강의가 될 수 있도록 많은 격려와 성원 부탁드립니다. |
디바이스마트매거진 독자 여러분, 안녕하세요. 반갑습니다.
[카멜레온 DIY LED 이야기] 네번째 시간입니다.
아, 참, 그리고 앞으로는 [카멜레온 DIY LED] 대신 줄인 말로 [카DL]을 주로 사용할까 합니다. 아무래도 3글자가 편하겠죠?
그러면, 기본 준비물부터 챙겨 보도록 하지요. GO~
직선(BAR) 모듈과 곡선(ARC) 모듈
카DL의 기본 구성품은 그리 많지는 않지만, 직선과 곡선, 방향자, 기본 도형을 가지고 있어서 똑같지는 않지만 비슷한 정도로는 어떤 형상이든 모두 구현이 가능합니다. 왜냐하면 임의의 형상은 이것을 이루는 직선과 곡선의 조합으로 표현이 가능하기 때문입니다. 물론, 정밀도에서는 조금 차이가 날 것이므로 완전 똑같게는 안되겠지만 잘만 만들면 상당히 비슷하게 됩니다.
카DL은 직선(BAR) 형태로 다음의 6가지 모듈을 제공합니다. 실제로 JLED-BAR-1만으로도 구성은 가능하겠지만 이렇게 되면 너무나 많은 연결이 필요하므로 길이가 다른 6가지 모듈을 제공하여 사용의 편의성을 제공하고 있습니다. 이 6가지 모듈은 길이가 각각 1, 2, 3, 4, 5, 10cm 로 설계되어 있어 연결된 형상의 크기를 매우 쉽게 예측할 수 있는 것도 장점입니다. 급할 때는 자 대용으로도 사용이 가능하지요.
기본 직선(BAR) 모듈에 대응하여 카DL이 제공하는 기본 곡선(ARC) 모듈은 다음의 12가지 모듈입니다. 곡선의 경우는 원의 일부인 원호에 해당되는 부분을 제공하는데 모든 원호에 대하여 제공할 수는 없으므로 대표적인 3가지 다른 곡률을 가진 원을 정하여 제공합니다. 개수는 3개가 연속된 것과 4개가 연속된 것의 2종류를 제공하고, 방향성에 따라 UP, DOWN의 2종류로 나누어 제공하므로, 총 3 x 2 x 2 = 12 가지가 기본 모듈이 됩니다. (방향은 왼쪽이 IN, 오른쪽이 OUT입니다.)
모듈의 이름은 이 원호 모듈을 이용하여 원을 만들 경우, 사용되는 총 LED의 개수와 모듈이 포함한 원의 개수, 그리고 방향을 포함하여 만들어집니다. JLED-ARC12-D3 모듈을 예로 들면, 이 모듈은 LED 3개로 이루어진 DOWN(D) 방향의 LED로, LED가 총12개(이 모듈 4개)가 모이면 아래와 같이 원(지름 약 40mm 정도)이 되는 모듈입니다.
여러 개의 서로 다른 원호 모듈을 이용하면 부드러운 곡선을 표현할 수 있는데, 예를 들어 아래와 같은 지렁이 형상을 만들 수 있습니다.
오, 그러면 직선(BAR) 모듈과 곡선(ARC) 모듈을 함께 섞어서 사용한다면 여러가지 임의의 형상을 만들 수도 있겠네요. 예. 맞습니다. 동물도 만들 수 있고, 글자도 만들 수 있고, 메뚜기도 만들 수 있고, 조금은 어렵겠지만 뽀로로도 만들 수 있겠습니다. 아래는 몇가지 예입니다.
너무 오래 설명만 하면 재미가 없으니까 다른 모듈이 더 필요해지면 그 때 가서 또 설명하기로 하고, 우리의 1단계 목표인 [I ♥ U] 제작에 들어가 봅시다.
I ♥ U
1단계 : 형상 설계하기
제작을 하기 위하여 가장 먼저 해야 할 일은 규격을 정하는 것입니다. 아래와 같은 사항을 정해 놓고 시작하는 것이 좋겠습니다.
첫번째로 결정해야 할 것은 형상입니다. 무엇을 만들지, 어떤 형상으로 만들지를 정해야 합니다. 우리는 이미 정했죠! [I ♥ U] 형태로 가로로 길게 만드는 것으로 하겠습니다.
두번째로 결정해야 할 것은 용도입니다. 어떤 용도로 어느 장소에 설치할 것인가? 소품 형태로 어떤 곳에 놓아도 되는 형태로 만들 것인지, 벽이나 유리창에 간판처럼 붙여놓을 것인지 등이지요. 일단 우리는 휴대용 소품으로 들고 다닐 수 있는 투명 아크릴 박스 형태로 꾸며보기로 하지요. 아크릴 박스 형태는 온라인 아크릴 전문점에서 다양한 크기의 박스 형태를 구입할 수 있습니다.
세번째는 크기가 되겠습니다. 용도에 알맞게 하기 위하여 크기를 결정하기도 하지만 크기는 소요되는 비용과도 어느 정도의 비례하므로 이것도 고려 대상이 됩니다. 크기가 너무 크면 비용이 많이 들 뿐만 아니라, 전원 공급이나 고정 방법 등에서도 제약을 받을 수 있습니다. 그렇다고 너무 작으면 원하는 형상을 표현하는데 어려움이 따르거나 형상이 부자연스러워질 수도 있으므로 알맞은 크기를 선택하여야 합니다. 우리는 비용은 적게 들면서도 형상은 또렷하게 나타낼 수 있는 정도의 크기로 전체 크기가 25cm (가로) X 10cm (세로) X 7cm (두께) 정도의 아크릴박스에 들어가는 정도로 하겠습니다. (사실은 미리 생각해서 준비한 박스입니다.)
마지막으로 해야 할 일은 디자인입니다. 디자인을 하기 위하여는 일단, 카DL이 제공하는 모든 형상을 알고 이것을 선택적으로 사용하여 디자인하는 것이 좋습니다. 디자인은 사실 제작하는 사람의 취향이나 능력에 따라 조금씩 달라질 수 있습니다. 디자인 감각이 있는 사람은 좀 더 예쁘고 세련되게 만들 수 있을 것이고, 그렇지 않은 사람은 약간은 어색하거나 투박한 형상으로 만들 가능성이 높겠지요. 제가 사용할 디자인은 제이씨넷 [신승현]님이 만들어 준 것인데 8cm X 8cm 사각형을 기준으로 아래와 같이 디자인하였습니다. 직선(BAR) 모듈과 곡선(ARC) 모듈을 다양하게 사용하였고, 방향자 모듈도 사용한 것이 보입니다. 제가 보기에는 디자인이 꽤 괜찮습니다.
영문자 I 와 U는 카DL 모듈이 가능한 직접 연결이 될 수 있도록 하면 누가 디자인해도 거의 이런 모양으로 나올 것 같고, 하트(♥)는 사람마다 다르게 디자인할 것 같은데, 이런 경우 2가지 사항은 꼭 고려하면서 디자인하셔야 합니다. 하나는 LED의 모양 및 배치입니다. 카DL에 실제로 전원이 들어와서 불이 켜질 때의 모습을 상상하여 원하는 모습으로 나타날 수 있도록 모듈을 선택하고 배치하는 것이 중요합니다. 실제로 동작하는 것은 LED 불빛이므로 아래와 같이 카DL의 동그란 LED를 색칠해 본 후 이것이 괜찮게 보이는지를 판단해 보는 것이 하나의 방법입니다.
다른 하나는 연결성입니다. 형상 때문에 어쩔 수 없이 연결이 직접적으로 될 수 없는 부분이 생기게 되는데 이런 상황이 가능한 적게 생기도록(즉, 직접 연결이 가능한 많아지도록) 디자인하는 것이 중요합니다. 왜냐하면 직접 연결은 간단한 커넥터(JLED-CON-0)로만 쉽게 연결되기 때문입니다. 또한, 모서리 부분은 카DL의 직선(BAR) 모듈과 곡선(ARC) 모듈만으로는 표현하기 어려운 부분이 있을 수 있으므로 필요에 따라 방향자(DIR) 모듈이나 도형(FIGURE) 모듈도 섞어서 사용하면 좀 더 자연스러운 형상을 만들 수 있습니다.
아, 참, 방향자(DIR) 모듈은 위에서 설명을 하지 않았죠. 카멜레온 DIY LED는 모서리의 직접 연결을 위하여 아래와 같은 6가지 방향자(DIR)를 제공합니다. 이것은 UP 또는 DOWN 방향으로 각각 45도, 90도, 135도 방향 전환 시 사용할 수 있으며, 가끔씩은 도형적인 의미로도 사용됩니다.
위 하트 모양에서는 오른쪽과 같이 동그라미로 표시된 부분에 안성맞춤으로 사용이 되었네요.
2단계 : 형상 제작하기
자, 이제 설계(디자인)가 완료되었으니 구현할 차례입니다. 일반적으로 카DL을 구현하는 방법은 하나의 골판지 또는 폼보드 등을 밑판으로 하여 카DL을 관통하여 모양을 잡고, 뒤쪽에서 커넥터와 케이블을 이용하여 고정시키는 방법이 가장 편하고 쉽습니다. 도화지, 아트지, 스티로폼, 책받침과 같은 얇은 플라스틱 등등 상당히 많은 다양한 재료를 사용하여 보았지만, 현재까지는 2mm 두께의 폼보드가 가장 편리하고, 그 다음으로는 1mm 정도 두께의 골판지가 편리한 것으로 보입니다. 조립할 때 한가지 주의해야 할 것은 카DL은 방향성이 있으므로 신호선의 IN과 OUT 방향을 잘 보고 연결해야 한다는 점입니다. 각 모듈의 V(+5V)와 G(GND) 신호는 동일한 신호끼리 연결하여야 하는 것은 물론, 앞 모듈의 O(Data Out)핀은 반드시 다음에 연결할 모듈의 I(Data In)핀에 연결해야만 카DL 전체 형상이 정상적으로 동작할 수 있습니다.
그러면, 이제 실제로 골판지를 밑판으로 사용하여 순서대로 제작해 보겠습니다.
(1) 검정색 골판지를 가로 239mm, 세로 94mm의 사각형으로 자릅니다. (아크릴 두께가 있어 양쪽으로 3mm씩은 여유를 둡니다.)
(2) 카DL을 모양에 맞추어 골판지 위에 원하는 형태로 놓아 봅니다. (뒤집어 놓으면 균형을 잘 잡을 수 있습니다.)
(3) 카DL을 조립합니다. 방향성을 잘 확인하고, 위치를 잘 잡아가며 조립하여야 자신이 원하는 형태가 되므로 주의하여야 합니다. 특히 2개의 카DL이 직접 연결되는 부분은 정확하게 연결되도록 위치를 잘 잡아서 조립하여야 나중에 커넥터(JLED-CON-0)를 쉽게 연결할 수 있습니다. 한편, 카DL은 연결 핀이 뾰족하게 나와 있어 골판지를 관통하여 조립할 때 매우 조심하여야 합니다. 잘못하면 연결 핀에 손이 찔려 상처가 날 수도 있습니다.
(4) 골판지를 뒤로 돌려서, 직접 연결되는 카DL은 JLED-CON-0를 이용하여 연결하고(JLED-CON-0는 2핀 점퍼 3개를 동시에 각각 연결하는 형태인 2×3 점퍼임) 직접 연결되지 않는 카DL은 JLED-CABLE3-MM10 또는 JLED-CABLE3-MM20 케이블을 이용하여 연결합니다. 이 때 전원 및 데이터 신호가 서로 일치하도록 방향성을 확인하면서 연결해야 합니다. (V-V, O-I, G-G가 연결되도록 함)
3단계 : 아두이노 연결하기
이제 만들어진 형상을 제어하기 위하여 아두이노를 연결하도록 하겠습니다. 아두이노는 일반적으로 가장 많이 사용하는 아두이노 UNO를 사용해도 되지만, 우리는 제어기를 아크릴박스에 넣어서 휴대용으로 제작하려 하므로, 크기가 작고 가격이 저렴한 아두이노를 선택하는 것이 좋겠습니다. 아두이노 NANO도 좋고, 아두이노 Pro Micro 등 어떤 것도 좋은데, 여기서는 기왕이면 크기가 엄지 손가락 크기로 가장 작고 가격도 상대적으로 저렴한 아두이노 Pro Micro(아두이노 Leonardo의 소형 버전)를 사용하는 것으로 하겠습니다.
아두이노 Pro Micro는 납땜이 되지 않은 상태의 것이 많은데 아래와 같은 핀 배열을 가지고 있습니다. 카DL과 연결할 신호는 VCC와 GND, 데이터 1포트이므로, 연결하기 쉽게 빨강색 네모 박스의 신호를 연결하도록 하겠습니다. 데이터신호로 A3 신호를 사용하는 것이지요. (아날로그 핀은 디지털핀으로도 사용 가능합니다.) 좀 더 편리하게 사용하려면 이 3핀의 신호를 터미널블록으로 처리한 카DL 전용 아두이노인 JARDUINO-PROMICRO-1을 사용하는 것도 방법입니다. (여기서는 이것을 사용하겠습니다.)
JARDUINO-PROMICRO-1의 3핀을 카DL 형상의 첫번째 모듈의 입력과 연결하면 되는데, 이 때 JLED-START-1을 아두이노와 카DL 첫번째 모듈 사이에 삽입하는 것이 좋습니다. JLED-START-1은 카DL 모듈을 여러 개 연결하거나 장시간 사용하는 경우 전체 모듈의 안정성을 위하여 제어기(아두이노)와 카DL 첫번째 모듈 사이에 장착하는 안정화 모듈로 안정화를 위한 대용량 커패시터와 저항을 내장하고 있습니다. 신호선 연결은 일반적인 카DL 모듈과 동일하게 연결합니다. (V-V, O-I, G-G)
4단계 : 아두이노 스케치 프로그램하기
하드웨어는 모두 완성되었으므로, 이제는 스케치 프로그램만 작성하면 될 것 같습니다. 자신이 원하는 형태로 [I ♥ U]가 움직이도록 프로그램을 작성해 보시지요. 지난 시간에 라이브러리를 이용하는 방법을 익혔으므로 너무 어렵게 생각하지 말고 일단 지난번 배운 라이브러리만을 이용하여 구현해 보겠습니다. 한가지 예로 지난 회에서 언급하였던 Adafruits 프로그램 중 strandtest 프로그램을 데이터 핀 번호와 LED 개수, 그리고 색상과 delay 시간 등만 아주 조금 바꾸고 그대로 실행시켜 보겠습니다. 설명은 프로그램 내의 주석을 참조하시기 바랍니다.
—————————————————
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#define PIN A3 // JARDUINO-PROMICRO-1 사용으로 데이터 핀은 A3
Adafruit_NeoPixel strip = Adafruit_NeoPixel(53, PIN, NEO_GRB + NEO_KHZ800); // [I ♥ U] LED 갯수 = 53
void setup() {
strip.begin();
strip.show();
}
void loop() {
colorWipe(strip.Color(255, 0, 0), 20); // 빨강색으로 하나씩 순서대로 채우기
colorWipe(strip.Color(0, 255, 0), 20); // 녹색으로 하나씩 순서대로 채우기
colorWipe(strip.Color(0, 0, 255), 20); // 파랑색으로 하나씩 순서대로 채우기
theaterChase(strip.Color(127, 127, 0), 20); // 노랑색(Yellow) 사이키 조명 디스플레이
theaterChase(strip.Color( 0, 127, 127), 20); // 심홍색(Magenta) 사이키 조명 디스플레이
theaterChase(strip.Color(127, 0, 127), 20); // 청록색(Cyan) 사이키 조명 디스플레이
theaterChase(strip.Color(127, 127, 127), 20); // 흰색(White) 사이키 조명 디스플레이
rainbow(20); // // 전체가 같은 색으로 동시에 변하면서 디스플레이
rainbowCycle(20); // // 전체가 다르게 다양한 색으로 변하면서 디스플레이
theaterChaseRainbow(20); // // 다양한 색으로 변하면서 사이키 조명 디스플레이
}
// 하나씩 순서대로 채우기 함수
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
// 전체가 같은 색으로 동시에 변하면서 디스플레이하는 함수
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// 전체가 다르게 다양한 색으로 변하면서 디스플레이하는 함수
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
// 한가지 색의 사이키 조명 디스플레이
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// 다양한 색으로 변하면서 사이키 조명 디스플레이
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// 0~255까지의 값을 전달하면 4 바이트 컬러값을 리턴하는 함수
// 임의의 고르게 분포된 컬러값을 생성하기 위하여 사용
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 – WheelPos;
if(WheelPos < 85) {
return strip.Color(255 – WheelPos * 3, 0, WheelPos * 3);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 – WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 – WheelPos * 3, 0);
}
}
—————————————————-
5단계 : 업로드하고 실행시키기
이제 프로그램까지 준비가 되었으니 업로드하고 실행시켜 볼 차례입니다. 한가지 주의하여야 할 것은 앞에서도 언급했듯이 아두이노 Pro Micro는 아두이노 Leonardo의 소형 버전이므로, 업로드시 스케치 프로그램의 [보드] 선택 항목을 “UNO”가 아닌 “Leonardo”로 선택하여야 하는 것입니다. 나머지 업로드 방법은 일반적인 아두이노와 동일합니다.
아래에 업로드 된 프로그램이 실행되는 예를 몇 가지 보였습니다.
오우, 아주 화려하게 잘 동작합니다. 생각했던 것보다 꽤 밝아서 눈이 조금 부실 정도입니다. 밤에는 멀리서도 아주 잘 보일 것 같네요. (혹시, 은은한 밝기를 원하시면 스케치 프로그램 작성 시 색상을 조절하시면 됩니다.)
6단계 : 외관을 정리하고 고정하기
위의 사진에서는 아크릴 상자에 넣어진 모습으로 동작하는데, 사실은 아크릴 상자에 넣지않은 상태에서 동작을 테스트하고 원하는 형태로 잘 동작하면 그 때 아크릴 상자에 조립하는 것이 순서입니다. 조립시에는 먼저, 연결된 카DL 형상을 아크릴 상자의 앞면에 밀착시키고, JLED-START-1과 JARDUINO-PROMICRO-1 은 뒤쪽으로 빼 놓습니다.
준비한 휴대폰 보조 배터리(용량이 큰 것일수록 좋음. 적어도 5000mAh 이상의 배터리 권장)를 아크릴 박스 뒷면에 위치시킵니다. 휴대성 및 전원 공급 용량의 이유로 업로드 후 실제 동작 시에는 전원 공급을 USB 케이블로 하지 않고 휴대폰 보조 배터리 등으로 하는 것이 좋습니다. 위 사진에서 보듯 찍찍이를 아크릴의 한쪽 면과 휴대폰 보조 배터리의 한쪽 면에 각각 붙인 후 서로 밀착시켜 정리하면 깔끔한 모양을 유지할 수 있습니다. USB 케이블을 이용하여 휴대폰 보조 배터리와 JARDUINO-PROMICRO-1을 연결하면 완성입니다.
7단계 : 내가 원하는 곳에 놓고 감상하기
모든 것이 원하는 대로 잘 동작합니다. 이제 내가 원하는 곳에 가져다 놓고 감상할 시간입니다. 주변 사람에게 자랑도 좀 하구요. 연인이나 친구에게 선물할 수도 있겠습니다. 저는 일단, 거실 앞쪽에 한 번 놓아 보았습니다. 괜찮게 된 것 같네요.
불을 꺼보니 LED의 움직임이 더욱 선명하게 나타나는 것이 환상적입니다. 오~ 예~
이 정도면 자동차 뒤 유리창에 놓아도 괜찮을 장식이 될 것 같습니다. 뒷 차에 부담을 주는 정도가 안되도록 밝기는 조절해야 하겠죠? 기회가 되면 [I ♥ U] 뿐만 아니라 내가 원하는 모양을 만들어 응용도 해보시기 바랍니다.
변색 카멜레온
[I ♥ U]가 잘 만들어졌으니, 좀 더 고급 단계인 [변색 카멜레온]에 도전해 보겠습니다. [I ♥ U]에서 했던 방법과 똑같은 순서대로 진행해 봅니다.1단계 : 형상 설계하기
이제 긴 설명은 생략하고 조금 단순화하여 빠르게 진행해 보겠습니다.
· 형상 : 카멜레온
· 용도 : 실제 카멜레온처럼 일부분씩 색상을 다르게 나타낼 수 있고, 약간의 움직임도 표현할 수 있는 창문에 부착하는 전광판 형태로 제작
· 크기 : A4 용지 크기와 비슷한 30cm X 20cm에 들어가는 크기
· 디자인 : 아래 참조 (이번 디자인도 제이씨넷 [신승현]님의 디자인입니다.)
카멜레온과 같은 동물 형상은 조금은 복잡하므로 특징을 잘 살려서 단순하게 표현하는 것이 중요합니다. (이것은 재능이 조금은 필요한 부분이므로 자신이 직접 하기가 어려우면 잘 할 수 있는 다른 사람에게 부탁하는 것도 방법입니다.) 아, 참, 그리고 기본 설계 도구가 궁금하실 분도 있을 것 같은데 위 그림은 오토캐드를 이용하여 카DL 기본 형상을 라이브러리처럼 모두 만들어 놓은 상태에서 이것을 배치하고 연결하여 만든 그림임을 밝혀둡니다. 이렇게 하기가 쉽지 않으면 그냥 손으로 대강의 모습을 스케치 한 후 카DL을 직접 배열해 가면서 진행해도 되겠습니다.
이미 한 번 이야기한 것처럼 카DL은 방향성이 있으므로 이것을 잘 고려하여 형상을 만들어야 합니다. 또한, 첫 시작점을 어디로 잡을 것인지, 연결되는 순서는 어떻게 할 것인지도 전체적인 모양을 고려하여 결정하는 것이 좋습니다.
저는 목 부분에서 시작하여 얼굴 ▶ 등 ▶ 꼬리 ▶ 배 ▶ 뒷다리 ▶ 앞다리 ▶ 피부 ▶ 눈 ▶ 혀의 순으로 연결되도록 카DL을 배치하였습니다. 여기서 새로 선보인 것은 눈 형상에 해당되는 JLED-HEXA-7 입니다. 6각형 모서리에 LED(WS2812B)가 하나씩 있고 가운데에도 1개가 있는 형상으로 카DL 도형(FIGURE) 그룹 중의 하나입니다. 카DL의 도형(FIGURE) 그룹은 아래와 같이 7개의 도형으로 구성되어 있으므로 필요에 따라 알맞은 것을 골라 사용하면 됩니다.
2단계 : 형상 제작하기
1단계에서 배열한 순서대로 카DL을 조립해 봅니다. 지난번과 마찬가지로 직접 연결되는 부분이 잘 조립될 수 있도록 하는 것에 주의하여야 하며, 한 가지 팁을 더 이야기하면 직접 연결되는 부분은 순서대로 차례차례 조립하는 것이 좋습니다. 순서 없이 조립을 진행하다 보면 중간에 직접 연결되는 부분을 조립할 때 서로 어긋나서 이미 진행하였던 조립을 다시 수정하여야 하는 상황이 발생할 수도 있기 때문입니다. 아래 그림에서는 화살표로 방향과 연결 관계를 미리 표시하여 가능한 이 순서대로 조립을 진행합니다. 또한 카DL의 원호(ARC) 그룹인 경우는 Up 방향 모듈과 Down 방향 모듈의 구분이 쉽지 않으므로, 그림 상에서 “U”, “D”를 간단히 명시해 놓고 조립을 진행하면 실수를 줄일 수 있습니다.
아래는 조립이 완성된 상태의 앞면입니다.
3단계 : 아두이노 연결하기
이번에는 제어기로 가장 많이 사용하는 아두이노 UNO를 사용하도록 하겠습니다. 아두이노 UNO와 JLED-START-1까지 연결한 뒷면 모습은 아래와 같습니다. 데이터핀은 디지털 핀 6번을 사용하였습니다. 아두이노와 JLED-START-1의 입력쪽을 각각 +5V- V(VCC), GND-G(GND), D6-I(Data In)의 짝으로 연결합니다.
4단계 : 아두이노 스케치 프로그램하기
그 동안에는 다른 사람들이 제공하였던 라이브러리와 스케치 프로그램을 그대로 이용하면서 값만 조금 바꾸어 사용하였는데, 이번에는 조금 더 적극적으로 내가 표현하고 싶은 동작과 색상을 정하고 이것을 스케치 프로그램으로 구현하도록 해 보겠습니다. 필요하다면 새로운 함수도 정의하여 작성하도록 하지요. 일단, 동작과 색상을 표로 간단하게 기술해 봅시다.
[카멜레온 형상의 동작 및 색상]
단계 | 동작과 색상 | 참조 사항 |
1 | 머리를 녹색으로 켜기 | |
2 | 등과 배, 꼬리를 파랑색으로 켜기 | |
3 | 뒷다리와 앞다리를 보라색으로 켜기 | |
4 | 피부를 노랑색으로 켜기 | |
5 | 눈을 주황색으로 켜기 | |
6 | 앞다리와 뒷다리를 번갈아 가면서 켜기 | 2번 반복 |
6 | 혀를 빨강색으로 내밀었다가 집어넣기 | |
7 | 눈은 싸이키로 반짝반짝, 피부도 싸이키로 반짝반짝 | |
8 | 전체가 동일한 랜덤색으로 앞에서부터 뒤로 천천히 변신 | 3번 반복 |
9 | 전체가 개별적으로 무지개색으로 변신 | 약 5초간 |
10 | 완전히 사라짐 | 약 5초간 |
※ 10단계까지 진행을 마치면 다시 1단계부터 무한 반복합니다.
[프로그램 구현 방법]
연결순서 | 그룹구분 | 시작번호 | 끝번호 |
1 | 머리 | 0 | 3 1 |
2 | 등 | 3 2 |
5 7 |
3 | 꼬리 | 5 8 |
8 3 |
4 | 배 | 8 4 |
8 9 |
5 | 뒷다리 | 9 0 |
9 9 |
6 | 앞다리 | 1 0 0 |
1 1 1 |
7 | 피부 | 1 2 2 |
1 3 2 |
8 | 눈 | 1 3 3 |
1 3 9 |
9 | 혀 | 1 4 0 |
1 4 7 |
색상이 바뀌는 동작은 그룹별로 처리되어야 하므로, 이것을 효과적으로 처리할 수 있는 기능은 우리가 새로 만들어야 할 것 같습니다. 음… 당장 엄밀하게 정의하지는 못하겠지만, 현재 우리가 사용하고 있는 기능을 LED 번호의 특정 범위에서 실행할 수 있는 함수로 확장하여 정의하면 매우 편리할 것 같네요. 예를 들어 colorWipe(color, wait)로 정의된 기능을 이용하여 colorWipeFT(from, to, color, wait)와 같이 시작 LED 번호인 from과 끝 LED 번호인 to를 파라미터로 더 정의하여 사용하면 좋을 것 같습니다. 이것은 원래 제공되었던 프로그램을 그대로 가져다가 쓰면서 for 루프를 사용하여 from부터 to까지 적용하면 되므로 별로 어렵지는 않을 것으로 생각됩니다. 예를 들어 colorWipeFT(from, to, color, wait) 함수 하나만 작성해 보면 아래와 같이 됩니다.
void colorWipeFT(uint16_t from, uint16_t to, uint32_t color, uint16_t wait)
{
/* 일정 범위의 카DL을 하나씩 순서대로 채우는 함수
- from : from LED 번호
- to : to LED 번호
- color : 32비트 RGB 컬러 코드, 0x00RRGGBB 형태
- wait : LED 사이의 동작 간격(딜레이)
*/
for (int i=from; i<=to; i++) // 원래 범위가 (0~끝)인 것을 (from~to)로 수정
{
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
원래 colorWipe( ) 프로그램 내에서 for (uint16_t i=0; i<strip.numPixels(); i++) 로 표현된 부분을 for (int i=from; i<=to; i++) 로 바꾸기만 하면 쉽게 colorWipeFT( )가 작성되는 것을 볼 수 있습니다. 다른 함수들도 이런 방법을 잘 응용하면 쉽게 만들 수 있겠지요?
또, 한가지 미리 알아둘 것은 randomSeed( ) 함수와 random( ) 함수에 관련된 것입니다. 이 부분은 C 함수에서도 많이 나오는 라이브러리 함수인데 아두이노에서도 라이브러리 로 제공됩니다. random( ) 함수를 이용하면 임의의 값(난수)을 얻을 수 있으므로 스케치 프로그램을 실행시킬 때 다양성을 부여하기가 매우 쉽습니다. 예를 들어 카DL 형상에 색상을 표현할 때 이 random( ) 함수를 적용하여 표현한다면 함수가 실행될 때마다 값이 달라져 표현되는 색이 실행할 때마다 변하는 임의성을 확보할 수가 있겠습니다. 함수를 사용하는 방법은 아래와 같습니다.
randomSeed(seed)
· 기능 : seed 값에 따른 난수표의 시작 포인트를 결정하여, 추후 random( ) 함수 사용시 난수를 제공할 수 있는 준비를 함, seed 값이 같으면 random( )의 return 값은 동일한 값이 됨
· seed : 정수값
· 반환값 : 없음
random(max)
random(min, max)
· 기능 : min과 max 사이의 임의의 난수값을 제공
· min : 반환값 범위의 최소값으로 long 타입이며 이 값은 포함됨
· max : 반환값 범위의 최대값으로 long 타입이며 이 값은 포함이 되지 않음
· 반환값 : 0~max 또는 min~max 사이의 정수
많이 사용되는 예로는,
randomSeed(analogRead(0));
randNumber = random(256);
과 같이 사용하여 0~255까지의 난수를 얻는 방법이 있습니다. 즉, 아두이노에서 아날로그 포트 중 하나인 A0 포트에 아무 것도 연결하지 않은 상태의 값을 읽으면 임의의 값이 읽히는 것을 이용하여 randomSeed(seed) 함수를 결정하고, 이후 원하는 범위의 값은 random(max)를 이용하여 추출해 내는 것이지요.
자, 이제 기본 준비가 되었으니 실제 카멜레온 형상에 대한 스케치 프로그램을 직접 작성해 보겠습니다. 가능하면 여러분들도 나름대로 먼저 충분히 작성해 본 다음에 아래 내용과 비교 검토해 보기를 권장합니다.
—————————————————-
/* 카멜레온 만들기 */
#define RED 0x00ff0000 // 빨강
#define GREEN 0x0000ff00 // 녹색
#define BLUE 0x000000ff // 파랑
#define YELLOW 0x00ffff00 // 노랑
#define SKYBLUE 0x0073d1f7 // 하늘색
#define PINK 0x00f69fa8 // 분홍
#define BLACK 0×00000000 // 검정(OFF)
#define BROWN 0x0088563f // 갈색
#define ORANGE 0x00f3753a // 오렌지색
#define DEEPBLUE 0x002a365c // 남색
#define HEAD_FROM 0 // 머리 시작 번호
#define HEAD_TO 31 // 머리 끝 번호
#define SPINE_FROM 32 // 등 시작 번호
#define SPINE_TO 57 // 등 끝 번호
#define TAIL_FROM 58 // 꼬리 시작 번호
#define TAIL_TO 83 // 꼬리 끝 번호
#define BELLY_FROM 84 // 배 시작 번호
#define BELLY_TO 89 // 배 끝 번호
#define LEG_B_FROM 90 // 뒷다리 시작 번호
#define LEG_B_TO 99 // 뒷다리 끝 번호
#define LEG_F_FROM 100 // 앞다리 시작 번호
#define LEG_F_TO 111 // 앞다리 끝 번호
#define SKIN_FROM 112 // 피부 시작 번호
#define SKIN_TO 132 // 피부 끝 번호
#define EYE_FROM 133 // 눈 시작 번호
#define EYE_TO 139 // 눈 끝 번호
#define TONGUE_FROM 140 // 혀 시작 번호
#define TONGUE_TO 147 // 혀 끝 번호
#define TWINKLE_LOOP 3 // twinkle 함수 실행시 깜빡깜빡 사이키 조명 횟수
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#define PIN 6 // 6번 핀을 데이터 핀으로 이용
Adafruit_NeoPixel cdl = Adafruit_NeoPixel(147, PIN, NEO_GRB + NEO_KHZ800);
// cdl 구조체 설정, 카멜레온 LED 총 개수 = 147
void setup() {
cdl.begin();
cdl.show();
randomSeed(analogRead(0)); // random( ) 함수 사용을 위한 준비, seed = A0 포트 read 값
}
void loop() {
uint8_t r, g, b;
uint16_t i;
uint32_t color;
colorWipeFT(HEAD_FROM, HEAD_TO, GREEN, 0); // 머리를 녹색으로 켜기
delay(300);
colorWipeFT(SPINE_FROM, SPINE_TO, SKYBLUE, 0); // 등을 하늘색으로 켜기
colorWipeFT(BELLY_FROM, BELLY_TO, SKYBLUE, 0);// 배를 하늘색으로 켜기
colorWipeFT(TAIL_FROM, TAIL_TO, BLUE, 0); // 꼬리를 파랑색으로 켜기
delay(300);
colorWipeFT(LEG_F_FROM, LEG_F_TO, BROWN, 0); // 앞발을 갈색으로 켜기
colorWipeFT(LEG_B_FROM, LEG_B_TO, BROWN, 0);// 뒷발을 갈색으로 켜기
delay(300);
colorWipeFT(SKIN_FROM, SKIN_TO, YELLOW, 0); // 피부를 노랑색으로 켜기
colorWipeFT(EYE_FROM, EYE_TO, PINK, 0); // 눈을 핑크색으로 켜기
delay(300);
for (i=0; i<4; i++) // 앞발과 뒷발을 번갈아 가면서 켜고 끄기, 4번 실행
{
colorWipeFT(LEG_F_FROM, LEG_F_TO, DEEPBLUE, 0);// 앞발은 남색으로 켜고
colorWipeFT(LEG_B_FROM, LEG_B_TO, BLACK, 0); // 뒷발은 끄기
delay(200);
colorWipeFT(LEG_B_FROM, LEG_B_TO, DEEPBLUE, 0); // 뒷발은 남색으로 켜고
colorWipeFT(LEG_F_FROM, LEG_F_TO, BLACK, 0); // 앞발은 끄기
delay(200);
}
colorWipeFT(LEG_F_FROM, LEG_F_TO, DEEPBLUE, 0); // 앞발을 남색으로 켜기
delay(200);
tongueFT(TONGUE_FROM, TONGUE_TO, RED, 50); // 혀를 빨강색으로 내밀었다가 집어넣기
twinkleFT(EYE_FROM, EYE_TO, PINK, 20); // 눈을 핑크색으로 깜빡이기
colorWipeFT(EYE_FROM, EYE_TO, PINK, 0); // 눈을 모두 켜기
twinkleFT(SKIN_FROM, SKIN_TO, YELLOW, 20); // 피부를 노랑색으로 깜빡이기
colorWipeFT(SKIN_FROM, SKIN_TO, YELLOW, 0); // 피부를 모두 켜기
delay(300);
for (i=0; i<3; i++) {
r = random(256); // 난수 1개 얻어 r 값으로 할당
g = random(256); // 난수 1개 얻어 g 값으로 할당
b = random(256); // 난수 1개 얻어 b 값으로 할당
color = cdl.Color(r, g, b); // r, g, b로 RGB 컬러값 결정
colorWipeFT(0, cdl.numPixels()-1, color, 10); // 위 컬러로 전체를 차례로 색칠
delay(500);
}
rainbowCycle(20); // 각 카DL을 다양한 색으로 표현
colorWipeFT(0, cdl.numPixels()-1, BLACK, 0); // 모든 카DL 소등(OFF)
delay(3000);
}
/* colorWipeFT( ) : 일정 범위의 카DL을 하나씩 순서대로 채우는 함수
- from : from LED 번호
- to : to LED 번호
- color : 32비트 RGB 컬러 코드, 0x00RRGGBB 형태
- wait : LED 사이의 동작 간격(딜레이)
*/
void colorWipeFT(uint16_t from, uint16_t to, uint32_t color, uint16_t wait)
{
uint16_t i;
for (i=from; i<=to; i++) // 원래 범위가 (0~끝)인 것을 (from~to)로 수정
{
cdl.setPixelColor(i, color);
cdl.show();
delay(wait);
}
}
/* tongueFT( ) : 일정 범위의 카DL을 혀를 내밀었다가 다시 거둬들이도록 동작처럼 움직이도록 하는 함수
- from : from LED 번호
- to : to LED 번호
- color : 32비트 RGB 컬러 코드, 0x00RRGGBB 형태
- wait : LED 사이의 동작 간격(딜레이)
*/
void tongueFT(uint16_t from, uint16_t to, uint32_t color, uint16_t wait)
{
uint16_t i;
for (i=from; i<= to; i++) // 혀를 내미는 동작
{
cdl.setPixelColor(i, color);
cdl.show();
delay(wait);
}
delay(wait);
for (i=to; i>= from; i–) // 혀를 거둬들이는 동작
{
cdl.setPixelColor(i, BLACK);
cdl.show();
delay(wait);
}
delay(wait);
}
/* twinkleFT( ) : 일정 범위의 카DL을 사이키 조명처럼 번쩍번쩍하면서 움직이도록 하는 함수
- from : from LED 번호
- to : to LED 번호
- color : 32비트 RGB 컬러 코드, 0x00RRGGBB 형태
- wait : LED 사이의 동작 간격(딜레이)
*/
void twinkleFT(uint16_t from, uint16_t to, uint32_t color, uint16_t wait)
{
uint16_t i, j;
for(j=0; j<TWINKLE_LOOP; j++)
{
for(i=from; i<=to; i=i+2) // 1개는 켜고, 그 다음 1개는 끔(BLACK)
{
cdl.setPixelColor(i, color);
if (i+1<=to)
cdl.setPixelColor(i+1, BLACK);
cdl.show();
}
delay(wait);
for(i=from; i<=to; i=i+2) // 위와 반대로, 켜진 것은 끄고(BLACK), 꺼진 것은 켬
{
cdl.setPixelColor(i, BLACK);
if (i+1<=to)
cdl.setPixelColor(i+1, color);
cdl.show();
}
delay(wait);
}
}
// 지난 회에 사용하였던 함수
// 전체가 다르게 다양한 색으로 변하면서 디스플레이하는 함수
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) {
for(i=0; i< cdl.numPixels(); i++) {
cdl.setPixelColor(i, Wheel(((i * 256 / cdl.numPixels()) + j) & 255));
}
cdl.show();
delay(wait);
}
}
// 지난 회에 사용하였던 함수
// 0~255까지의 값을 전달하면 4 바이트 컬러값을 리턴하는 함수
// 임의의 고르게 분포된 컬러값을 생성하기 위하여 사용
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 – WheelPos;
if(WheelPos < 85) {
return cdl.Color(255 – WheelPos * 3, 0, WheelPos * 3);
} else if(WheelPos < 170) {
WheelPos -= 85;
return cdl.Color(0, WheelPos * 3, 255 – WheelPos * 3);
} else {
WheelPos -= 170;
return cdl.Color(WheelPos * 3, 255 – WheelPos * 3, 0);
}
}
—————————————————-
※ 프로그램 정리 및 테스트는 한밭대학교 윤병우님이 도움을 주었습니다.
5단계 : 업로드하고 실행시키기
조금 긴 과정이었지만 스케치 프로그램 작성이 완료되었습니다. 이번에는 아두이노 UNO 이므로 업로드시 스케치 프로그램의 [보드] 선택 항목을 “UNO”로 선택하고 업로드와 실행을 진행하면 되겠습니다. 자, 원하는 대로 잘 움직이는지 살펴 볼까요? 아, 참, 여기서 한가지만 더 주의!!! 바로 전에 실행했던 [I ♥ U] 제작 시와 다르게 고려하여야 할 것 하나는 휴대폰 보조 배터리 용량입니다.
이번 [변색하는 카멜레온]의 경우는 147개의 WS2812B가 사용되므로 전류 소모량이 상당히 되므로 최소 약 2A의 전류 공급 용량을 갖는 휴대폰 보조 배터리를 사용하시기 바랍니다. LED를 켜다가 전류 용량이 부족하면 그대로 정지하거나 리셋되어 다시 처음부터 시작할 수 있습니다.
성공입니다! 발이 왔다가는 하는 동작과 혀를 날름거리는 동작도 잘 된 것 같습니다. 몸 전체 컬러를 변화시킬 때는 random() 함수를 이용하므로 루프가 반복될 때마다 새로운 색상으로 변화하므로 지루하지 않다는 장점도 있네요. 외관을 잘 다듬어서 지난번에 만든 것처럼 아크릴 판에 넣거나, 창문이나 유리판에 고정시켜 보조 간판처럼 사용하는 것이 가능할 것 같습니다. OK~
이 정도면 이제 어떤 형상, 어떤 컬러, 어떤 움직임도 시간만 주어진다면 모두 만들 수 있을 것 같은 자만심(?)도 드네요. 여러분도 상상의 나래, 창조의 나래를 펴서 자신만의 디자인과 자신만의 프로그램으로 동작하는 카DL 소품을 한 번쯤 만들어 보시기 바랍니다.
오늘 모두 수고 많으셨습니다. 다음 시간에는 [카멜레온 DIY LED 이야기]의 마지막 시간으로, [특별한 크리스마스 트리] 제작을 포함하여 생활 속에서 응용할 수 있는 재미있는 카DL 소품을 함께 만들어 보는 시간을 갖도록 하겠습니다. 좋은 하루 되시기 바랍니다. 감사합니다.