2026년 1월 25일 일요일

옆길로 샌 Ardule Project - USB MIDI host to DIN MIDI converter 만들기는 좌절과 극복의 연속이었다

아두이노 우노 R3 입문 키트(KEYES KT0001)를 주문한 것이 2020년 10월(관련 글). 아주 초보적인 예제 코딩만 몇 차례 해 보다가 최근 약 1년 동안은 이 키트와는 별도로 구입한 아두이노 나노 '클래식'과 아두이노 나노 에브리를 사용한 MIDI 컨트롤러 및 드럼 패턴 플레이어를 만드느라 몰두하였었다. GitHub에도 문서와 코드를 비롯한 거의 모든 자료를 올려 두었다. 프로젝트명은 Ardule Project - Arduino Nano-based Drum Patternology Ecosystem이다.

아두이노 식구 중에서 가장 먼저 구입했던 아두이노 우노(R3, ArduinoDocs의 자료)는 초창기에 몇 번의 간단한 실습을 한 것 외에는 별다른 용도를 찾지 못하고 있었다. (Nano) Ardule의 곁다리 프로젝트로서 계획하여 아주 최근 시작한 것은 USB MIDI host to DIN MIDI Converter의 제작이다. USB 단자밖에 없는 MIDI controller keyboard를 DIN 5-pin MIDI 커넥터만 갖고 있는 MIDI 사운드 모듈에 연결하여 실시간 연주를 할 수 있는 중간 '어댑터'에 해당하는 것을 만들고 있었다. 원래 이런 상황에서는 USB host 역할을 할 PC와 USB MIDI cable이 있으면 된다(아래에서 보인 사진). 하지만 컴퓨터 없이 단독으로는 전혀 쓸 수 없는 물건이다. 이것은 USB 장치(디바이스)이기 때문에 이를 제어할 USB 호스트(컴퓨터)가 없으면 쓰지 못하는 불편함이 있다.

아직도 쉽게 구할 수 있는 USB MIDI 케이블. 전통적인 DIN 5P MIDI 커넥터만 있는 구형 장비를 PC에 연결하도록 해 주는 MIDI 인터페이스에 해당한다. 아주 오래 전에는 PC내부에 꽂는 확장 카드 형식, 또는 시리얼/패럴랠 포트를 이용하는 방식이 있었다.

아두이노 우노의 생태계에는 '메인 보드' 위에 겹쳐 꽂아서 기능을 확장할 수 있는 다양한 'shield'가 존재한다. USB host shield와 MIDI shield만 있으면 납땜 작업을 전혀 하지 않고 원하는 일을 이룰 수 있을 것이라 생각했다. 그리고 이를 제작하게 되면 컴퓨터가 없어도 USB MIDI keyboard controller와 DIN MIDI sound module을 직접 연결하여 연주하는 것이 가능하리라고 생각하였다. 인터넷에도 이를 위한 다양한 DIY 프로젝트가 존재하니까 말이다.

그런데 그렇게 쉬운 일이 아니었다.

첫 좌절은 아두이노 우노 + USB host shield를 연결하고 여기에 USB MIDI keyboard controller를 연결한 뒤 펌웨어를 올렸을 때 건반에는 전원조차 들어오지 않았던 일이다. 이는 USB host shield가 기본 구성으로는 자체 USB-A 커넥터로 5V를 내보내지 않기 때문이었다. 보드 내에서 두 군데의 패드를 납으로 이어야 한다는 사실 앞에서 첫 좌절을 겪었(관련 글).

두 번째 좌절. 아두이노 우노와 USB host shield는 양 옆 가장자리의 커넥터 외에도 ICSP(In-Cirtuit Serial Programming)라는 6핀 헤더를 통해 연결된다. 아두이노 우노에는 2x3 핀이, 위에 포개어 놓는 USB host shield에는 소켓이 위치한다. 그런데 보드 두 장을 포개어 ICSP 커넥터를 완전히 밀착하더라도, 좌우의 핀은 끝까지 끼워지질 않는다. 이것 때문에 USB host shield에 건반을 꽂아도 인식이 되다말다 하는 일이 벌어졌다. 좌우의 핀 배열을 통해 +5V가 확실하게 공급되어야 하기 때문이다.

USB host shield의 ICSP 핀헤더 소켓(2x3)이 문제다. 너무 높다!

처음에는 이 접촉 문제를 가벼이 여기고 전원이 충분하지 않다고 생각했다. PC->USB 커넥터로 공급되는 5V의 전류에는 한계가 있으니, 2A 이상의 대전류를 흘릴 수 있는 5V 전원을 마련하여 아두이노 우노의 +5V 핀에 공급하기로 하였다. 아두이노 우노의 소켓에는 USB host shield가 꽂혀야 하니 납땜을 통해 전원 공급선을 별도로 빼야 한다. DC 어댑터 잭에 약간 높은(예: 7V~9V) 전원을 넣으면 전선 피복을 벗기고 납땜을 하지 않아도 되겠지만, 전압차가 클 경우 내부 레귤레이터가 너무 무리를 하게 된다. 전압차는 전부 열로 바뀌기 때문이다.

아두이노 우노의 핀아웃 다이어그램(원본). 왼쪽 가장자리의 녹색 원으로 표시한 곳에서 선을 따서 5V DC를 직접 공급하였다. 아래의 녹색 타원으로 둘러싼 것은 뒤에서 설명할 ICSP 핀 헤더. 이것은 좌우에 배열된 소켓과 내부적으로 연결되어 있다. 그러나 USB host shield의 좌우 핀 헤더는 대부분 'pass-through'용이다. 따라서 반드시 이 2x3 핀을 이용해서 통신해야 한다.

하필이면 내가 갖고 있는 어댑터는 5V와 12V뿐이다. 후자를 이용할 경우, 부품통에 굴러다니는 스텝다운 모듈을 쓰면 된다. 그리고 PC쪽의 USB를 통한 전원과 독립 전원을 동시에 연결하면 좋지 않다는 의견이 있어서 PC쪽에서는 5V를 공급하지 못하도록 케이블을 개조하기로 하였다. 정확히 말하자면 케이블을 개조하는 것이 아니라 USB 케이블 어댑터를 새로 만들었다. 시중의 USB 케이블은 커넥터와 선재가 거의 일체형태라서 작업을 하기가 불편하기 때문이다. 알리익스프레스에서 DIY용 USB 커넥터를 별도로 구입하느라 며칠이 소요되었다. 기기 보호를 위해 데이터는 차단하고 충전만 되는 USB 케이블용 어댑터는 비교적 흔하다.

전원 차단형 USB 케이블 어댑터 만들기. 커넥터는 나사가 아니라 접착제로 붙여야 한다. 정말 오랜만에 플라스틱 모델용 접착제 'TAMIYA CEMENT'를 꺼냈다. 아마 25년은 족히 묵었을 것이다. 수축 튜브를 케이블 중간 부분에는 씌우지 않는 실수를 범하였다.
아두이노 우노의 아랫쪽에서 전원과 그라운드를 위한 선을 납땜하였다. 그러나 이것으로 충분하지 않았다. 아두이노와 USB host shield의 핀 접촉이 완벽하지 못하기 때문이다. 문제의 원인은 ISCP 핀을 접속하기 위한 USB host shield의 소켓이 너무 높은 데에 있다. 이보다 더 밀착해야 한다!

어쨌든 충분한 전류를 흘릴 수 있는 전원장치까지 연결하였는데 키보드 인식이 매우 불안하였다. 몇 번의 실험을 거친 최종 결론은 두 보드 좌우의 핀/소켓 어레이가 완전히 밀착하지 않은 데에 원인이 있다는 것이었다. USB host shield의 ICSP 소켓을 제거한 뒤에 아두이노 우노와 연결할 방법을 고민하였다. 그렇지! IC 소켓 하나를 반으로 잘라서 쓰면 되겠구나. 원형 IC 소켓 스트립도 갖고 있었지만 핀이 도저히 들어가지 않았다.

왼쪽부터 MIDI shield, 소켓을 개조한 USB host shield, 그리고 아두이노 우노. 개조를 하지 않은 실드도 보이고 있다.

ICSP 커넥터 체결에 대한 오해 때문에 USB host shield도 두 개를 보유하게 되었다. 원래 갖고 있던 것은 2020년에 아두이노 우노 R3 키트를 살 때 들어 있었는지, 나중에 따론 산 것인지 잘 기억이 나지 않는다. 왜 최근에 실드를 하나 더 사게 되었나? 판단 착오의 흐름은 다음과 같다.

  1. 어라? ICSP 커넥터 때문에 두 보드의 핀/소켓 헤더가 밀착되지 않네. ICSP 소켓을 실드에서 떼어 버리자!
  2. 어라? ICSP 커넥터를 연결하지 않으면 안 되는 거였네... 원래 모습 그대로 두고 그렇게 좌우 핀/소켓이 들뜬 상태에서 쓰는 건가? 에이, 하나 더 사자.
  3. 어라? 새로 산 보드는 작동이 되다 안되다 하네... 그러면 ICSP 소켓을 떼어버린 이전 shield를 쓰되 어떻게 해서든 아두이노 우노와 연결을 해야 되겠네. 흑흑...

여기까지 하여 USB 키보드를 연결한 뒤 키를 누르면 PC의 아두이노 IDE 시리얼 모니터에 이벤트가 출력되게 하는 것까지 성공하였다. 이제 MIDI shield를 통해 MIDI out 신호만 나가게 하면 될 것이라 기대하였다.

모든 논의와 C++ 코드 설계는 챗GPT의 도움을 받았다. 이제 마지막으로 생각하고 펌웨어를 업로드하는데 뭐가 좀 이상하다. 업로드 과정에서 에러가 발생하는 것이었다. MIDI shield에 붙어 있는 용도 미상의 ON/OFF 슬라이드 스위치가 수상하였다. 세 번째 좌절이었다.

아두이노 나노 에브리와 달리 아두이노 우노 및 아두이노 나노 클래식은 펌웨어 업로드시 RX(D0)이 다른 곳에 연결되어 있으면 안 된다. 그래서 펌웨어 업로드 시에는 점퍼를 사용하는 등 별도의 수단을 강구해야 한다. 그리고 TX(D1)을 통해 UART MIDI 신호가 나가게 되므로 기본적으로 시리얼 모니터도 쓰지 못한다.

이 스위치를 OFF 위치에 놓으니 비로소 펌웨어 업로드가 성공하였다. 아마도 이 스위치를 ON으로 놓으면 DIN 5핀 커넥터로 들어오는 MIDI IN 신호를 RX 핀으로 보내는 기능을 하는 것으로 여겨진다.

MIDI IN을 쓰려면 스위치를 ON으로 놓을 것.

펌웨어 업로드가 되었지만 여전히 소리는 나지 않았다. USB-MIDI 신호의 파싱에 문제가 있었기 때문이다. 이것이 네 번째 좌절이었다. MIDI shield만을 이용하여 '도레미파솔라시도'를 무한 반복하는 코드를 테스트하면서 보드가 정상임을 먼저 확인한 뒤 문제를 해결해 나갔다.

무슨 말인지 나도 잘 모르겠음. 완벽하게 이해를 하지 못하더라도 학습을 위해 중간 단계마다 문서를 만들어서 잘 저장해 두었다.

이렇게 몇 단계의 좌절을 거쳐서 드디어 USB 키보드 컨트롤러를 통해 롤랜드 사운드캔버스 SC-D70을 제어하여 소리를 낼 수 있었다. 그러나 보드 3장이 겹쳐져 있어서 맨 아래 아두이노 우노의 LED가 잘 보이지 않는다. 작동 상태를 표시할 겸 I2C 2004 LCD를 연결하였다. LCD 표시에 너무 충실하면 키보드 제어에 지연이 발생하기 때문에 몇 번의 최적화를 거쳤다.

하는 일에 비해 2004 LCD 디스플레이는 너무 크다. 

2004 LCD는 이 작은 기기에게 지나치게 크다. 1602 LCD 또는 0.96인치 OLED 디스플레이가 더 적합하겠지만 일단 갖고 있는 부품으로 작동을 확인하고 싶은 욕심이 컸다. 최종 개발품의 소형화를 위해 나중에 OLED 디스플레이를 써 보고 싶다. 사실 작동 상태만 확인하면 되니 캐릭터 디스플레이가 아니라 두어 개의 LED로도 충분하다.

이로써 케이스만 씌우면 실사용에 문제가 없는 수준이 되었다. 필요한 기능은 거의 다 구현했으니 프로젝트의 목표를 80% 달성했다고 볼 수 있을까? 절대 아니다. DIY에서 핵심 기능 구현보다도 케이스를 만드는 일이 가장 어려운 단계임은 누구나 잘 안다. 아마 여기에 80% 이상의 노력이 들어갈 것이다.

Nano Ardule 생태계 구축에 들인 수 개월 동안의 노력이나 숱한 좌절을 생각하면 이번 서브 프로젝트는 매우 빠르게 진척된 셈이다. 가장 시급한 기능 개선은 디스플레이를 가장 능률적인 것으로 확정하는 것이다. 하드웨어 버튼 같은 것은 달고 싶지 않다. 채널 리맵/레이어링 기능 등은 Nano Ardule MIDI Controller에 이미 충분히 구현되어 있으니 이것을 다음에 연결하여 사용하면 된다.

이렇게 Ardule 세계의 장난감이 하나 둘 늘어나고 있다. 이 서브 프로젝트 또한 GitHub의 Nano Ardule 리포지토리 하위(Ardule USB MIDI Host)에 정리하기 시작하였다.

[2026년 3월 31일 업데이트 by ChatGPT] Arduino UNO R3 + USB Host Shield + MIDI Shield로 만든 USB MIDI 브리지, 반대 방향도 가능할까?

다음은 직접 만든 USB MIDI 브리지의 동작 방향과 한계에 대해 정리한 문답입니다. ChatGPT가 자동생성하였음을 미리 밝혀 둡니다.

Q. Arduino UNO R3 + USB Host Shield + MIDI Shield를 이용하여 USB MIDI bridge를 만들었습니다. 이것은 USB MIDI keyboard 출력을 DIN MIDI sound module로 보내줍니다. 만약 MIDI shield의 IN에 legacy MIDI keyboard를 꽂으면, UNO의 USB 단자를 통해서 다른 PC로 전달하는 것이 가능할까요? 그리고 PC에서 이것을 MIDI IN으로 인식할 수 있나요?

A. 짧게 결론부터 말하면, 기본 상태의 Arduino UNO R3로는 어렵습니다. 즉, DIN MIDI 신호를 받아서 UNO의 USB 단자를 통해 PC에 보내더라도, PC에서는 그것을 일반적인 MIDI IN 장치로 인식하지 않습니다.

이유는 Arduino UNO R3의 USB 구조 때문입니다. UNO R3는 메인 마이컴인 ATmega328P가 USB를 직접 처리하는 구조가 아니라, 별도의 ATmega16U2가 USB-Serial 변환기처럼 동작합니다. 따라서 PC에 연결했을 때 기본적으로는 MIDI 장치가 아니라 시리얼 포트(COM 포트)로 보입니다.

ATmega328P (main MCU)
        │ UART
ATmega16U2 (USB-Serial converter)
        │
       USB

즉, 다음과 같은 경로는 가능합니다.

DIN MIDI IN → MIDI Shield → UNO → USB → PC

하지만 PC 입장에서는 이것이 다음처럼 보입니다.

DIN MIDI → UNO → USB Serial → PC

다시 말해, MIDI 데이터가 시리얼 데이터로 전달될 수는 있어도, 그것만으로 PC가 이를 표준 USB MIDI 장치로 인식하지는 않습니다.

PC에서 MIDI IN으로 인식되려면, USB 쪽이 USB MIDI 클래스 디바이스로 동작해야 합니다. 그런데 기본 상태의 UNO는 그렇게 되어 있지 않습니다.

물론 예외는 있습니다. UNO의 ATmega16U2 펌웨어를 다시 써서 USB MIDI 디바이스처럼 동작하게 만들면, 이론적으로는 가능합니다. 이 경우에는 DIN MIDI 입력을 받아 PC에서 MIDI 장치처럼 인식되도록 구성할 수 있습니다. 다만 이 방법은 펌웨어 재플래시가 필요하고, 기존의 USB-Serial 기능이 사라지거나 디버깅이 불편해질 수 있어 다소 번거롭습니다.

좀 더 현실적인 대안은 다음과 같습니다.

  • Arduino Leonardo / Micro / Pro Micro처럼 USB가 내장된 보드를 사용한다.
  • Teensy처럼 USB MIDI 지원이 매우 잘 되는 보드를 사용한다.
  • UNO는 그대로 두고, PC 쪽에서 Serial-to-MIDI 변환 프로그램을 사용한다. 다만 이 경우는 표준 MIDI 장치 인식과는 다르며 안정성과 지연 면에서 아쉬울 수 있다.

