이전 포스트에서 작성한 라이브러리를 스케치에서 사용하는 방법을 알아보자.

#include <Morse.h> //라이브러리 인클루드
Morse morse(13);
void setup() {
}
void loop() {
   morse.dot(); morse.dot(); morse.dot();
   morse.dash(); morse.dash(); morse.dash();
   morse.dot(); morse.dot(); morse.dot();
   delay(3000);
}

이 파일은 원래의 스케치파일과 비교하여 몇 가지 다른 점이 있다. 먼저 라이브러리를 인클루드하기 위해서 #include <Morse.h>를 서두에 추가한 것이다. 이것으로 라이브러리에서 정의된 클래스를 이용할 수 있다. 두 번째로 클래스의 인스턴스를 다음과 같이 생성한다는 것이다.

Morse morse(13);

이것이 실행되면 Morse 클래스의 생성자가 실행되며 13이라는 핀번호를 넘겨주게 된다. 이 생성자 안에서 pinMode()함수를 실행했으므로 setup() 함수에서는 그럴 필요가 없다. 그리고 dot(), dash() 함수를 호출하기 위해서는 이 클래스 인스턴스를 매개로 해야 한다. 예를 들어서 13번 핀과 12번 핀에 LED가 연결되어 있다면 다음과 같이 하면 된다.

Morse morse(13);
Morse morse2(12);


멤버 함수 하이라이트 기능

 만약 아두이노 IDE를 사용한다면 추가로 keyword.txt 파일을 만들어서 하이라이트될 함수명을 지정해 줄 수 있다.


Morse KEYWORD1
dash KEYWORD2
dot KEYWORD2

 

각각의 줄은 함수명과 탭구분자 그리고 KEYWORD1/KEYWORD2 라는 지정어가 와야 한다. KEYWORD1은 클래스명을 지정하며 KEYWORD2 는 멤버함수임을 지정한다.

예제 파일 제공

 만약 다른 사용자들의 편의를 제공하기 위해서 예제를 제공하고 싶다면 Morse 폴더 밑에 examples 폴더를 생성한 후 그 안에 각각의 예제를 위한 폴더들을 만들고 그 안에 예제파일을 두면 된다. 이 예제들은 아두이노 IDE의 파일>예제 메뉴에 자동으로 나타난다.

#ifndef ~ #endif 전처리문의 이해

 동일한 헤더 파일(.h 파일)을 중복해서 선언하면 문법적으로 오류를 발생하게 되어 있다. 예를 들어서 MyLib.cpp 파일에서

#include “MyLib.h”
#include “MyLib.h”
....

와 같이 중복선언을 한다면 컴파일러 오류가 발생할 것이다. 사용자가 이런 식으로 작성하는 경우는 거의 없겠지만 개발자의 의도와 관계없이 이런 경우가 발생할 수도 있다. 예를 들어서 a.h 에서 b.h 를 인클루드 했는데 a.cpp 파일에서 이를 간과하고 a.h 와 b.h 둘 다 인클루드 했다면 결과적으로 b.h 는 두 번 포함되는 것이다.


 이 문제는 #ifndef _상수 ~ #endif 전처리문으로 회피할 수 있다. 전처리문은 컴파일이 수행되기 이전에 처리되며 이것의 동작은 이것으로 묶인 부분이 컴파일에 포함되려면 ‘_상수’ 가 정의되지 않은 상태여야 한다.(if not defined 가 조합된 명령어가 #ifndef 이다.)

해결책은 이전 포스트에서 언급한 바와 같이 헤더 파일 전체를 다음과 같이 이 전처리문으로 묶는 것이다.

#ifndef MYLIB_H
#define MYLIB_H
class MyLib {
   ...
};
#endif

이제는 MyLib.h 헤더파일을 아무리 중복해서 인클루드해도 오류가 발생하지 않는다. 그 원리는 맨 처음 인클루드 명령에서는 MYLIB_H라는 상수가 정의되지 않았기 때문에 #ifndef ~ #endif 안의 프로그램이 수행되는데 그 안에서는 MYLIB_H 상수가 정의된다. 즉 맨 처음 이 구문이 포함될 때 상수 MYLIB_H가 정의되므로 만약 중복되서 인클루드되는 경우가 발생하더라도 두 번째 부터는 #ifndef ~ #endif 안의 프로그램이 포함이 되지 않는 것이다.

 결과적으로 맨 처음에 수행되는  #include “MyLib.h” 문만 처리되며 그 이후의 중복되는 #inclde 명령은 처리되지 않게 되어 MyLib 클래스의 선언부가 한 번만 확장된다.



Posted by 살레시오

 본 포스트에서는 사용자 라이브러리를 작성하는 방법을 예제로 설명하도록 하겠다. 다음과 같이 간단한 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 헤더파일을 인클루드시켜야 한다. 이 헤더는 스케치파일의 경우 자동으로 인클루드되므로 별도로 작성할 필요는 없지만 라이브러리 파일의 경우에는 명시적으로 다음과 같이 포함시켜야 한다.

#include "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 이어야 한다.



Posted by 살레시오

 본 포스트에서는 인터넷으로 내려 받은 사용자 라이브러리를 설치하는 방법과 직접 라이브러리를 작성하는 방법에 대해서 좀 더 자세히 설명하도록 하겠다.

 아두이노 IDE를 설치하면 {내문서}\Arduino\libraris 폴더가 생성되고 여기에 다운로드 받은 라이브러리를 복사하거나 사용자가 직접 작성한 라이브러리를 저장한다. 컴파일을 수행할 때 이 폴더는 자동으로 인클루드되어서 여기에 있는 라이브러리들이 링크된다.

 라이브러리는 기본적으로 폴더 단위로 저장되어야 한다. 예를 들어서 MyLib 라는 이름으로 (보통 라이브러리명은 대문자로 시작한다.) 라이브러리를 작성한다면 {내문서}\Arduino\libraris 폴더 밑에 MyLib라는 폴더가 있어야 하고 이 폴더 밑에 MyLib.h 헤더 파일과 MyLib.cpp 파일이 있어야 한다. 만약 예제 파일을 제공하고 싶다면 example 폴더 밑에 예제 파일의 이름과 같은 폴더를 두고 그 밑에 .ino 파일을 위치해 두어야 한다. 이를 도시하면 다음과 같다.


[그림 1] 윈도에서 아두이노 라이브러리 폴더의 구조

보통은 라이브러리는 클래스나 변수 등을 선언한 헤더 파일(.h)과 클래스 멤버함수의 정의부가 있는 .cpp 파일로 나뉜다. 그리고 헤더 파일에는 MyLib 클래스가 선언되어 있어야 한다. 보통은 헤더 파일과 본체 파일(.cpp 파일)로 나뉘지만 모든 선언과 정의를 헤더 파일에 둘 수도 있다. 하지만 헤더 파일에는 클래스의 선언부를 작성하고 그것을 구현한 cpp파일을 별도로 두는 것이 더 일반적이고 바람직하다. 이렇게 구성하면 이 라이브러리를 사용하는 스케치파일에서는 헤더 파일만 인클루드해서 사용할 수 있고, 여러 곳에서 중복해서 사용할 경우에도 헤더 파일만 인클루드 하면 되기 때문이다


 아두이노 홈페이지(http://arduino.cc/en/Reference/Libraries)에서 다양한 아두이노의 라이브러리에 대해서 설명하고 있다. 사용자는 여기에서 필요한 라이브러리를 다운로드 받아서 설치할 수 있다. 예를 들어서 OneWire 라는 라이브러리를 다운로드 받았다고 하자. 그러면 다운로드 폴더에 OneWire.zip 파일이 다운로드 되어 있을 것이다. 이 압축파일에는 OneWire.h, OneWire.cpp 파일이 들어 있다. 이 경우 이 압축파일을 이용하여 바로 사용자 라이브러리 폴더에 복사할 수 있는데 다음과 같이 Sketch>Include library > Add .ZIP Library 메뉴를 이용하여 압축파일을 선택해 주면 된다.

[그림 2] 아두이노 IDE의 라이브러리 관리 메뉴

이 메뉴를 선택한 후 OneWire.zip 파일을 선택하면 자동으로 사용자 라이브러리 폴더에 압축이 해제되서 복사해 들어가게 된다.

 OneWire.zip 파일은 다운로드 받은 압축파일에 필요한 라이브러리 파일이 직접 들어가 있는 경우이지만 경우에 따라서 인터넷에서 받은 파일이 여러 버전의 라이브러리를 가지고 있는 것도 있다. 예를 들어서 우노용과 두에용이 분리되어서 있는 경우이다. 이런 경우에는 사용자가 직접 압축을 해제한 후에 필요한 폴더만 사용자 라이브러리 폴더에 수동으로 복사해 주어야 한다.



Posted by 살레시오

  파이썬의 numpy, scipy, 심지어 sympy 까지 있는데 MATLAB의 control system toolbox 같은 것은 없나.. 하고 생각했었는데 있었다. 사용자 매뉴얼을 아래에 링크하였다.

python control system library User's manual


이 모듈은 winPython 에서 기본적으로 설치되어 있지 않다. 하지만 윈파이썬의 콘솔창(Tools > Open command prompt) 에서 다음과 같이 명령을 내리면 자동으로 인스톨된다.

------------------------------------------------------------------------
> pip install control
------------------------------------------------------------------------

이 라이브러리는 기본적인 선형제어 시스템에 관련된 함수들과 클래스가 정의되어 있고 MATLAB control toolbox 와 이름체계가 비슷한 것 같다.

이제 simulink 같은 툴만 나오면 되는 건가.. 갈수록 파이썬에 놀라는 중이다.

[#00084]

Posted by 살레시오