본문 바로가기

프로젝트/블루투스 무드등

[비전공자도 만들 수 있는 블루투스 무드등] 2. 아두이노 코딩 part 1-설치 및 예제

안녕하세요? 닉네임간편입니다.

저번 시간에는 아두이노와 LED를 연결하여 동작하기 이전의 모습까지 만들어봤습니다. 이번 시간에는 본격적인 코딩을 하기에 앞서 몇 가지 준비를 하고, LED 스트립 예제를 통해 실제로 LED를 제어하는 것까지 해보겠습니다.

1. 아두이노 IDE 설치

먼저 코딩을 위해 아두이노 IDE를 설치해야 합니다. 아래 사이트에 접속해서 운영체제에 맞는 프로그램을 설치하시면 됩니다.

 

https://www.arduino.cc/en/software

 

Software

Open-source electronic prototyping platform enabling users to create interactive electronic objects.

www.arduino.cc

 

설치가 다 되었다면 스케치를 실행합니다.

먼저 툴 -> 보드에 들어가서 사용하고 있는 보드를 설정합니다. 저는 아두이도 우노를 사용하고 있으므로 Arduino Uno를 선택해서 보드를 설정했습니다.

다음으로 포트를 설정합니다. 먼저 아두이노를 컴퓨터에 연결합니다. 이후 스케치에서 툴 -> 포트로 들어가 사용하고 있는 아두이노가 있는 포트를 선택합니다.

 

보드와 포트 설정

이제 모든 준비는 마쳤습니다. 자유롭게 코딩을 통해 원하시는 제품을 만들 수 있게 된 겁니다.

 

 

2. 함수 설명

본격적으로 코딩을 하기에 앞서, 간단하게 아두이노 스케치 내부에 있는 함수에 대해 설명드리겠습니다.

 

아두이노 스케치 화면

void setup()


setup() 함수는 스케치가 시작할 때 호출되며 변수나 핀 모드 등을 초기화하고 라이브러리 사용을 시작할 수 있습니다.

호출한다는 것은 말 그대로 이해하시면 됩니다. 예를 들어 강혁이라는 아이에게 일을 시킬 때 강혁이의 이름을 불러서 일을 시키는 것처럼, IDE에서도 함수 이름을 불러서 일을 시키는 것이라고 이해하시면 됩니다.
즉, setup()이라고 적는 것은 함수의 이름을 불러서 일을 시키려고 하는 것이고, 중괄호 {} 안에 적는 내용은 구체적으로 시킬 일을 의미합니다.

 

예를 들어서 강혁이에게 운동장 한 바퀴를 달리라는 일을 시키겠습니다. 강혁이는 머리가 좋아 어떤 속도로 달려야 할지, 보폭은 어떻게 해야 하는지 모두 스스로 판단해서 달릴 수 있습니다. 그러나 컴퓨터는 이 모든 것들을 다 알려주어야 합니다. 이때 컴퓨터에게 속도, 보폭 등은 한 번만 알려주면 계속해서 해당 속도, 보폭을 반복할 것입니다. 따라서 이것들을 초기에 알려주는 역할을 하는 것이 바로 setup() 함수라고 이해하시면 되겠습니다.

setup() 함수는 아두이노의 전원을 켜거나 리셋한 후 한 번만 실행됩니다.

 

 

void loop()


다음으로 loop() 함수입니다. loop 함수는 말 그대로 중괄호 {} 안에 적혀있는 내용을 반복하는 함수입니다.
앞선 예제를 다시 이용하자면, 강혁이가 운동장 한 바퀴를 달리려면 앞발을 한 번만 내딛으면 안 될 것입니다. 계속해서 앞 발과 뒷 발을 반복적으로 내딛으면서 달려야 할 것입니다. 이처럼 필요한 동작을 반복하면서 원하는 기능을 수행하도록 하는 것이 loop 함수입니다.


LED 불빛이 계속 빛나기 위해서도 해당 동작을 반복해야 합니다. 따라서 기능적인 부분은 loop 함수에 적는다고 보시면 됩니다.

 

이제 함수에 대한 기본적인 개념을 알아보았으니 LED 스트립 예제를 통해 실제로 사용해보겠습니다.



3. LED 스트립 예제

LED 스트립 예제를 사용하기에 앞서, 네오픽셀 라이브러리를 아두이노 스케치에 추가하셔야 합니다.

먼저 스케치 -> 라이브러리 포함하기 -> 라이브러리 관리에 들어갑니다.

 

라이브러리 관리 창

검색창에 'Adafruit NeoPixel'를 검색하고, 빨간색 네모로 표시된 곳의 설치 버튼을 눌러 설치합니다.(저는 이미 설치가 되어있어서 INSTALLED라고 뜹니다

 

네오픽셀 라이브러리 설치

 

 

설치가 다 되었다면 파일 -> 예제 -> Adafruit NeoPixel -> standtest_wheel을 선택하시면 되겠습니다. 물론 어떤 예제를 선택하셔서 자유롭게 응용하셔도 좋습니다.

 

 

 

해당 예제에는 많은 내용이 있지만, 지금은 rainbow() 함수만 사용하겠습니다.
필요한 부분만 간추린 전체 코드는 다음과 같습니다.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(50);
  strip.show();
}

void loop() {
  rainbow(20);
}

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);
  }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

지금부터 코드 예제에 대해 순서대로 설명하겠습니다.

 

1. 변수 정의

#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, PIN, NEO_GRB + NEO_KHZ800);

 

#define 은 변수에 이름을 붙여 정의하는 것입니다. #define A B라고 한다면 B를 A라고 부른다고 생각하시면 됩니다. 여기선 6번 핀을 PIN이라고 정의합니다.

 

Adafruit_NeoPixel() 함수는 총 3개의 파라미터를 전달받습니다. 쉽게 설명하자면 함수가 기능을 수행하는 데 있어 3가지 설정을 한다고 보시면 됩니다.

 

첫 번째로 4는 LED 개수를 의미하며, 제가 구매한 LED 스트립은 4개이므로 4로 설정했습니다. 만일 여러분이 구매한 LED 스트립의 개수가 4개가 아니라면 해당 개수를 적어주시면 됩니다.

 

두 번째로 PIN은 아두이노와 연결된 핀의 번호입니다. 앞선 시간에 LED 스트립의 입출력을 담당하는 선(노란색 선)을 6번 핀에 연결하였으므로, 여기선 6을 지정해줍니다. 그런데 이때 앞서 6을 "PIN"이라고 이름 붙이기로 하였으므로, PIN으로 적습니다.

 

세 번째는 네오픽셀의 유형에 관계된 것인데, 이는 사실 지나치셔도 무방합니다. 만일 NEO_GRB, NEO_KHZ800과 다른 유형의 네오픽셀을 사용한다면 다르게 입력해야 하지만, 대부분의 네오픽셀은 다르게 입력하지 않아도 될 것입니다.

 

 

2. setup 함수

void setup() {
  strip.begin();
  strip.setBrightness(50);
  strip.show();
}

 

setup() 함수는 앞서 설명했듯 변수를 초기화하거나 라이브러리 사용을 시작하는 함수입니다.

strip.begin()을 통해 동작을 시작한다는 것을 명시합니다. 즉, 이제 스트립을 사용할 준비를 하도록 하는 함수입니다.

strip.setBrightness(50)은 LED 스트립의 밝기를 설정합니다. 밝기는 0~255까지 값이 있으며 지금은 50을 설정합니다.

strip.show()는 스트립 객체에, 즉 LED에 밝기, 색상 등의 정보를 전달하는 역할을 합니다.

쉽게 설명드리자면, 이 함수를 호출함으로써 LED에 불빛이 나게 됩니다.

 

조금 명확히 설명하자면, show 함수는 색상, 밝기 등의 데이터를 스트립 객체에 전달하고, 이를 업데이트하는 함수입니다.

이 예제에서 setBrightness 함수를 통해 스트립의 밝기 정보가 생성되었습니다. 그리고 show 함수를 통해 해당 밝기 정보가 스트립 객체, 즉 LED로 전달되었습니다. 그러나 아직 색상에 대한 정보가 생성되어 전달되지 않았으므로, LED는 아직 빛나지 않고 전원이 꺼진 상태로 초기화가 됩니다.

이렇게 전원이 꺼진 상태로 초기화가 되도록 하는 건 setup 함수 내에서 처음 호출된 show 함수가 하는 역할입니다.

 

show 함수는 이후에도 호출됩니다. 해당 설명은 그때 설명하겠습니다.

 

 

3. loop 함수

void loop() {
  rainbow(20);
}

 

loop() 함수는 안에 동작을 반복하는 함수입니다. 현재 rainbow()이라는 함수를 반복하도록 설정했습니다.

 

 

4. rainbow 함수

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);
  }
}

 

rainbow 함수는 말 그대로 무지갯빛처럼 LED 스트립이 표현할 수 있는 색을 순서대로 표현하는 함수입니다. 

unit8_t, unit16_t는 int 형의 타입을 재정의한 것으로, 각각 8bit, 16bit의 자료형을 나타냅니다.
아두이노는 컴퓨터이지만 일반적인 데스크톱이나 스마트폰과 달리 메모리가 제한되기 때문에 최적화에 신경 써주어야 합니다. 따라서 일반적인 자료형을 사용하기보단 이런 식으로 사용함으로써 메모리를 더 효율적으로 사용할 수 있습니다.
자료형에 대한 이야기는 다음 시간에 하고, 지금은 단지 더 효율적인 사용을 위해 unit8_t와 같은 것들을 사용한다고 이해하시면 되겠습니다.

 

for로 시작하는 구문은 반복문으로, 세미콜론을 기준으로 초기식;조건식;증감식으로 구성되어있습니다.

초기식은 변수를 초기화하는 것으로, for문이 처음 등장할 때 j=0 은 j변수를 0으로 설정하겠다, 0으로 초기화하겠다는 것입니다.

조건식은 이 조건이 만족하는 동안에는 계속해서 for문 안에 내용을 반복한다는 것입니다. j <256 조건식은 j변수가 256보다 작다면 내용을 계속 반복한다는 것입니다.

증감식은 변수를 증감하는 것입니다. 예를 들어 j변수는 처음에 0으로 설정되었고, 이 값이 변하지 않는다면 조건 j <256에 만족하기 때문에 영원히 반복할 것입니다. 이를 막기 위해 증감식을 통해 j의 값을 증가하거나 감소시켜 반복문이 무한 반복하는 것을 막을 수 있습니다. 여기선 j++이라고 했고, 이는 간단히 말해 j의 값을 1씩 증가시킨다고 보면 되겠습니다.

 

여기에 등장한 for문은 for문 안에 for문이 있는 중첩 for문입니다. 처음 등장한 for문을 첫 번째 for문이라 하고, 두 번째 등장한 for문을 두 번째 for문이라 하겠습니다.

두 번째 for문이 의미하는 바는 스트립의 LED 개수만큼(numPixels) 색상을 지정하겠다는 것입니다.

그리고 첫 번째 for문이 의미하는 바는 0부터 255까지의 표현할 수 있는 색을 모두 표현하겠다는 것입니다.

저의 경우 총 4개의 LED에 색상을 모두 지정하는 것이 두 번째 for문의 역할이며, 0부터 255까지의 색을 '4개의 LED'에 모두 표시하는 것이 첫 번째 for문의 역할입니다.

 

strip.show();
delay(wait);

 

이후에 show() 함수를 통해서 색상과 밝기 데이터를 스트립 객체로 전달합니다. 그리고 이 상태를 업데이트하여 해당 색상과 밝기 데이터에 의거해 LED 불빛이 나도록 합니다.

이때 만일 show 함수를 호출하지 않는다면 색상과 밝기 데이터가 즉각적으로 업데이트되지 않습니다. 따라서 앱에서 색상을 변경하였더라도 이것이 즉각적으로 반영되지 않고, 제대로 작동하지 않는 것처럼 보일 수 있습니다. 따라서 이를 방지하기 위해선 show 함수를 꼭 호출하는 것이 좋습니다.

 

delay() 함수는 어떤 동작을 수행한 이후 일정 시간을 기다리도록 하는 함수입니다.

현실 세계는 디지털 세상처럼 갑자기 사라지거나 갑자기 나타나지 않고 부드럽게, 유연하게 사물이 움직이거나 동작합니다. 마찬가지로 이러한 동작을 하기 위해 갑자기 사라지거나 갑자기 동작하지 않고 일정 시간 텀을 두고 동작을 할 수 있도록 하는 것입니다.

 

delay() 함수 안에는 밀리세컨드 단위로 입력하며, 1초를 멈춘 다음에 동작하도록 하고 싶다면 delay(1000)이라고 입력하면 됩니다. 1초는 1000밀리 세컨드이기 때문입니다.

void rainbow(uint8_t wait) {
	// 중략
	delay(wait);
	// 중략    
}

void loop() {
  rainbow(20);
}

이 부분을 보면 rainbow 함수는 wait 이라는 파라미터를 전달받고, loop 함수에선 20이라는 숫자를 전달받았습니다. wait 은 delay() 함수에 전달되어 동작이 잠깐 멈출 시간을 정의하며, 이 예제에선 20 밀리세컨드만 멈추었다가 다시 동작을 수행한다고 이해하시면 되겠습니다.

만일 시간을 조금 더 멈추게 하고 싶으시다면 loop 함수 내에서 rainbow(1000) 이런 식으로 숫자를 조정하시면 되겠습니다.

 

그런데 예제에 등장한 Wheel 함수에 전달된 파라미터는 일반적으로 보이는 것과 다릅니다.

strip.setPixelColor(i, Wheel((i+j) & 255));

이 예제에서 Wheel 함수에 파라미터로 전달된 값은 (i+j) & 255 입니다.

프로그래밍에서 &는 '그리고', 'AND' 라는 의미입니다. 이 부분에선 해당 의미가 비트 AND 연산자로 사용되었습니다. 비트연산에 대해선 여기서 전부 설명드릴 수 없으므로, 추후 다른 글을 통해 설명드리겠습니다.

여기선 단지 저런 수식처럼 표현된 것이 파라미터로 전달되었다라고 이해하시면 되겠습니다.

 

 

5. Wheel 함수

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

 

Wheel 함수는 LED 픽셀 하나의 RGB 색상을 지정하는 함수입니다.

색상 코드를 보면 아시겠지만 색은 빨간색, 파란색, 초록색을 혼합하여 표현됩니다. 그리고 Color 함수도 순서대로 빨간색, 파란색, 초록색이 얼마나 포함되는지를 나타냅니다.

즉, strip.Color(빨간색이 포함되는 정도, 파란색이 포함되는 정도, 초록색이 포함되는 정도)로 이해하시면 되겠습니다.

if 조건문을 통해 WheelPos 값에 따라서 색상을 다르게 지정합니다.

 

 

 

이제 업로드를 누르면 다음과 같은 결과가 나옵니다. 업로드는 오른쪽 화살표 버튼을 클릭하시면 됩니다.

업로드

 

LED 스트립 예제 결과

시각적 편의를 위해 미리 만들어놓은 판데기?를 씌워놓았습니다. 이건 추후에 3D 프린팅에 관련된 글을 포스팅할 때 자세히 보여드리겠습니다.

 

4. 마무리

이번 시간에는 아두이노 IDE 설치 및 LED 스트립 예제에 대해 알아보았습니다. 다음 시간에는 본격적으로 스마트폰과의 블루투스 연동을 위해 코딩을 직접 해보겠습니다.

오늘 알려드렸던 정보가 많은 도움이 되었기를 바랍니다.

728x90
반응형