안경잡이개발자

728x90
반응형

  Teensy는 USB 장치(Device) 개발용 키트로, 새로운 USB 장치를 개발하고자 할 때 아두이노(Arduino) IDE를 기반으로 하여 개발을 진행할 수 있습니다. Teensy는 USB 장치 개발용 키트라는 점에서 원하는 USB Type으로 해당 보드를 이용할 수 있습니다. 저는 Teensy 3.6 보드를 사용하고 있는데, Teensyduino를 설치한 뒤에 다음과 같이 다양한 기본적인 USB 타입들을 확인할 수 있습니다.

 

 

  Teensy는 동시에 여러 개의 인터페이스를 제공하기에 용이하다는 점에서 다목적의 USB 장치를 만들 수 있습니다. 예를 들어 동시에 마우스이면서 키보드인 USB 장치를 만들 수 있습니다. 다만 기본적으로 제공하는 USB Type이 아니라, 자신만의 USB Type을 만들고자 한다면 어떻게 해야 할까요? 새로운 보드를 추가하고 개발하는 방법을 소개합니다.

 

※ 새로운 USB 타입 정의하기 ※

 

  자신만의 USB Type을 정의하고자 할 때는 가장 먼저 boards.txt 파일을 수정해야 합니다. 일반적으로 boards.txt 파일을 열어서 수정할 때는 에디터(Editor) 프로그램을 관리자 권한으로 실행하셔야 합니다.

 

  ▶ Boards.txt 파일 경로: C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3

 

 

  boards.txt를 열면 각 Teensy 보드 버전에 따라서 다양한 보드 타입과 기타 내용들이 정의되어 있는 것을 확인할 수 있습니다. 가볍게 다음과 같은 내용을 추가하여 새로운 USB Type으로 "USB_TEST"를 추가할 수 있습니다.

 

teensy36.menu.usb.test=Test
teensy36.menu.usb.test.build.usbtype=USB_TEST
teensy36.menu.usb.test.fake_serial=teensy_gateway

 

  그러면 다음과 같은 형태로 들어가게 될 겁니다.

 

 

  이제 boards.txt를 저장한 뒤에 아두이노 IDE를 관리자 권한으로 실행합니다. 그러면 다음과 같이 새로운 USB Type으로 "Test"가 추가되어 있는 것을 확인할 수 있습니다.

 

 

※ USB Description 정의하기 ※

 

  (참고: 아두이노 IDE를 관리자 권한으로 실행했다면, 소스코드 편집기도 관리자 권한으로 실행해야 합니다.)

 

  USB 장치는 기본적으로 우리의 컴퓨터 (Host)에 꽂았을 때 기본적인 Description 정보를 보냅니다. "나는 어떤 기능을 제공하는 USB 장치야."라는 의미라고 보시면 됩니다. 당연히 새로운 USB 장치를 개발한다면 Description 정보를 수정할 필요가 있을 것입니다.

 

  Teensy 3.6 버전에서는 usb_desc.h 파일에서 그러한 정보를 담고 있습니다. 이 소스코드를 수정하면 알아서 Teensy 보드가 연결될 때 호스트(Host)에게 자신의 수정된 Description 정보를 보냅니다.

 

 

  예를 들어 다음과 같이 작성할 수 있습니다. 저는 간단히 키보드와 마우스의 기능만을 포함하고 있는 새로운 USB Type을 정의했습니다. 참고로 KEYBOARD_INTERFACE나 MOUSE_INTERFACE 등은 usb_keyboard.h와 usb_mouse.h 코드를 사용할 수 있도록 해주는 전처리 구문입니다. 다시 말해, 일단 저는 이미 Teensy 코어(Core)에 정의되어 있는 키보드와 마우스 기능을 그대로 사용하고자 합니다. (만약 이러한 코어 코드까지 다 새롭게 만드시고 싶을 수 있는데요. 이 또한 원하신다면 처음부터 다 만드실 수 있습니다.)

 

