아두이노 마이크로/레오나르도용 USB MIDI 어댑터 키트 – 전체 부품 리스트
부품 및 소모품
| 부품 | 수량 | 비고 |
| Arduino Micro (또는 Leonardo) | 1 | ATmega32u4 기반, 네이티브 USB 지원 |
| 6N137 옵토커플러 | 1 | 고속, 광범위 구매 가능 |
| 1N4148 고속 스위칭 다이오드 | 1 | |
| 커패시터 100 nF | 1 | |
| 저항 220 Ω | 3 | |
| 저항 10 kΩ | 1 | |
| 저항 470 Ω (스루홀) | 1 | |
| LED (범용) | 1 | 전원 표시용 |
| LED 홀더 | 1 | 플라스틱 케이스 장착용 |
| DIN 5핀 커넥터 (오디오/비디오용) | 2 | MIDI IN/OUT용, 볼트/너트 포함 |
| 플라스틱 케이스 | 1 | 모든 부품 수납 가능한 크기 |
| 범용 PCB | 1 | |
| PCB 마운트 (나일론 스탠드오프 등) | 1 | 케이스 내 PCB 고정용 |
앱 및 온라인 서비스
프로젝트 개요
아두이노로 USB-MIDI 어댑터를 만들려다 기존 자료들이 소프트웨어/하드웨어 구현이 미흡해 직접 제작해 공유합니다.
하드웨어
- Arduino Leonardo로 브레드보드에서 프로토타입 검증 후, Arduino Micro로 납땜 버전 제작. 둘 다 ATmega32u4로 네이티브 USB 지원 → PC에서 USB MIDI 인터페이스로 인식
- MIDI 표준에 따라 옵토커플러(6N137)와 저항으로 완전 절연된 전류 루프 구성
- 회로도상 MIDI OUT 커넥터만 핀 2를 그라운드에 연결 (MIDI 표준)
- 완성품 사진들




소프트웨어
Control Surface 라이브러리 사용. 복잡한 MIDI 프로토콜을 올바르게 처리하며, 포텐셔미터/페달/버튼 등 추가 MIDI 컨트롤러 쉽게 확장 가능. 콜백 등록으로 MIDI↔USB 양방향 데이터 가공 가능.
활용 예: 롤랜드 D-50 신시사이저의 버그 수정. 마지막 건반을 떼면 'All Notes Off'(0xB0 0x7B) 전송 → 최신 VST는 서스테인 즉시 차단으로 오작동. 이 메시지 필터링으로 D-50을 마스터 키보드로 정상 사용 가능.
알려진 이슈: Control Surface 라이브러리 구버전은 대용량 SysEx 패킷 처리 시 오류. D-50 에디터/라이브러리안 사용 시 큰 SysEx 전송으로 에러 발생. 소스 코드 주석에 수정 방법 기재 (라이브러리 2.x에서 수정 예정).
기본 USB-MIDI 인터페이스 버전과 'All Notes Off' 필터링 버전 두 가지 소스 코드 제공. 다른 MIDI 라이브러리나 직접 구현도 하드웨어 호환 가능.
트러블슈팅 팁: 외부 MIDI 기기와 통신 안 되면 DIN 커넥터 핀 4, 5가 뒤바뀐 것일 수 있음. 커넥터 핀아웃 다이어그램이 어느 면 기준인지 불명확한 경우 많음.
코드
기본 MIDI-USB 인터페이스 소스 코드
/* USB MIDI Adapter
대용량 SysEx 지원을 위해 Control Surface 라이브러리 수정 필요:
- MIDI_MessageTypes.hpp: uint8_t length → size_t length
- Settings.hpp: SYSEX_BUFFER_SIZE 128 → 320
(2.x 버전에서 수정 예정)
USB 장치명 변경: hardware/arduino/avr/boards.txt에서 leonardo.build.usb_product 수정 후 업로드, 원복
*/
#include
USBMIDI_Interface midiusb;
HardwareSerialMIDI_Interface midiser = {Serial1, MIDI_BAUD};
MIDI_PipeFactory<5> pipes;
const int ledPin = 10; // 전원 LED 핀
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH);
// MIDI USB ↔ Serial 양방향 파이프
midiusb >> pipes >> midiser;
midiser >> pipes >> midiusb;
// Control Surface 메시지는 USB만
Control_Surface >> pipes >> midiusb;
// 양쪽 모두 Control Surface와 연결
midiser >> pipes >> Control_Surface;
midiusb >> pipes >> Control_Surface;
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
}
'All Notes Off' 필터 포함 버전
/* USB MIDI Adapter with "All Notes Off" Filter
동일 라이브러리 수정 필요
*/
#include
USBMIDI_Interface midiusb;
HardwareSerialMIDI_Interface midiser = {Serial1, MIDI_BAUD};
MIDI_PipeFactory<4> pipes;
const int ledPin = 10;
// 커스텀 MIDI 콜백: 채널 메시지 필터링
struct MyMIDI_Callbacks : MIDI_Callbacks {
void onChannelMessage(Parsing_MIDI_Interface &midi) override {
ChannelMessage cm = midi.getChannelMessage();
if (cm.header == 0xB0 && cm.data1 == 0x7B) {
// "All Notes Off" 무시
return;
} else if (cm.header == 0x90 && cm.data2 == 0x00) {
// 벨로시티 0인 Note On → Note Off로 변환
cm.header = 0x80;
}
midiusb.send(cm);
}
void onSysExMessage(Parsing_MIDI_Interface &midi) override {
midiusb.send(midi.getSysExMessage());
}
void onRealTimeMessage(Parsing_MIDI_Interface &midi) override {
midiusb.send(midi.getRealTimeMessage());
}
} callbacks;
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH);
midiusb >> pipes >> midiser;
Control_Surface >> pipes >> midiusb;
midiser >> pipes >> Control_Surface;
midiusb >> pipes >> Control_Surface;
Control_Surface.begin();
midiser.setCallbacks(callbacks);
}
void loop() {
Control_Surface.loop();
}
회로도

usb_midi_interface_twiE32gvR3.fzz (Fritzing 파일)