2026년 5월 29일 금요일

Fluid Ardule, LCD의 외계어 표시를 없애다

Fluid Ardule의 UI 컨트롤러에 해당하는 아두이노 우노에는 I2C LCD 모듈이 연결되어 있다. 이것이 이따금 '외계어'를 표시하는 문제가 있었다. 가끔 일어나는 노이즈 문제라고 생각하기에는 그 빈도가 너무 잦았다. USB 커넥터를 뽑았다가 다시 연결해도 완벽하게 해결되지 않았다. 만약 내가 만드는 물건이 '상품'을 목표로 한다면, 도저히 시장에 내놓기 부끄러운 상태였다.


이 모습은 영화 <프레데터>에 나오는 Yautja 알파벳을 닮았다. 작년에 개봉한 <프레데터: 죽음의 땅> 관련 기사(LA Times 링크)에서는 이 문자와 언어 체계에 대한 상세한 정보가 담겨 있다. 



문제는 이것이 단순한 미관상의 문제가 아니라는 점이다. LCD는 Fluid Ardule의 보조 진단 장치 역할을 한다. 전원을 넣은 직후 상태를 알려주고, Raspberry Pi와 연결되었는지 여부도 표시한다. 따라서 화면이 깨진다는 것은 사용자가 장비를 신뢰하기 어렵다는 뜻이다. 설령 실제 기능은 정상이라 하더라도 말이다.

처음에는 I2C 통신 자체를 의심했다. 하지만 곧 이상한 사실을 발견했다. 외계어 현상은 Raspberry Pi와의 통신이 시작되기 전에도 발생한 적이 있었다. 그렇다면 원인이 Serial 통신에만 있는 것은 아니었다.

ChatGPT와 더불어 온갖 가설 수립과 실험을 해 보면서 생각이 조금씩 바뀌었다. 

문제는 LCD가 아니라 초기화 순서일 수 있었다.

UNO, PCF8574 I2C backpack, HD44780 LCD 컨트롤러는 전원이 들어온 뒤 각각 안정화되는 시간이 조금씩 다르다. 만약 Arduino가 너무 빨리 실행되어 lcd.init()를 호출한다면 LCD 쪽이 아직 완전히 준비되지 않았을 가능성이 있다.

전원을 넣으면 아두이노 우노가 켜지면서('cold start') LCD 모듈(컨트롤러 포함)에도 전원이 인가되어 자연스럽게 화면이 나온다. 이 때에도 외계어가 발생한 사례가 있었지만 매우 드물었다.

그러나 라즈베리 파이가 완전히 부팅되고 Fluid Ardule 서비스가 시작되면서 아두이노 우노와 USB를 통한 시리얼 통신을 수립하는 과정에서 우노는 다시 재시작될 수 있다. Arduino Uno의 기본 자동 리셋(auto-reset) 기능 때문이다.

이 경우 LCD는 계속 전원이 공급되고 있는데 우노만 다시 시작되는 상황이 발생한다. ChatGPT는 이러한 비대칭적인 재시작 과정이 LCD 상태 불안정의 한 원인일 가능성을 제기하였다. 다만 이것이 유일한 원인인지는 아직 단정할 수 없다.

그래서 RESET-GND 사이에 10µF 전해 콘덴서를 추가하는 실험을 했다.

이 콘덴서는 전원 안정화용이 아니다. RESET 핀의 상승 시간을 약간 늦추어 Arduino가 조금 더 늦게 시작하도록 만든다. 즉 LCD와 PCF8574가 충분히 준비된 뒤 초기화가 이루어질 가능성을 높이는 것이다.

놀랍게도 효과가 있는 것으로 보였다. 외계어 발생 빈도가 눈에 띄게 감소하였다.

그런데 이번에는 예상치 못한 부작용이 나타났다.

Arduino IDE에서 펌웨어를 업로드하려고 하자 갑자기 다음과 같은 오류가 발생했다.

not in sync: resp=0x55

한참 원인을 찾다가 문득 깨달았다. 10µF 콘덴서가 Arduino의 자동 리셋 기능까지 방해하고 있었던 것이다. 실제로 콘덴서를 제거하면 업로드가 정상적으로 이루어졌고, 다시 연결하면 동일한 문제가 재현되었다. 이는 콘덴서가 RESET 타이밍에 실제 영향을 주고 있음을 보여주는 간접적인 증거이기도 했다.

결국 콘덴서는 납땜된 상태로 두지 않고, 필요할 때 꽂았다 뺄 수 있는 탈착식 구조로 변경했다. 다음과 같은 프로토타입 실드를 쓰고 있기 때문에 소켓 헤더의 Rst와 GND에 전해 콘덴서를 필요한 때에 꽂는 것으로 충분하였다. 어제는 리셋 버튼 스위치 근처에 납땜을 하였었다.



그 과정에서 또 하나의 개선점을 발견했다.

현재 UNO-1 펌웨어는 전원 투입 시 LCD를 초기화하지만, Raspberry Pi와 처음 연결되는 순간에는 LCD를 다시 초기화하지 않는다. 그래서 최초 HELLO 메시지를 수신할 때 LCD를 한 번 더 재초기화하는 코드를 추가했다. 일종의 복구 계층을 만든 셈이다(Commit 0380f4a).

정리하면 현재 구조는 다음과 같다.

  • RESET-GND 10µF 콘덴서 → 예방 계층
  • HELLO 수신 시 LCD 재초기화 → 복구 계층

하나는 문제가 발생하지 않도록 돕고, 다른 하나는 혹시 문제가 생겨도 다시 정렬해 준다.

수정 후에는 서비스 재시작을 25회 이상 반복했지만 외계어 현상은 관찰되지 않았다. 물론 원래도 매우 낮은 빈도로 나타나던 문제였기 때문에 완전 해결을 선언하기는 이르다. 그러나 적어도 지금까지의 결과는 상당히 고무적이다.

돌이켜보면 이번 사건은 단순히 LCD 글자가 깨지는 문제를 해결한 것이 아니었다. 오히려 시스템의 초기화 시퀀스를 이해하게 된 과정에 가까웠다. 전원 투입, RESET 해제, LCD 초기화, Raspberry Pi와의 링크 수립이 서로 어떤 관계를 갖는지 다시 생각하게 만들었다.

가끔은 가장 작은 부품 하나가 가장 큰 교훈을 준다.

 

댓글 없음: