Nano Ardule 드럼 패턴학 생태계를 열심히 일구면서 핵심적인 기능을 거의 다 개발한 단계까지 왔다. 문서 또는 비디오 형태의 매뉴얼을 만드는 일만 남았다고 생각한다. 보다 더 욕심을 내자면 KiCad를 익혀서 PCB를 만들어 보고 싶다. 페놀기판에 얼기설기 엮어서 만든 현재의 프로토타입은 영 모양새가 좋지 않기 때문이다. 그야말로 전자 DIY의 마지막 단계까지 가 보고 싶다. 물론 이를 전부 수용하는 아름다운 케이스를 만드는 일이 DIY의 진정한 마지막 단계일 것이다.
PCB 주문을 위한 Gerber 파일 설계는 내가 대충 익혀서 사용한 Fritzing에서도 가능한 것으로 아는데, 브레드보드가 아니라 perfboard를 바탕으로 대충 회로도를 그려 놓았기 때문에 연결 상태가 완벽한지 아직 자신이 없다.
잠시 옆길로 새기 위해 아두이노 UNO에 층을 쌓듯이 포개어 쓸 수 있는 두 종류의 실드('Shield')를 구입하였다. 그것은 USB 호스트 실드와 MIDI 실드. 컴퓨터를 거치지 않고도 USB MIDI 키보드를 구식 사운드 모듈(DIN 5핀 MIDI 단자)에 연결하여 직접 제어하기 위함이다. 이를 Ardule USB MIDI Host라 부르고자 한다.
|
|
| 아래부터 아두이노 우노 R3, USB host shield, 그리고 MIDI shield로 3층집을 쌓았다. |
납땜도 필요하지 않은 DIY라서 펌웨어만 올리면 자연스럽게 동작을 하리라고 기대하였다. 우선 USB host shield에 USB MIDI Controller Keyboard(AKAI MPK mini MK2)를 연결한 뒤 제대로 인식이 되고 건반을 눌렀을 때 note on/off 신호가 나오는지 시리얼 모니터로 출력하는 코드를 올려 보았다.
그러나... 건반에 불이 들어오지 않는다. USB 단자를 통해서 전원이 공급되어야 하는데 그렇지 않은 것 같다. 전류가 부족한가? 챗GPT와 더불어 고민을 해 보니 USB host shield의 보드 안에서 VBUS로 5V가 공급되도록 직접 납땜을 해야 한다는 것이다. 다음 사진은 납땜을 마친 뒤 찍은 것이다. 빨간 원으로 표시한 패드 두 곳을 납땜하여 이어야 아두이노 UNO로부터 핀 헤더를 통해 공급된 5V가 USB 단자의 VBUS 핀을 통해 USB 디바이스로 공급된다고 한다. 의외로 이런 정보는 판매처(알리익스프레스)에서도 잘 제공하고 있지 않으며, 국문 웹 자료에서도 거의 찾아보기 어렵다. 사용자가 직접 납땜을 해야 함을 알려주는 판매자의 웹사이트를 어렵게 찾아서 소개한다(링크).
보드를 관찰한 후 내가 내린 결론은 이렇다. 아두이노 우노를 통해 공급되는 3.3V/5V를 USB 호스트 실드로 가져오려면 헤더쪽(위 사진에서 아랫줄)의 패드를 전부 납땜하여 연결해야 하고, 이를 USB 호스트 실드의 USB 단자를 통해 공급하려면 3.3V와 5V 중 원하는 것을 VBUS와 연결되도록 납땜을 하면 된다. 나에게 필요한 것은 5V이므로, 헤더쪽에서 오는 전원 중 5V만 연결하였다.
왜 USB 호스트 실드는 이렇게 '반제품'처럼 만들어서 판매하는 것일까? USB로 접속하는 모든 기기가 이를 통해 전원을 공급받는 것은 아니기 때문에 사용자에게 선택 여지를 준 것이라고 생각한다. 잘못하면 전원의 중복으로 인해 오류가 날 수도 있다.
이러한 시행착오 끝에 USB MIDI 컨트롤러 키보드를 연결하니 성공적으로 인식이 되고, 키 누름에 반응하여 시리얼 모니터에 note on/off 메시지가 나오는 것을 확인하였다.
무난히 USB 호스트 실드의 테스트를 마치고 다음 단계로 진행하려는 찰나, 키보드의 인식이 불안정함을 느꼈다. 아무래도 PC -> USB -> 아두이노 우노를 통해서 다시 외부 USB 기기(키보드)를 동작시킬 전류까지 충당하기에는 부족함이 있는 것 같다. 상세한 raw message를 확인해 보았다. 테스트했던 다른 코드에서는 raw=18 (0x12)가 나오기도 한다. 이것은 detached / idle을 의미한다.
Ardule Bridge - USB/MIDI FULL DIAG USB Host Shield init OK Plug / unplug USB MIDI device and operate keys... [USB] State raw = 32 (0x20) # attached [USB] State raw = 64 (0x40) # powered [USB] State raw = 80 (0x50) # default / enumeration start [USB] State raw = 81 (0x51) # configured running [USB] State raw = 144 (0x90) # error
raw=144(0x90)은 에러라고 한다. PC USB 전원만 쓰면 자주 생기는 브라운 아웃(brown-out, 전원은 살아 있는데 전압이 모자라서 오동작하는 상태)라고 하였다. 실제로 USB 키보드를 꽂았음에도 불구하고 작동을 하지 않는 경우 멀티미터로 실드 쪽의 VBUS를 찍어보면 3V 약간 넘는 전압이 나왔다. 정전은 black-put, 전압이 떨어져서 오동작하는 상태는 brown-out이다.
그렇다면 충분한 전류를 흘릴 수 있는 양질의 5V를 어떻게 공급하면 좋을까?
- 7~9V의 DC 어댑터가 있다면, 아두이노 우노의 어댑터 잭을 통해 꽂으면 된다. 내부적으로 선형 레귤레이터를 통해 5V로 낮추어서 제공하므로 발열이나 순간 전류에 취약하다.
- 가장 바람직한 것은 최소한 1A를 공급할 수 있는 안정적인 5V(4.8~5.2V)를 소켓 헤더쪽에 공급하는 것이다. Vin 단자는 곤란하다. 왜냐하면 내부적으로 1번과 같기 때문이다. 리니어 레귤레이터는 목표 전압보다 높은 전압을 주어야 작동한다.
여기에 더하여 PC와 아두이노 우노를 연결하는 USB 케이블에서 VBUS를 끊어서 오직 데이터만 전송하게 만드는 것이 바람직하다고 한다. 보통 PC USB와 외부 5V를 동시에 연결해도 문제는 없지만, 안전을 위한다면 외부 5V 단독이 최선이다. 12V 2.5V DC 어댑터와 LM317을 이용한 스텝다운 모듈(아래 사진)이 있으니 양질의 5V를 공급하는 것은 당장 가능하다. 그러나 전원만 차단되는 USB 연장 케이블을 구하기는 아주 어려우니(데이터는 차단하고 충전만 제공하기 위한 제품은 흔히 구할 수 있음) USB 커넥터를 별도로 주문하여 직접 만들기로 하였다.
간단히 끝날줄 알았는데 그게 아니었다.
[업데이트] 전원부를 보강한 뒤 수정한 펌웨어로 테스트한 결과
PC <-> 아두이노 우노 연결은 일반 USB 케이블을 그대로 사용하되 레귤레이터를 통해 12V에서 5V로 낮춘 전원을 헤더쪽에 공급해 보았다. 이번의 펌웨어는 상태값을 기본 상태(base)와 에러 플래그(err)로 분리하여 출력하도록 만들었다. 반복하여 키보드를 연결하였을 때 100% 정확하게 인식되었으나 0x90은 일정한 위치에서 계속 따라다닌다. 맨 끝의 raw=18은 키보드를 분리했을 때의 메시지이다.
Ardule Bridge - USB MIDI Monitor (robust) USB Host Shield init OK Plug USB MIDI keyboard and play... [USB] raw=18 (0x12) base=18 (0x12) err=NO [USB] raw=32 (0x20) base=32 (0x20) err=NO [USB] raw=64 (0x40) base=64 (0x40) err=NO [USB] raw=80 (0x50) base=80 (0x50) err=NO [USB] raw=81 (0x51) base=81 (0x51) err=NO [USB] raw=144 (0x90) base=16 (0x10) err=YES CC | CH 1 | CC 64 | VAL 127 CC | CH 1 | CC 1 | VAL 34 CC | CH 1 | CC 7 | VAL 94 CC | CH 1 | CC 5 | VAL 12 CC | CH 1 | CC 2 | VAL 41 CC | CH 1 | CC 3 | VAL 70 CC | CH 1 | CC 4 | VAL 37 NOTE ON | CH 1 | NOTE 60 | VEL 88 NOTE OFF | CH 1 | NOTE 60 NOTE ON | CH 1 | NOTE 62 | VEL 77 NOTE OFF | CH 1 | NOTE 62 NOTE ON | CH 1 | NOTE 64 | VEL 85 NOTE OFF | CH 1 | NOTE 64 [USB] raw=18 (0x12) base=18 (0x12) err=NO
raw=144 (0x90) base=16 (0x10) err=YES의 의미에 대한 챗GPT의 해석은 다음과 같다.
이 의미는?
USB Host Library 2.0 계열에서:
-
0x51: CONFIGURED / RUNNING -
그 직후:
-
클래스 드라이버가 첫 엔드포인트 트래픽을 시작
-
첫 IN/OUT 트랜잭션 중
-
NAK
-
일시적 timeout
-
또는 class-specific 요청에 대한 지연 응답
→ USB 규격상 정상인 현상
-
-
하지만 라이브러리는 이걸:
-
“연결 실패”가 아니라
-
ERROR 비트(0x80)를 세트해 둡니다
그리고 중요한 포인트 👇
👉 이 err 비트는 자동으로 클리어되지 않습니다. (래치됨)
그래서:
-
매번 같은 타이밍에
-
항상
0x90이 “한 번 보이는 것”입니다.
왜 항상 “같은 위치”에서만 나오나?
이건 오히려 정상적인 결정론적 패턴입니다.
-
0x51= 열거 완료 -
그 다음 프레임에서:
-
첫 SOF
-
첫 인터럽트 IN 폴링
-
첫 클래스 초기화 동작
-
이 정확히 같은 지점에서
해당 키보드 + Host Shield + 라이브러리 조합이
“한 번 NAK/지연”을 만들고,
라이브러리는 그걸 ERROR로 기록하는 겁니다. //여기까지
결론은 이러하다. 지금의 0x90은 USB 열거 직후 첫 트래픽에서 발생하는 결정론적, 그리고 무해한 ERROR 플래그라서 정상 동작의 일부이다. 따라서 이러한 로직을 본 코드에 흡수하면 된다.