#elif defined(USB_TEST)
  /* USB 장치의 기본적인 ID와 클래스 정보 */
  #define VENDOR_ID 0x16C0
  #define PRODUCT_ID 0x0707
  #define DEVICE_CLASS 0xEF // 기타 USB 클래스 (Miscellaneous) 
  #define DEVICE_SUBCLASS 0x02 // 기타 USB 클래스 (Miscellaneous)의 서브 클래스 
  #define DEVICE_PROTOCOL 0x01 // 다양한 인터페이스 사용 (Interface Association Descriptor)

  /* USB 장치의 이름 정보 */ 
  #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
  #define MANUFACTURER_NAME_LEN 11
  #define PRODUCT_NAME {'M','y',' ','T','e','s','t',' ','B','o','a','r','d'}
  #define PRODUCT_NAME_LEN 13

  /* USB 장치의 엔드포인트 및 인터페이스 정보 */
  // 엔드포인트 0번은 Control Transfer 목적으로 고정 
  #define EP0_SIZE 64
  #define NUM_ENDPOINTS 6
  #define NUM_USB_BUFFERS 30
  #define NUM_INTERFACE 5

  /* CDC 관련 정보 */
  #define CDC_IAD_DESCRIPTOR 1
  #define CDC_STATUS_INTERFACE 0
  #define CDC_DATA_INTERFACE 1 // 시리얼 (Serial) 
  #define CDC_ACM_ENDPOINT 1
  #define CDC_RX_ENDPOINT 2
  #define CDC_TX_ENDPOINT 3
  #define CDC_ACM_SIZE 16
  #define CDC_RX_SIZE 64
  #define CDC_TX_SIZE 64

  /* 키보드 (Keyboard) */
  #define KEYBOARD_INTERFACE 2
  #define KEYBOARD_ENDPOINT 4
  #define KEYBOARD_SIZE 8
  #define KEYBOARD_INTERVAL 1

  /* 키보드 미디어 키 (Keyboard Media Keys) */
  #define KEYMEDIA_INTERFACE 3
  #define KEYMEDIA_ENDPOINT 5
  #define KEYMEDIA_SIZE 8
  #define KEYMEDIA_INTERVAL 4

  /* 마우스 (Mouse) */
  #define MOUSE_INTERFACE 4
  #define MOUSE_ENDPOINT 6
  #define MOUSE_SIZE 8
  #define MOUSE_INTERVAL 2

  /* 각 엔드포인트의 데이터 송수신 관련 정보 */
  #define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY // CDC ACM
  #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY // CDC RX
  #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY // CDC TX
  #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY // 키보드 TX (전송만) 
  #define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY // 키보드 미디어 키 TX (전송만) 
  #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY // 마우스 TX (전송만)

 

  또한 USB Function Driver에는 HID (Human Interface Device), CDC (Communication Device Class), MSC (Mass Storage Class) 등이 포함됩니다. 이 때 Mouse, Keyboard 등은 기본적으로 HID에 속하며, 시리얼(Serial) 통신은 CDC에 속합니다.  그래서 usb_desc.h에서 CDC 부분을 빼버리면 아두이노에서 Serial 라이브러리를 사용할 수 없습니다.  마찬가지로 Mouse나 Keyboard 부분을 빼버리면 아두이노에서 Mouse, Keyboard 라이브러리를 사용할 수 없답니다.

 

  참고로 usb_desc.h 부분의 코드가 잘못되어 있으면 호스트(Host)에서 USB 장치로 인식조차 안 할 수 있습니다. 만약에 usb_desc.h 파일을 수정한 뒤에 Teensy 보드로 업로드를 했는데, 아예 인식을 안 하는 경우 (특히 포트조차 못 잡는 경우) Teensy 보드에 있는 작은 버튼을 눌러서 초기화 해주셔야 합니다. 

 

※ 예제 소스코드 ※

 

  예제 소스코드는 다음과 같습니다. Mouse, Keyboard, Serial 라이브러리를 모두 사용합니다.

 

void setup() {

}

void loop() {
    int i;
    for (i = 0; i < 40; i++) {
        Mouse.move(2, -1);
        delay(100);
    }
    delay(1000);
    Serial.println("Hello");
    Keyboard.print("Hello World");
}

 

※ 실행 결과 ※

 

  컴파일 이후에 Teensy 보드에 업로드를 하면 성공적으로 USB 장치가 동작합니다. 반복적으로 마우스를 움직이며, 키보드로 "Hello World"를 입력하고, 시리얼 통신으로 "Hello"라는 문자열을 전송합니다. 리눅스 환경에서 lsusb 명령어를 이용해 USB 장치의 상세 Description을 확인하면 다음과 같습니다.

 

  사실 Vendor ID로 사용한 0x16c0는 이미 정의되어 있네요. 이 값 또한 원래는 바꿔주어야 합니다. 

 

 

  또한 이어서 인터페이스(Interface) 정보를 확인해 보시면, 인터페이스마다 CDC, Keyboard, Mouse 등의 각기 다른 기능이 제공되는 것을 알 수 있습니다. CDC를 이용한 시리얼 통신은 Bulk Transfer를 기반으로 하고 있으며, HID를 이용한 Keyboard 기능은 Interrupt Transfer를 기반으로 하고 있네요. 각각 패킷 크기도 64 바이트와 8 바이트로 다릅니다. 사실 이 내용들도 대부분 usb_desc.h 파일에 정의되어 있습니다.

 

728x90
반응형

728x90
반응형

  아두이노를 설치한 뒤에 하드웨어(hardware) 폴더로 이동하면 boards.txt 파일이 존재한다. 여기에는 아두이노 IDE에서 사용할 수 있는 각종 USB 보드(Board)의 종류에 대해서 다룬다. 필자는 최근에 새로운 타입의 USB 보드를 개발할 필요가 있었다. 그래서 boards.txt 파일에 새로운 타입의 보드를 추가했다. 일단 간단히 "xyz"라는 이름의 보드를 추가했다.

 

 

  그랬더니 다음과 같은 오류 메시지를 만날 수 있었다.

 

 

  아두이노에서 이처럼 컴파일 오류가 발생하는 경우에는 자세히 확인하기 위해서 환경설정에서 컴파일, 업로드와 관련한 자세한 메시지가 출력되도록 설정을 바꿀 필요가 있다.

 

 

  확인 결과 컴파일 과정에서 FQBN (Fully Qualified Board Name)을 제대로 찾지 못해 문제가 발생하는 것으로 보인다. 내가 새롭게 추가한 "xyz" 보드를 제대로 인식하지 못하고 있는 것이다.

 

 

  사실 이 문제의 해결 방법은 간단하다. 아두이노를 관리자 권한으로 실행하면 수정된 boards.txt 파일을 정상적으로 인식하고, 자신이 추가한 보드 정보를 읽어올 수 있다.

 

 

  다만 이 경우에는 기타 모든 코어 코드를 수정할 때에도 에디터를 관리자 권한으로 실행할 필요가 있다. 아두이노 코어(Core) 코드를 수정할 때 에디터를 관리자 권한으로 실행하여 수정하지 않으면, 아두이노 IDE와 연동이 제대로 이루어지지 않을 수도 있다.

728x90
반응형

728x90
반응형

  Teensy Board를 이용하는 경우 다양한 오류를 만날 수 있는데요. 해결하기 어려운 오류는 포럼(Forum)에 글을 남김으로써 다른 개발자에게 도움을 받을 수 있습니다. Teensy 포럼 웹 사이트의 링크는 다음과 같습니다.

 

  ▶ PJRC 포럼(Forum) 웹 사이트: https://forum.pjrc.com/

 

  만약 회원가입을 아직 안 하신 분이라면 다음과 같이 [Register] 버튼을 눌러서 회원가입을 진행할 수 있습니다.

 

 

  회원가입을 진행할 때에는 아이디, 비밀번호, 이메일 등 다양한 정보를 기입한 뒤에 [Complete Registration] 버튼을 눌러서 회원가입 요청을 할 수 있습니다.

 

 

  회원가입 이후에는 자신이 회원가입을 할 때 기입했던 이메일 주소로 등록 완료 메일이 옵니다. 여기에서 링크를 눌러 주시면 실제로 회원가입이 완료됩니다.

 

 

  회원가입이 완료되면 이제 포럼에 글을 작성할 수 있게 됩니다.

 

 

  저는 개발 관련 이슈가 있어서 [Technical Support & Questions] 경로로 이동하였습니다.

 

 

  다음과 같이 [Post New Thread] 버튼을 눌러서 게시판에 글을 작성할 수 있습니다.

 

 

 

  이후에 다음과 같이 글을 작성하시면 됩니다. 가능하면 이미지와 소스코드 및 설명을 최대한 자세하게 첨부하는 것이 좋은 답변을 받기에 유리합니다.

 

 

  이렇게 글을 쓴 뒤에 이메일로 알림을 받도록 설정하면, 누군가 댓글을 달았을 때 다음과 같이 댓글이 달렸다는 이메일이 도착합니다.

 

 

  이후에 댓글에 대하여 다시 댓글을 다는 방법은 다음과 같습니다. [Reply With Quote] 버튼을 눌러서 다른 사람의 글에서 인용할 부분을 설정합니다. 그리고 글의 내용을 작성하면 됩니다. [Post Quick Reply] 버튼을 눌러서 댓글을 등록할 수 있습니다.

 

728x90
반응형