정리하면, UNO + USB Host Shield + MIDI Shield 조합은 USB MIDI keyboard의 출력을 DIN MIDI로 바꾸는 용도로는 매우 유용하지만, 그 반대 방향인 DIN MIDI를 USB MIDI 장치로 PC에 인식시키는 용도로는 기본 상태에서 적합하지 않습니다.

한 줄로 요약하면 이렇습니다.

Arduino UNO R3의 USB는 기본적으로 MIDI 장치가 아니라 USB-Serial 장치이므로, PC에서 MIDI IN으로 바로 인식되지는 않습니다.

[2026년 4월 2일 업데이트 by ChatGPT] UNO를 통한 Serial MIDI 브리지와 Raspberry Pi에서의 활용

위 문답에서는 Arduino UNO R3의 USB가 기본적으로 MIDI 장치가 아닌 USB-Serial 장치이기 때문에, PC에서 이를 표준 MIDI IN 장치로 인식하지 못한다는 점을 설명했습니다. 이 내용은 정확합니다.

다만 여기에는 하나의 숨은 전제가 있습니다. 즉, “USB로 연결된 장치는 반드시 표준 USB MIDI 디바이스로 인식되어야만 유용하다”는 가정입니다. 그러나 이 전제는 특히 Raspberry Pi와 같은 임베디드 환경에서는 반드시 참이라고 볼 수 없습니다.

오히려 다음과 같은 접근이 더 현실적이고 안정적인 경우도 많습니다.

DIN MIDI → UNO → USB (Serial) → Raspberry Pi → ALSA MIDI

이 구조에서 UNO는 MIDI 장치가 아니라 MIDI 데이터를 시리얼 스트림으로 전달하는 브리지로 동작합니다. Raspberry Pi에서는 이 시리얼 데이터를 읽어 ALSA MIDI 포트로 재구성하면, 결과적으로 소프트웨어 신디사이저(예: FluidSynth)에서 정상적인 MIDI 입력으로 사용할 수 있습니다.

즉, PC에서 “USB MIDI 장치로 보이느냐”는 문제와, Raspberry Pi에서 “MIDI로 활용할 수 있느냐”는 문제는 서로 다른 층위의 이야기입니다.

왜 이 방법이 유효한가

  • Raspberry Pi 3B는 USB와 Ethernet이 내부적으로 공유된 구조이기 때문에, USB 장치가 많아질수록 불안정해질 수 있습니다.
  • USB 오디오 인터페이스와 USB MIDI를 동시에 사용할 경우, note off 누락이나 USB 오류(예: urb -32)가 발생할 수 있습니다.
  • UNO를 이용해 MIDI를 Serial로 변환하면, Pi는 USB 대신 가벼운 시리얼 데이터만 처리하면 되므로 전체 시스템 안정성이 향상됩니다.

구조 비교

[기존 구조]
USB MIDI 키보드 → Pi (USB) → FluidSynth

[개선 구조]
USB MIDI 키보드 → UNO → Serial → Pi → ALSA MIDI → FluidSynth

후자의 경우, Pi의 USB 부하를 줄이면서도 MIDI 입력을 유지할 수 있습니다.

주의할 점

  • 이 방식은 표준 USB MIDI 디바이스로 인식되는 것이 아니라, 소프트웨어를 통해 MIDI로 변환하는 구조입니다.
  • 따라서 Raspberry Pi 측에서 Serial → MIDI 변환 프로그램(예: Python 스크립트, ttymidi 등)이 필요합니다.
  • MIDI 메시지는 1~3바이트로 구성되므로, 올바른 패킷 처리와 running status 처리가 필요합니다.

정리

Arduino UNO R3는 USB MIDI 장치로 직접 인식되지는 않지만, MIDI 데이터를 Serial로 전달하고 이를 Raspberry Pi에서 ALSA MIDI로 재구성하면 충분히 실용적인 MIDI 입력 경로를 만들 수 있다.

즉, UNO의 한계는 “USB MIDI 장치가 아니다”라는 점이지, “MIDI를 전달할 수 없다”는 의미는 아닙니다. 오히려 적절한 구조를 선택하면, USB 기반보다 더 안정적인 시스템을 구성할 수도 있습니다.


바로 위에서 논의한 것과 비슷한 프로젝트는 다음과 같은 키워드로 검색 가능하다고 한다.

  • Arduiono MIDI bridge
  • USB MIDI to serial bridge
  • ttymidi Raspberry Pi
  • MIDI UART interface Linux


댓글 없음: