2026년 2월 1일 일요일

APS StepSeq 기능의 사소한 수정

Ardule Pattern Studio의 StepSeq에 몇 가지 편집 기능을 추가하다 

곡 전체에 해당하는 드럼 패턴 데이터를 자작 프로그램의 스텝 시퀀서 기능으로 찍어 보고 나서 개선 아이디어가 몇 가지 떠올랐다. 마디(bar) 단위로 데이터를 전부 지우거나, row(악기) 또는 column(스텝, 즉 시간) 단위로 한꺼번에 지우는 기능이 있으면 정말 편리할 것 같았다.

  • Shift + B(bar): 마디 전체 데이터 삭제
  • Shift + R(row): 악기 전체 데이터 삭제
  • Shift + C(column): 스텝 전체 데이터 삭제
모든 삭제 동작은 편집창에 띄운 해당 마디에서만 이루어진다.


Undo 기능은 별로 중요하지 않다. 저장하지 않고 상위 메뉴로 나갔다가 다시 'S'키를 눌러서 StepSeq 기능으로 들어오면 되니까 말이다. 

이런 소소한 편집 기능을 직접 만들고 있는 나 자신을 돌아보았다. 명령만 내리면 인공지능이 완벽한 수준의 음악을 만들어 주는 시대에 드럼 패턴 입용 스텝 시퀀서를 직접 코딩하고 있다니! 

드럼 악보 표기의 수수께끼

나는 드럼을 칠 줄 모르지만, 데이터를 직접 다루면서 드럼이라는 악기의 매력에 한층 더 다가간 것 같다. 정말 흥미로운 사실이지만 드럼 악보를 표기하는 방법은 아직도 완벽하게 통일되지 않았다고 한다. 인터넷을 검색하면 다음과 같이 드럼세트와 오선악보를 매칭시켜 놓은 그림이 자주 보인다. 누가 고안했는지 아주 이해하기 쉽다.

그림 출처: drumeo "How to read drum music (for beginners)"

심벌 계열의 악기는 특히 오선악보 표기법이 통일되어 있지 못하다. 국내외의 표기 관행이 다른 것도 문제이다. 예를 들어 내가 구한 드럼테라스의 <아니 근데 진짜> 드럼 악보(링크)를 보면 공부할 거리가 잔뜩 나온다. 이 악보 전체에서 라이드 심벌을 치라는 지시는 없었던 것 같다.

드럼 악보 표기의 수수께끼.

애초에 드럼이라는 악기의 연주 정보를 오선보로 표기하려는 시도 자체가 불가능한 것인지도 모른다. 라이드 심벌만 하더라도 컵과 엣지를 칠 때 매우 다른 소리가 나지 않는가? 이러한 상세한 지시사항은 음표가 아니라 글로 적어 놓아야 할 것이다. 디지털의 세계에서는 있을 수 없는 일이다. 기록과 재생에서 차이가 있을 수 없기 때문이다. 하지만 아날로그의 세계에서 기록이나 표준화는 그야말로 '최소한'일 뿐이다. 나머지를 이루는 대부분은 연주자의 재량에 맡겨질 뿐이며, 녹음된 음원도 일종의 레퍼런스인 셈이다.

어쩌면 내가 드럼 악보를 보면서 갖는 의문은 MIDI 프로그래밍 초급 교실에서 한번씩 다 훑고 지나가는 매우 기본적인 사항인지도 모른다. 그렇다 하더라도, 실제로 곡 전체의 리듬을 데이터로 다루고 직접 구현해 보지 않았다면 이런 질문에 도달하는 일은 없었을 것이다. 하드웨어-소프트웨어(펌웨어 포함)을 거쳐 오히려 드럼이라는 악기 연주의 본질에 더 가까이 다가갔다고나 할까.

APS로 만든 드럼 데이터 시험 연주

400개가 넘는 드럼 패턴 데이터(?)를 집대성하였으나 최신 기성곡에 딱 맞는 패턴을 골라서 쓰는 일은 쉽지 않다. Ardule Drum Patternology 생태계의 좋은 점은 드럼 패턴을 스텝 시퀀서에서 직접 입력할 수 있다는 것. 우리 밴드의 보컬리스트가 꼭 부르고 싶어 하는 LUCY의 <아니 근데 진짜>의 드럼 연주를 Ardule에서 생태계에서 구현해 보기로 하였다.

드럼 악보는 드럼테라스에서 사용에 제한 없이 제공하는 것(PDF 링크)을 입수하여 사용하였다. 드럼 악보 표기법을 잘 알지는 못하는 상태라서 약간의 어려움이 있었다. 특히 이 악보 체계에서는 크래시와 라이드 심벌을 때리는 방법을 구별하기가 어려웠다.

결국 보유한 패턴은 하나도 쓰지 못했고, 전부 새로 입력하였다. 하이햇의 닫힌 정도를 달리 하면서 타격하는 뉘앙스 차이를 완벽하게 반영하지는 못한다. 타격의 세기(velocity)도 0-약-중-강의 4단계가 전부이지만, 없는 것보다는 낫다. 총 35개의 패턴(2 마디 단위)를 입력하였다. 데이터를 입력하면서 APS 파이썬 스크립트에 남아 있던 약간의 버그를 수정하는 예기치 못한 좋은 일도 있었다.

섹션 정보를 넣을 수 있어서 곡 단위의 데이터 입력 및 편집이 쉽다. 이 곡에 사용한 패턴의 접두어는 'AGJ'이다. 짜의 머릿글자를 대충 따서 사용하였다.

템포는 142 BPM으로 상당히 빠르며 결코 쉬운 곡은 아닌 것 같다. 나는 드럼 연주자가 아니므로 그 어려움을 어떻게 이해하겠는가. 유튜브에서 원곡의 영상과 함께 템포를 맞추어 재생하면서 촬영을 해 보았다. 키보드 조작으로 재생을 하였으니 두 사운드가 서로 완벽하게 싱크가 맞을 수는 없다. 유튜브 쇼츠로도 올렸지만 자막이 너무 커서 화면을 많이 가린다.

올해에는 드러머가 참여하기 어려운 공연에서 이 시스템이 쓰일 수 있을 것이라고 믿는다. 여기까지 온 것도 정말 큰 성취가 아닐 수 없다.

2026년 1월 30일 금요일

IRIS 성과 입력 마감일에 불확정성의 원리를 생각해 보다

얼핏 비슷해 보이는 두 낱말, 결과성과는 같지 않다. 이 둘의 차이를 검색을 통해 알아보았다.

--- 여기부터 ---

성과(Performance/Outcome)는 목표 달성 여부와 영향력을 중시하는 고객·가치 중심의 개념인 반면, 결과(Result/Output)는 단순히 일을 수행하여 나온 1차적 산출물을 의미하는 공급자·실행자 중심의 개념입니다. 성과는 "무엇을 이루었는가"에 초점을 맞추며, 결과는 "무엇을 했는가"에 초점을 둡니다. 
  • 성과 (Outcome/Performance): 설정한 목표를 얼마나 달성했는지에 대한 가치나 영향력입니다. 고객 만족이나 조직의 비전 달성 등 의도된 바람직한 최종 상태를 의미합니다.
  • 결과 (Output/Result): 일을 수행함으로써 발생한 1차적인 결과물이나 수치입니다. 과정의 결과로 나타난 산출물 자체를 의미합니다. 
핵심 차이점:
  1. 방향성: 성과는 목적지(목표)에, 결과는 이동한 경로(행위)에 가깝습니다.
  2. 관점: 성과는 고객/상급자 지향적(무엇을 달성했나?)이고, 결과는 실행자 지향적(무엇을 했나?)입니다.
  3. 성격: 성과는 목적 지향적이며 성패를 평가하지만, 결과는 원인에 의해 야기된 모든 산출물을 포함합니다. 
즉, 100페이지 보고서를 작성한 것은 '결과'이며, 그 보고서를 통해 계약을 따낸 것은 '성과'입니다. 일을 열심히(결과) 하는 것을 넘어, 원하는 목표를 달성(성과)하는 것이 중요합니다. 

--- 여기까지 ---

오늘, 즉 2026년 1월 30일은 2025년도에 발생한 국가연구개발과제의 성과 정보를 IRIS, 즉 범부처통합연구지원시스템에서 입력하는 마감일이다. 너무나 당연한 이야기지만 과제 개시 이후에 발생한 성과만이 해당 과제의 것으로 온전히 인정받을 수 있다. 

연구재단에서 배포한 2025년도  성과입력 매뉴얼은 여기에 있다. 무려 230쪽! 빽빽한 문서가 아니라 파워포인트로 만들어진 것이라서 그나마 다행인데, 성과의 종류가 너무나 많다. 이러한 체계를 만든 연구재단, 그리고 IRIS를 개발하고 운영하는 KISTEP은 정말 수고가 많으심은 잘 알겠다.



논문은 가장 객관적이면서 증빙하기도 쉬운 성과라고 볼 수 있다. PMID만 넣어서 정보를 당겨올 수 있다면 얼마나 좋을까? 그렇지 않다. 모든 저자의 과학기술인번호를 입력해서 확인을 해야 하고(단순 입력도 가능한 것은 정말 고마운 노릇임), 사사(acknowledgement)에 따른 기여율도 퍼센트로 입력해야 한다. 논문의 시작과 끝 페이지를 입력하는 방법도 복잡하다. 요즘은 온라인으로만 출판하는 저널도 많기 때문에 페이지 번호가 별로 의미가 없는 경우가 많은데, 이러한 때에는 어떻게 해야 하는지 아주 친절하게 정보입력 매뉴얼에 적혀 있다.

후! 나라는 인간이 지금까지 성장하는데 아버지와 어머니는 몇 %나 기여했을까? 그것을 합 100%라 되게 산출하는 것이 가능할까? 원래 논문 작성에 도움을 준 사람에게 감사의 뜻을 표하기 위해 시작된 사사는 좀 이상한 방향으로 변질되어 이 연구성과에 기여한 연구과제를 적시하였는지 파악하는 근거가 되었다.

물론 이렇게 된 데에는 연구자의 책임도 크다. 대충 이름만 얹어서 논문의 공저자로서 출판을 하고, 'defense'를 해야 하는 연구과제가 여기에 기여했다고 역시 대충 쓰는 일이 너무 잦아지니 이렇게 연구자를 옭죄는 구조가 된 것 아니겠는가?

몇 가지 불평을 늘어 놓자면, 우선 IRIS 시스템의 안정성은 많이 좋아진 것 같다. 초장기에는 로그인에만 30분이 걸리고, 마감 연장을 한다는 공지가 뜨고, 늦게 제출한 것은 구제 불가라면 연장은 또 뭔지 불만이 가득하고... 이런 상황은 많이 좋아진 것으로 안다.

다만 너무 세부적인 사항을 일일이 과제책임자가 입력해야 하는지 그 효율성에 의문이 간다. 사실 성과라고 별도로 입력할 것이 아니라, 과제 보고서에 그 내용을 넣으면 되는 것 아닌가? 예를 들어 운영이나 저변 확대와 같은 과제라면 행사나 언론홍보 자체가 '결과'일 수 있고, 보고서에 넣으면 된다. 그런데 이를 '성과'라는 다른 말로 포장하여 보고서와 별개로 그 정보를 입력해야 한다니 답답하기만 하다.

정보 입력을 위한 매뉴얼도 너무 방대하다. 이 책자가 두껍고 상세하다는 것 자체가 IRIS 성과 입력 시스템이 지능적이고 고도화되었음을 입증하는 것은 결코 아니다. 내가 일하는 조직에서도 이러한 자료 입력 매뉴얼을 자주 만들어 배포하는데, 혹시 우리도 서비스 공급자 입장에서만 일을 하는 것은 아닌지 반성할 일이다.

결국 모든 것은 우리 삶의 곳곳에 스며든 '평가'를 어떻게 진행하고 또 받아들일까 하는 데서 기인한다. 국민의 소중한 세금이 들어갔으니 어떤 성과를 창출하였는지 평가를 받는 것은 타당한 일인데, 이러한 측정과 평가라는 것이 과정과 결과의 많은 부분을 왜곡하는 것도 사실이다. 이처럼 거시세계에서 벌어지는 일도 하이젠베르크의 불확정성 원리(양자역학 세계에서 일어나는)와 매우 닮았다. 관찰(대충 측정이나 평가와 비슷한 일이라고 해 두자)이 결과에 영향을 미친다. 나의 버전으로 고쳐 말하자면 평가는 행위의 의도나 결과에 영향을 주고, 심지어 왜곡까지 일으킨다.

성과를 측정하려는 제도가 연구의 방향을 바꾸고, 연구의 방향이 다시 성과의 정의를 바꾸는 순환에 들어간다. 성과가 좋았다고 최종 평가를 받아야 생존할 수 있으니까! 우리는 성과를 기록하는 것인가, 성과를 만드는 것인가? 이보다 현실 세계에서 훨씬 무서운 것은, 일선 공무원의 영향력이다... 이에 대해서는 말을 아끼고 싶다.

2026년 1월 25일 일요일

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

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

아두이노 식구 중에서 가장 먼저 구입했던 아두이노 우노(R3, ArduinoDocs의 자료)는 초창기에 몇 번의 간단한 실습을 한 것 외에는 별다른 용도를 찾지 못하고 있었다. (Nano) Ardule의 곁다리 프로젝트로서 계획하여 아주 최근 시작한 것은 USB MIDI host의 제작이다. USB 단자밖에 없는 MIDI controller keyboard를 DIN 5-pin MIDI 커넥터만 갖고 있는 MIDI 사운드 모듈에 연결하여 실시간 연주를 할 수 있는 중간 '어댑터'에 해당하는 것을 만들고 있었다. 원래 이런 상황에서는 USB host 역할을 할 PC와 USB MIDI cable이 있으면 된다. 이러한 경우 신호의 방향을 반대로 할 수도 있다. 하지만 컴퓨터가 없으면 매우 곤란하다.

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

아두이노 우노의 생태계에는 '메인 보드' 위에 겹쳐 꽂아서 기능을 확장할 수 있는 다양한 'shield'가 존재한다. USB host shield와 MIDI shield만 있으면 납땜 작업을 전혀 하지 않고 원하는 일을 이룰 수 있을 것이라 생각했다.

그런데 그게 아니었다.

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

두 번째 좌절. 아두이노 우노와 USB host shield는 양 옆 가장자리의 커넥터 외에도 ICSP(In-Cirtuit Serial Programming)라는 6핀 헤더를 통해 연결된다. 아두이노 우노에는 핀이, 위에 포개어 놓는 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는 이 작은 기기에게 지나치게 크다. 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년 1월 19일 월요일

아두이노 USB 호스트 실드를 사용하려면 보드 내에서 5V 패드를 납땜으로 연결해야 한다

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를 어떻게 공급하면 좋을까?

  1. 7~9V의 DC 어댑터가 있다면, 아두이노 우노의 어댑터 잭을 통해 꽂으면 된다. 내부적으로 선형 레귤레이터를 통해 5V로 낮추어서 제공하므로 발열이나 순간 전류에 취약하다.
  2. 가장 바람직한 것은 최소한 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 플래그라서 정상 동작의 일부이다. 따라서 이러한 로직을 본 코드에 흡수하면 된다. 


2026년 1월 17일 토요일

Nano Ardule의 MIDI 파일 재생 기능 개선

Nano Ardule의 펌웨어 개발이 이제 대부분의 기능 구현을 마쳤고 리팩토링 단계에 접어들었다고 바로 이전 글에서 호기롭게 선언하였지만, 아직 모든 것이 완벽하지는 않다. 가장 불편하다고 느끼는 것은 일반적인 type 0 MIDI file을 재생할 때 시작 부분에서 음이 와르르 쏟아지듯 들리는 것이다. 시작 포인트를 약간 지나서 음이 밀려서 쏟아져 나오면서 음 간격은 정상보다 더 좁게 느낀다. 다음 동영상(FLOURISH.MID)에서 첫번째 것이 코드 수정 전의 상태이다. 녹음이 썩 깨끗하게 되지는 않았지만 귀를 기울여 들어보면 뭔가 자연스럽지 않다는 것을 알 수 있다. 이후 두 번의 녹음은 한결 나아진 모습을 보인다.



이 현상을 'Starting Burst'라 부르기로 하고 원인 분석 및 해결에 나서기로 했다. 비상용 (드럼) 패턴이나 단일 패턴 재생에서는 관찰되지 않는다. 녹음한 사운드를 챗GPT에 업로드하여 분석을 실시하고, 이로부터 해결 방안을 도출하여 코드를 수정하는 사이클을 두 차례 걸쳤다. 문제의 원인은 타이밍 스케쥴링 에 있다고 판단하였다. 구체적인 원인 분석과 개선 전략은 별도의 글에 정리하였다. 완벽하게 문제가 해결되었다고 볼 수는 없으나, 실용적인 면에서는 이것으로 충분하다. 이 펌웨어는 type 0 MIDI 파일 재생을 목표로 하는 것이 아니기 때문이다. 드럼 전용 패턴 또는 ARR 파일의 재생은 아주 매끄럽게 잘 되고 있다.

만약 아두이노용 MIDI 라이브러리를 사용하여 펌웨어 개발을 했다면 이런 문제를 겪지 않았을지도 모른다. 그러나 그만큼 더 많은 메모리 공간이 필요하고, 내가 원하는 기능까지 넣는 것은 불가능하다고 판단하였었다. 그래서 다음과 같은 것이 전부 내가 만드는 펌웨어의 몫이었다.

  • MIDI 파일 파싱(VLQ, running status, meta event)
  • tick -> time 변환
  • 스케쥴러(catch-up, drift, blocking)
  • SD/IO의 블로킹 특성
  • MCU 타이밍(마이크로초/밀리초 해상도)

MIDI와 관련된 라이브러리를 전혀 사용하지 않은 '날것 코딩'을 선택하였기 때문에 MIDI 파일을 일단 재생하게 만드는 것조차 쉽지 않았다. 그러나 더욱 강력한 통제력을 얻을 수 있었다. 문제의 원인을 정확히 진단하고, 실용적으로 문제가 느껴지지 않는 수준까지(만) 개선하는 것. 충분히 합리적인 자세였다고 자체 판단하기로 했다.

몇 시간 지난 후 재평가를 해 보았다. 아직도 약간의 지연이 느껴져서 재생 시작 시 200 msec의 고정 지연 시각을 주었더니 훨씬 나아진 것 같다.

가끔 git push를 하다가 다음과 같은 메시지를 접하고 놀랄 때가 있다.

> git push
To https://github.com/jeong0449/NanoArdule.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/jeong0449/NanoArdule.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

README.md 같은 것을 GitHub 웹사이트에서 직접 고쳐 놓은 다음 로컬에 이를 반영하지 않은 상태에서 다른 파일을 고친 뒤 push를 하려다가 이런 일을 겪는다. 이때에는 'git pull origin main'(= git pull, 조건이 맞는 경우)을 실행한 뒤 git push 명령어를 날리면 된다. 'git status'에서 내가 지금 고친 파일만 눈에 뜨인다고 안심하고 있을 일이 아니다.



2026년 1월 16일 금요일

리팩토링 단계에 들어간 Nano Ardule 드럼 패턴 플레이어

리팩토링(refactoring)은 소프트웨어 공학의 전문 용어라고 한다. 코드의 외부 동작은 변경하지 않으면서 내부 구조를 개선하고 정리하는 작업이다. 마틴 파울러(Martin Fowler)의 저서 『Refactoring: Improving the Design of Existing Code』를 통해 널리 알려진 개념이라고 한다. 챗GPT와 더불어 코딩 작업을 하면서 이제 리팩토링 단계에 접어들었다는 말을 들었지만, 이렇게 정립된 개념이라는 것은 미처 알지 못하였다.

이미지 출처: 교보문고 


"Refactoring is a disciplined technique for restructuring existing code,
without changing its observable behavior."

이것은 마이크로SD카드가 인식 불능일 때 쓸 수 있도록 코드 안에 심어 놓은 'emergency payload' 드럼 패턴이다.

이 책의 내용을 친절하게 국문으로 정리한 리포지토리가 있어서 소개한다(링크). GitHub는 공동개발 및 코드 배포용으로만 쓴다고 생각을 했는데 문서 보관용으로도 쓸 수 있었다.

패턴 목록이 보이는 화면에서 인코더를 돌려서 6번을 선택하여 진입했다고 가정하자. 재생을 마친 뒤, 상위 메뉴로 복귀했을 때 커서가 여전히 6번에 있어야 하는가, 또는 1번으로 돌아가야 하는가? 현재까지의 동작은 1번으로 돌아가는 것이었다. 그러나 상위에서 하위 메뉴(목록)로 내려갈 때에는 언제나 1번부터 시작하는 것이 자연스럽지만, 그보다 하위 메뉴에서 목록으로 올라갈 때에는 원래의 위치에 있는 것이 낫다고 생각하여 개선을 진행하였다. 이것도 리팩토링인가? 단순한 UI 개선이라고 볼 수도 있으나. 기존 흐름을 더욱 일관되게 만드는 것이라서 전형적인 리팩토링이다.

구분분류
버튼 기능 추가새 롱프레스 동작기능 추가
재생 로직 변경BPM 처리 방식 변경기능 변경
커서 위치 기억상태 복원리팩토링
화면 문구 변경“Ready” → “Ready to Play”UI polish (리팩토링의 일부)

아두이노 나노에서 내가 원하는 드럼 패턴 재생 동작은 다 할 수 있게 된 것 같다. 코드의 가독성을 높이고, 내부에 어지럽게 널려 있는 한글 코멘트를 영문하하는 일이 남았다. 또다른 펌웨어인 MIDI controller는 EEPROM에 설정을 저장하고 불러오는 기능을 아직 더 넣어야 한다.

코딩의 능률은 Git/GitHub를 쓰면서 획기적으로 높아졌다. Git와 GitHub가 기여한 정도는 뚜렷하게 차이가 있다. Git는 버전 관리를 매우 편리하게 만들어 주었고, GitHub는 보다 책임감을 갖고 코드와 문서를 정리하는 동기를 부여해 주었다. 앞으로 이 두 가지의 도구가 없는 개발은 상상하기 어렵다. 문서는 GitHub 공개용과 내부용으로 철저히 나누었다. 공개용은 앞으로도 계속 기록으로 남을 것을 감안하여 매우 신중하게 작성하였고, 단기적인 목표와 개선 경험을 담은 내부용은 위키 사이트에만 두었다. 엄밀히 말하면 비공개는 아니다. 내부용 문서는 챗GPT에 작업 지시문과 더불어 업로드하니 시행착오를 크게 줄일 수 있었다. 

나의 삶을 리팩토링 대상으로 삼을 수 있을까? 삶에서 겉으로 보이는 것은 바뀌지 않지만 내부 구조를 개선한다면 그 이유는 무엇이겠는가? '유지보수'가 쉬워지고, 미래를 위한 대비를 감당할 여지가 생기기 때문이다. 당장은 드러나지 않는 내면의 변화란 비용이 드는 일이지만 그만한 가치가 있다.

다음은 어제 도착한 아두이노 우노용 USB 호스트 쉴드 및 MIDI 쉴드이다. USB MIDI 키보드 컨트롤러를 DIN 5P MIDI 커넥터가 달린 사운드 모듈에 연결하여 사용하기 위함이다. 할 일이 끊이지 않는다. 올해는 LibreCAD로 그린 앰프 상판도 주문하여 6V6 싱글 앰프를 다시 만드는 일도 기다리고 있는데...