[아두이노] NeoPixel 제어

IOT/아두이노|2019. 4. 1. 09:00

[아두이노] NeoPixel 제어 


오늘의 주제는 NeoPixel로 재밌는 LED 제어에 대해서 살펴보도록 하겠습니다. NeoPoxel를 제어하기 위해서 Adafruit_NeoPixel 라이브러리를 이용하는데 별로 어렵지 않게 LED 색을 만들어 내기 때문에 재미 있는 시간이 될거라 생각됩니다. 사용되는 함수는 몇개 안되지만 그래도 상상력을 얼마나 발휘하느냐에 따라서 멋진 작품들을 만들 수 있는 부품임으로 관심을 많이 가져주세요.

1. NeoPixel


NeoPixel은 여러 종류가 있습니다. 긴 띠, 한개짜리, 링형 막대형 등 다양한 부품들이 있습니다. 가상시뮬레이터에서는 아래 그림처럼 한개짜리와 원형과 여러종류의 링을 제공하고 있네요. 다루는 것은 다 동일하니깐 간단히 다뤄보도록 하겠습니다.


NeoPixel의 핀 구조는 Vcc, Gnd 핀이 각각 두개씩 있으며 Vin과 Vout 핀으로 나눠져 있습니다. Vcc, Gnd은 NeoPixel의 전원을 담당하겠죠. Vin은 해당 NeoPixel의 들어오는 입력값이고 Vout은 해당 NeoPixel에 들어왔던 입력값 중 일부를 다음 NeoPixel로 보내는 출력핀이 됩니다. 아래 그림의 Orange 선을 보시면 됩니다. Orange 선이 신호값이 들어오고 다음 NeoPixel로 보내는 흐름선으로 생각하시면 됩니다.


예를들어, 순차적으로 1초 단위로 1,2,3 NeoPixel이 켜진다고 가정해 봅시다. 신호 값은 1,2,3번에 불이 켜지라고 명령을 내리게 됩니다. 이때 데이터값이 Orange선으로 따라서 해당 위치에 불이 들어오게 합니다. 고로, Orange선은 명령값을 전달하는 통로로 생각하시면 됩니다.


다시 종합하면, 3번까지 NeoPixe에 불이 들어오라고 명령을 내리면 그 신호 값이 1번에 불이 들어오고 2번의 Neopixel에 신호를 보내고 2번에 불이들어오고 다시 Orange선을 통해서 3번 NeoPixel에 신호값이 전달되어 3번에 불이 들어오게 됩니다. NeoPixel간의 연결은 Vout과 Vin을 연결한 통로로 신호가 전달되니깐 이 점만 잘 기억해 주세요.

2. 회로도 구성


  • 준비물 : NeoPixel Ring 12 1개, NeoPixel 6개, 아두이노우노
  • 내용 : 사용 할 NeoPixel를 간단히 연결해 보자.

대충 두종류의 NeoPixel를 Vcc, Gnd 명칭을 잘 보고 연결하시면 됩니다. 그리고 Vin, Vout은 3번핀에 연결했네요. 제 블로그에 올렸던 회로도에서 약간만 수정했네요.


주의할것은 1개짜리 NeoPixel을 연결할때 두번째 라인은 회전시켜서 배치한 거라 Vout, Vin을 잘 체크하시고 연결하셔야 합니다. 그냥 드래그해서 배치한 형태에서 두번째 라인을 Vout에서 Vout로 연결하는 실수를 하시면 안됩니다.

3. 라이브러리 추가


참조 : [아두이노] LCD16x2 I2C(LiquidCrystal_I2C) 제어
라이브러리 출처 : https://github.com/adafruit/Adafruit_NeoPixel


NeoPixel 라이브러리는 여러 종류가 있습니다. 실제로 실험하실 분은 위 링크된 참조 LCD16x2 I2C 포스트 내용중에 라이브러리 추가하는 방법이 잘 나와 있으니깐 보시고 라이브러리를 추가하시면 됩니다.

그런데 가상시뮬레이터로 하시는 분들은

#include <Adafruit_NeoPixel.h>

이 문구만 있으면 됩니다.

라이브러리 올려주신 분의 github 주소입니다. 거기 가셔서 Adafruit_NeoPixel.h, Adafruit_NeoPixel.h.cpp 파일을 꼭 보시기 바랍니다.

거기 보시면 아래와 같은 코딩들이 있습니다. 타입 설정하는데 어느정도 보셔야 합니다. 실제로 구현 하실때 왜 불이 안들어오지 의도치 않게 결과가 나오는 이유가 타입 설정 때문에 그렇습니다. 하나로 고정되어 있는게 아니라 부품에 따라서 그 타입에 맞게 설정해야지 정상적으로 동작합니다.

 Constructor: number of LEDs, pin number, LED type
 
 LED type :
 NEO_KHZ800  800 KHz datastream
 EO_KHZ400  400 KHz datastream
 
 NEO_RGB  ((0 << 6) | (0 << 4) | (1 << 2) | (2))
 NEO_RBG  ((0 << 6) | (0 << 4) | (2 << 2) | (1))
 NEO_GRB  ((1 << 6) | (1 << 4) | (0 << 2) | (2))
 NEO_GBR  ((2 << 6) | (2 << 4) | (0 << 2) | (1))
 NEO_BRG  ((1 << 6) | (1 << 4) | (2 << 2) | (0))
 NEO_BGR  ((2 << 6) | (2 << 4) | (1 << 2) | (0))
 NEO_RGBW
 ...
 NEO_WRGB 
 ...
 

다른 함수들도 꼭 보시고 대충 어떤 느낌으로 흘러가는지만 살펴보세요. 나중에 색을 세팅하는 함수에서 위에 나와있는 RGB라는 글자들이 보이시죠. 위치를 나타냅니다. 색을 세팅하는 함수는 같지만 해당 위치의 인자값은 달라지게 됩니다. RGB 인자를 순서대로 넣었는데 처음 세팅을 BGR로 해버렸다면 코딩하는 사람은 RGB라고 생각하고 색 값을 넣었지만 색 세팅함수에서는 BGR로 인식해버릴 수 있으니깐 잘 살펴보셔야 해요. 그리고 함수명들만 헤더 파일에 어떤게 있는지만 한번 살펴봐 주세요.

4. 코딩


  • 사용함수 : Adafruit_NeoPixel(), neopixel.begin(), neopixel.setPixelColor(), neopixel.show(), neopixel.clear()
  • 내용 : 간단히 순차적으로 NeoPixel에 불이 들어오게 하자.
  • 참고소스 : [아두이노] 3x3x3 CUBE LED 제어 III

함수

  • Adafruit_NeoPixel(NeoPixel수, NeoPixelPin, NEO_GRB + NEO_KHZ800) : 생성자함수로 NeoPixel 클래스 객체를 만들때 사용합니다. 몇개의 NeoPixel를 사용하고 어느 핀을 사용할지와 Neopixel 타입을 설정을 하는 함수입니다. 우선 가상시뮬에이터는 이 값을 기본으로 사용하세요.
  • neopixel.begin() : 라이브러릴 사용하면 꼭 객체 시작을 알리는 함수가 있죠. 이것도 마찬가지입니다. 사용하겠다고 선언.
  • neopixel.setPixelColor(위치, R, G, B) : 색을 나타냅니다. 위와 같은 Neopixel 타입을 설정했을때 RGB의 위치는 이와 같이 결정됩니다. 참고로 타입이 바뀌면 색상 위치도 바뀌니깐 햇갈리지 마세요. 쉽게말해서, 색을 세팅하는 함수입니다.
  • neopixel.show() : 색이 세팅한 값을 실제로 보여주라는 함수입니다. Orange선을 통해서 해당 위치에 색이 켜지겠지요.
  • neopixel.clear() : 지금까지 켜진 NeoPixel를 초기화하는 함수입니다. 켜진 NeoPixel를 다 꺼지겠지요.
    참고로 clear()함수로 명령을 내렷다고 해서 NeoPixel에 들어온 불이 꺼지지는 않습니다. 내부적으로 세팅한 setPixelColor()함수의 값만 초기화 될 뿐이죠. 내부적으로 초기화 된 값에서 show()함수를 실행 시켜야 초기화된 상태로 NeoPixel이 꺼지게 됩니다. ( "왜! 안꺼져! 이런 실수를 안하셨으면 해요!")

설계

NeoPixel 라이브러리를 사용하니깐 사용할 객체를 선언해야 합니다. 한개짜리 6개와 12개짜리 링 한개로 총 18개의 NeoPixel를 제어하니깐 아래와 같이 선언하시면 되겠습니다.

const byte neopixelPin = 3;
Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(18, neopixelPin, NEO_GRB + NEO_KHZ800);

순차적으로 NeoPixel로 불이 들어와야 하니깐 18개NeoPixel 기준으로 for문 한개를 사용하여 18번 반복하면 되겠죠.

for(int i=0;i<18;i++){
   NeoPixel i에 불이 들어오게하라;
}

이 로직으로 대충 돌아가야 겠죠. NeoPixel 함수는 불이 들어올려면 색을 세팅하고 그 세팅값을 NeoPixel로 보내야 합니다.

setPixelColor()함수로 색을 정하고, show()함수로 출력하면 됩니다.

  for(int i=0;i<24;i++){
    neopixel.setPixelColor(i, 255, 0, 0);    
    neopixel.show();
    delay(100);    
  } 

대충 이렇게 코딩 됩니다. i번째 위치 NeoPixel에 RGB에서 R(255)로 Red색으로 세팅하고 show()함수로 해당 위치에 NeoPixel에 불이 들어오게 됩니다. 그렇게 어렵지 않죠. NeoPixel 라이브러리로 간단히 해당 위치에 원하는 색으로 불이 들어오게 하는 함수가 이 두 함수입니다. 어떻게 로직을 짜냐에 따라서 재밌는 패턴이 만들어 지고 화려하게 불이 들어오게 할 수 도도 있게 됩니다.

딜레이는 빠르게 보기 위해서 0.1초로 했네요. 가상시뮬레이터에는 지연렉이 좀 있기 때문에 좀 빠르게 보기 위한 값이니깐 실험할 때는 원하는 시간 간격으로 돌려보세요.

그리고, 시작은 begin()함수를 사용하고 초기화는 clear()함수를 사용합니다. 꺼먹지 마세요. 그리고 clear()함수 명령을 내렸는데 왜 NeoPixel이 안꺼지지 하고 혼동하시는 분이 있는데요. 무조건 Neopixel에 명령을 보내는 것은 show()함수 입니다. 내부적으로 clear()함수로 초기화 되었어도 출력된 NeoPixel은 초기화 되지 않습니다. show()함수로 같이 쓰시면 외부의 NeoPixel까지 초기화 된다는 점을 꼭 기억해주세요.

전체적으로 코딩을 하면,

#include <Adafruit_NeoPixel.h>

const byte neopixelPin = 3; 
Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(18, neopixelPin, NEO_GRB + NEO_KHZ800);

void setup() {
  neopixel.begin();  
}

void loop() {  
  for(int i=0;i<18;i++){
    neopixel.setPixelColor(i, 255, 0, 0);    
    neopixel.show();
    delay(100);    
  } 
  neopixel.clear(); 
  neopixel.show();
  delay(100);    
}

5. 결과




오늘은 회로도 만드는 것이 간단하니깐 전과정을 기록해 봤네요. 그리고 결과는 Red 색 하나만 순차적으로 불이 들어오게 하면 좀 그러니깐 R->G->B순으로 불이 들어오게 가상시뮬레이터에서 돌려봤네요. 어떤 결과가 나오는지 동영상을 꼭 확인 해보세요. 아니면 공개 회로도에 링크된 곳에 가셔서 가상시뮬레이터를 직접 돌려보세요.


마무리


진짜 오늘 배운 부품 소재는 재맸는 소재입니다. 아마도 한번은 보셨을지 모르겠네요. 클럽에 네온싸인 같은 것이나 할로윈 축제때 어떤 사람을 보면 몸에서 야광 LED가 깜박이는 것들을 보셨을꺼에요. 유튜브를 검색을 하시면 NeoPixel로 모니터를 만들어서 동영상을 감상하시는 분도 있고 연주가들은 악기에 붙여서 휘황찬란하게 표현하는 분도 있고 찾아보시면 스케일들이 남다른 분들의 영상물들을 많이 보실 수 있을 꺼에요. 아마도 실제로 구매해서 만들고 싶은 충동이 느껴지실 거라고 생각됩니다. 그런데 개당 가격이 좀 비싼편이라서 약간 구매해서 실험하기는 애매한 점도 있습니다. 우리에게는 가싱시뮬레이터가 있고 그걸 통해서 대리 만족을 느끼면 됩니다.

오늘은 간단한 동작으로만 채웠습니다. 그 이유는 여러분들의 상상력을 발휘할 시간을 주기 위해서 입니다. 다양한 표현을 시도해 보세요. 여러분들은 NeoPixel로 난 무엇을 만들어 볼까? 무엇을 만들 수 있을까? 계속 자신에게 질문을 던져주세요. 그리고 순차적으로 출력되는 저 for문을 가지고도 다양한 표현을 할 수 있습니다. setPixelColor()함수와 show()함수의 의미와 동작원리를 곰곰히 잘 생각해보시면 for문 한개로도 꽤 다양한 패턴을 만드실 수 있으니깐 꼭 동작 원리를 이해해 주세요.


댓글()