본 포스트에서는 사용자 라이브러리를 작성하는 방법을 예제로 설명하도록 하겠다. 다음과 같이 간단한 LED로 모르스 부호를 표시하는 스케치 프로그램으로 시작한다.
int pin = 13; void setup() { pinMode(pin, OUTPUT);} void loop() { dot(); dot(); dot(); dash(); dash(); dash(); dot(); dot(); dot(); delay(3000);} void dot() { digitalWrite(pin, HIGH); delay(250); digitalWrite(pin, LOW); delay(250);} void dash() { digitalWrite(pin, HIGH); delay(1000); digitalWrite(pin, LOW); delay(250);} |
이것을 업로드하여 실행하면 내장 LED로 SOS신호를 3초 간격으로 반복하여 생성한다.
이 프로그램에서 dot() 함수와 dash()를 라이브러리로 빼내서 만들어보도록 하겠다. 여기서는 내장 LED를 사용하였지만 라이브러리에는 LED가 연결한 핀을 생성자에서 지정할 수 있도록 할 것이다. 생성자 안에서는 pinMode()함수를 호출하여 지정된 핀을 출력으로 지정하도록 한다. 이제 변환을 시작해 보자.
아두이노 라이브러리는 보통 두 개의 파일이 필요하다. 헤더 파일(.h 파일)에는 라이브러리에서 제공하는 클래스와 변수 등의 선언이 위치한다. 클래스 멤버함수 등의 실제 코드는 .cpp 파일에 작성하면 된다. 이렇게 작성해 놓으면 만약 다른 사용자가 이 라이브러리를 참고할 때에는 헤더 파일만 보면 될 것이다. 다른 사용자가 굳이 보지 않아도 되는 실제 코드 부분은 다른 파일로 분리시켜서 가독성을 향상시키는 것이다.
헤더파일의 핵심은 다음과 같은 클래스 선언 부분이다.
class Morse { public: Morse(int pin); void dot(); void dash(); private: int _pin;}; |
클래스에는 사용되는 함수와 변수의 선언이 있으며 외부에서 호출해야 하는 함수는 public 으로, 외부에 굳이 노출시킬 필요가 없는 함수/변수는 private 으로 선언한다. 클래스에는 생성자(constructor)라는 것이 있는데 이것은 클래스의 인스턴스가 생성되는 시점에서 호출되는 함수이다. C++의 생성자는 클래스와 이름이 같으며 출력형식은 지정해주지 않는다.
헤더파일을 작성할 때 추가로 고려해야 되는 사항이 있는데 먼저 아두이노의 표준 함수들을 사용하기 위해서 다음과 같이 Arduino.h 헤더파일을 인클루드시켜야 한다. 이 헤더는 스케치파일의 경우 자동으로 인클루드되므로 별도로 작성할 필요는 없지만 라이브러리 파일의 경우에는 명시적으로 다음과 같이 포함시켜야 한다.
또한, 전체 헤더파일을 다음과 같은 전처리문으로 둘러싸주는 것이 필요하다.
#ifndef Morse_h#define Morse_h // the #include statment and code go here... #endif |
이것은 C++에서 특정 헤더파일은 중복해서 인클루드되는 것을 방지하는 일반적인 방법이므로 이해가 가지 않아도 상관없지만 관련 부분을 검색에서 한 번 숙지하기를 권한다.
마지막으로 주석문을 이용하여 라이브러리에 대한 간단한 설명을 헤더 파일 머리에 작성해주는 것이 좋다. 여기에는 보통 보통 작성자, 날짜, 버전, 라이센스에 대한 정보를 기록한다. 이러한 고려사항들을 모두 적용하면 헤더 파일은 다음과 같은 모양을 가질 것이다.
/*Morse.h - Library for flashing Morse code.Created by David A. Mellis, November 2, 2007.Released into the public domain.*/#ifndef Morse_h#define Morse_h #include "Arduino.h" class Morse { public: Morse(int pin); void dot(); void dash(); private: int _pin;}; #endif |
이제 실제 코드가 위치하는 .cpp 파일의 작성법에 대해서 알아보자. 이 파일은 Arduino.h 와 방금 작성한 Morse.h 파일을 처음에 인클루드해야 한다.
#include "Arduino.h"#include "Morse.h" |
그 다음 생성자를 작성한다. 이 생성자는 클래스 인스턴스를 생성할 때 호출되므로 여기에서 pinMode()함수를 호출하여 사용자가 지정한 핀을 출력으로 설정하는 것이 좋다.
Morse::Morse(int pin) { pinMode(pin, OUTPUT); _pin = pin;} |
함수명 앞의 Morse:: 는 이 함수가 Morse라는 클래스의 멤버함수라는 것을 지정한다. 이 클래스의 다른 함수들을 정의할 때에도 같은 문법이 적용된다. 그리고 private 변수 _pin에서 맨 앞의 _은 이 변수가 private 변수라는 것을 관례적으로 표시하는 방법이며 또한 함수의 입력 인수 pin과도 구별시켜주는 역할을 한다.
그 다음으로 원래의 스케치 파일에서 가져온 dot()함수와 dash()함수를 정의하면 된다. 이 함수의 내부에서는 스케치 파일과 다르게 클래스의 멤버 변수 _pin을 사용한다.
void Morse::dot() { digitalWrite(_pin, HIGH); delay(250); digitalWrite(_pin, LOW); delay(250);} void Morse::dash() { digitalWrite(_pin, HIGH); delay(1000); digitalWrite(_pin, LOW); delay(250);} |
또한 간단한 설명을 담고 있는 주석문을 파일 서두에 포함시키는 것이 좋다. 전체 .cpp 파일은 다음과 같다.
/*Morse.cpp - Library for flashing Morse code.Created by David A. Mellis, November 2, 2007.Released into the public domain.*/ #include "Arduino.h"#include "Morse.h" Morse::Morse(int pin) { pinMode(pin, OUTPUT); _pin = pin;} void Morse::dot() { digitalWrite(_pin, HIGH); delay(250); digitalWrite(_pin, LOW); delay(250);} void Morse::dash() { digitalWrite(_pin, HIGH); delay(1000); digitalWrite(_pin, LOW); delay(250);} |
이것으로 라이브러리의 작성은 끝났으며 이 파일들은 {내문서}\Arduino\libraries\MyLib 폴더에 위치하여야 아두이노 하프가 인클루드시킬 수 있다. 먼저 {내문서}\Arduino\libraries 밑에 Morse 폴더를 생성한 후 이 두 파일을 그 안에 복사해서 넣으면 된다. 폴도의 구성도를 그려보면 다음과 같다.
[그림 1] Morse 라이브러리의 폴더 구조
이제 아두이노 IDE를 재실행시키면 Sketch>Include library 메뉴의 하위에 Morse 항목이 새로 생긴 것을 확인할 수 있을 것이다.
[그림 2] 생성된 Morse 라이브러리
주의할 점은 헤더 파일과 본체 파일 모두 이름이 속한 폴더와 같아야 한다는 것이다. 그리고 확장자는 정확하게 .h와 .cpp 이어야 한다.