9부까지는 4층 IO 보드 한 장의 이야기였습니다. 이번엔 새 보드입니다 — RP2040에 DC24V 입력, 옵토 절연 입력 4채널, 릴레이 출력 4채널, 4층 72×84 mm.

그리고 이번 편의 주제는 하나입니다.

한 문장 요약

미연결이 남았다는 것은 결론이 아니라, 다음 조사의 시작점입니다.

이번 작업에서 저는 “이건 물리적으로 불가능하다”고 세 번 결론 냈습니다. 세 번 다 틀렸고, 세 번 다 원인은 보드가 아니라 제 코드가 통로를 못 본 것이었습니다.


1. 제조 최소 사양은 “풀기 위해” 건드리는 변수가 아니다

비아 드릴 사양을 먼저 건드렸습니다. 배선이 안 빠지길래 비아를 0.35/0.20으로 줄였더니 문제가 풀렸습니다. DRC도 통과했습니다. 그런데 이건 푼 게 아니라 미룬 것이었습니다.

돌아온 지적은 명확했습니다.

“비아는 너무 작게 뚫으면 비아가 터지거나 내층이 정상으로 안 뚫린다. 라인도 마찬가지로 너무 얇으면 특수 PCB가 아닌 이상 정상으로 프린트되지 않는다.”

그래서 사양을 실측으로 고정했습니다. 사내 양산 CAM 9세트의 드릴 테이블을 전부 열어 보니 최소 드릴이 예외 없이 0.300~0.305 mm였습니다. 설계 원본의 비아 스택도 같은 말을 했습니다: 표준 비아 드릴 0.305 / 패드 0.610.

교차검증도 됐습니다. 9장 전부에서 이 셋이 정확히 일치합니다.

보드의 비아 개수  =  드릴 1번 툴(0.30) 개수  =  0.61 패드 어퍼처 개수
예)  352 = 352 = 352,   173 = 173 = 173

여기서 얻은 규칙은 이겁니다.

제조 사양을 낮춰서 풀리는 문제는 대개 푼 게 아니라 미룬 것입니다. 사양은 마지막까지 고정 변수로 두고, 움직이는 것은 배선과 배치입니다.

그래서 빌드 마지막에 비아 게이트를 넣었습니다. 규격 미달 비아가 하나라도 있으면 빌드가 멈춥니다. 규칙을 문서에만 적으면 지켜지지 않습니다 — 코드로 박아야 지켜집니다.


2. 0.4 mm 피치 옆에는 비아가 “안 들어가는 게 맞다”

QFN-56 핀 피치는 0.4 mm입니다. 여기에 표준 비아를 놓으려면 얼마가 필요한지 산수로 확인했습니다.

비아 반지름 0.300 + 클리어런스 0.150 + 이웃 배선 반폭 0.075 = 0.525 mm
필요 0.525  >  가용 0.400        → 안 된다

이건 도구 결함이 아니라 진짜 기하입니다. 그런데 여기서 제가 틀린 건 결론이었습니다. “비아가 안 들어가니 이 핀은 못 뺀다”고 했는데, 애초에 거기에 비아를 놓을 이유가 없었습니다. 핀에서는 선만 평행 차선으로 빼고, 보드가 열리는 지점까지 나간 다음 거기서 층을 바꾸면 됩니다.

막힌 것은 “핀 옆에 비아”였지 “그 핀의 탈출”이 아니었습니다. 안 되는 것을 정확히 좁히지 않으면, 되는 것까지 같이 포기하게 됩니다.

QFN 주변 탈출 배선 확대

풀린 뒤의 MCU 주변입니다. 핀에서 나온 선들이 평행 차선으로 곧게 빠져나가고, 비아는 그 차선이 끝나 자리가 생기는 지점에 모여 있습니다. 핀 바로 옆에 구멍이 하나도 없는 것이 이 그림의 요점입니다.


3. “물리적으로 불가능” 세 번, 전부 도구 결함

제가 내린 결론실제 원인
“차선 끝이 갇혀서 못 나간다”패드 크기를 GetSizeX/Y(패드 자기 좌표계)로 재서 회전 부품에서 가로세로가 뒤바뀜
“미로가 경로를 못 찾는다”격자 0.10이 팽창에 한 칸을 더해, 0.288 mm 여유를 0.325 필요로 오판
“패드가 완전히 둘러싸였다”접지 포어를 벽으로 취급해서, 1 mm 비어 있는 곳을 막힌 것으로 봄

세 번 다 화면상으로는 “보드가 꽉 찼다”로 보였습니다. GetSizeX/Y 함정은 이 프로젝트에서만 세 번 밟았습니다.

그래서 순서를 규칙으로 만들었습니다.

  1. 좌표로 잽니다. 인상이 아니라 숫자로. 여유 vs 필요폭.
  2. 여유가 필요폭보다 크면 도구를 의심합니다.
  3. 판정 기준을 통일합니다. 마감 루프와 최종 게이트가 다르게 재면, 루프는 자기 기준으로만 좋아지고 게이트는 계속 끊김을 봅니다.
  4. 그래도 남으면 배치를 바꿔 다시 돌립니다.

4. 배치를 사람이 고르면 재현이 깨진다 — 루프 안에 넣었다

배치 탐색 루프(위 4번)가 이번 편의 핵심입니다. 배치를 바꾸면 결과가 실제로 달라집니다.

바꾼 것미연결
QFN 여유(halo) 4.0 → 6.09 → 4
QFN 위치 (30,26) → (36,30)4 → 2
라우터 1회 → 5회 중 최선1~9로 흔들리던 것이 1로 안정

여기서 하나 더 알게 된 게 있습니다. 라우터 편차가 배치보다 큽니다. 같은 입력으로 미완주가 1에서 20까지 나옵니다. 편차가 지배하면 그걸 없애려 애쓸 게 아니라 자동화 안에 집어넣으면 됩니다 — 여러 번 돌려서 가장 좋은 것을 씁니다. 복권이 아니라 정해진 비용입니다(시도 수 × 라우팅 시간).

그래서 최종 형태는 이렇게 됐습니다.

후보 배치를 순회하며 전 파이프라인을 돌린다
  ├ 라우팅은 매번 5회 시도해 미완주가 가장 적은 것을 채택
  ├ 미연결 0 + 단락 0 이면 즉시 중단하고 저장
  └ 후보를 다 돌아도 0이 아니면 → 라우터 시도 배가 → 보드 확대(76×88 → 80×92 …)

포인트는 후보를 다 돌고도 끝내지 않는다는 것입니다. 부품이 보드를 꽉 채운 경우가 아니라면, 열릴 때까지 단계를 올립니다.


5. 정작 제일 많이 잡아먹은 건 “루프 자체가 죽는 방식”이었다

자동화 인프라에서 시간이 녹았습니다. 배치 루프를 돌리기 시작하자 배선이 아니라 거기서 시간이 갔고, 네 가지 전부 조용히 틀리는 종류였습니다.

① 두 빌드가 같은 보드 파일을 썼습니다. 앞 빌드가 아직 도는데 락 파일을 rm으로 밀어버렸습니다. 결과가 섞였습니다. → 락은 지우는 게 아니라 작업 디렉터리를 분리하는 것이 답입니다.

② 작업 사본의 트리 위치를 안 지켰습니다. 스크립트가 ROOT = 상위의 상위 로 공유 라이브러리를 찾는데, 보드 폴더만 복사하니 FootprintLoadNone을 돌려주고 배치가 통째로 죽었습니다.

③ 사본을 만드는 sed 한 줄이 문법 오류였습니다. 그래서 실행 스크립트가 아예 만들어지지 않았고, 후보 12개가 전부 “실패”로 집계됐습니다. 로그가 0줄이라는 게 신호였는데 늦게 봤습니다.

후보가 전부 똑같이 실패하면 후보를 의심할 게 아니라 루프를 의심해야 합니다. 12개가 하나도 빠짐없이 같은 지점에서 죽는 건 설계 문제일 수가 없습니다.

④ 살아 있는 빌드를 제가 죽였습니다. 파이프의 grep이 블록 버퍼링을 해서, 멀쩡히 돌던 빌드가 로그상 멈춘 것처럼 보였습니다. “죽었네” 하고 전역 taskkill을 세 번 했습니다. 병렬로 돌던 후보가 전부 같이 죽었고, 저는 그걸 “후보가 완주를 못 했다”고 읽었습니다.

→ 살았는지 죽었는지는 로그가 아니라 프로세스 목록으로 판단합니다. 진행을 보고 싶으면 bash -x 추적(stderr, 무버퍼)을 씁니다.


6. 배치 루프가 찾은 결과

배치 루프가 찾은 답은 제가 “실측으로 최적”이라 믿던 값이 아니었습니다.

U1(36, 30), 여유 5.0, 보드 72×84     →  미연결 0 / 단락 0

스윕에서는 여유 6.0이 더 좋아 보였는데, 실제로 0을 낸 건 5.0이었습니다. 라우터 편차가 그만큼 크다는 뜻이고, 그래서 사람이 스윕 표를 보고 고르는 것보다 루프가 끝까지 도는 편이 낫습니다.

미연결 0에 도달한 보드의 배선

루프가 찾아낸 배치로 다시 깐 결과입니다. 주황이 상면, 초록이 내층 배선이고 빨강은 내층 평면입니다. 아래쪽 릴레이 구역이 성기고 위쪽 MCU 구역이 빽빽한 것이 이 보드의 성격을 그대로 보여줍니다 — 막히는 곳은 언제나 같은 자리였습니다.

부품이 올라간 하면 — 이 보드는 109개 중 95개가 이쪽에 있다

같은 보드의 하면입니다. 가운데 정사각형이 0.4 mm 피치 QFN이고, 그 둘레로 저항과 커패시터가 촘촘히 붙어 있습니다. 위 배선 그림에서 빽빽하던 구역이 실제로는 이런 모습입니다 — 부품이 이만큼 몰려 있으니 탈출 통로가 그렇게 좁았던 것입니다.

검증은 루프가 낸 숫자를 믿지 않고 다시 쟀습니다.

항목결과
넷리스트NETS MATCH
DRC 3회(최악값)미연결 0, 단락 0
남은 위반starved_thermal 1 (서멀 릴리프 — 없애면 납땜이 안 되므로 그대로 뒀습니다)
비아 215개전부 0.60/0.30 이상
각도자유각 0

이번 편에서 얻은 규칙

“안 된다”는 보고서를 닫기 전에 네 단계를 다 밟았는지 확인합니다: 좌표 · 도구 · 판정 기준 · 배치.

  • 제조 최소 사양은 마지막까지 고정 변수입니다. 낮춰서 풀리면 미룬 것입니다
  • 안 되는 것을 정확히 좁힙니다 — “핀 옆 비아”가 막힌 것과 “그 핀의 탈출”이 막힌 것은 다릅니다
  • 편차가 지배하면 편차를 자동화 안에 넣습니다(best-of-N)
  • 후보가 전부 똑같이 실패하면 루프를 의심합니다
  • 로그가 멈춘 것처럼 보인다고 죽은 게 아닙니다 — 프로세스로 확인합니다
  • 배치 선택을 사람 손에 두면 재현이 깨집니다. 루프 안에 있어야 합니다

미연결이 남았다는 것은 결론이 아니라, 좌표 · 도구 · 판정 기준 · 배치를 차례로 확인하라는 신호입니다.

다음 편에서는 이 보드를 사내 양산 도면 9장과 나란히 놓고 뜯어본 이야기를 쓸 생각입니다. 카파(구리 포어)를 어떻게 까는지, 거버에서 무엇을 읽을 수 있고 무엇을 읽으면 안 되는지 — 거기서 제가 예전에 잘못 적어둔 수치 하나도 정정하게 됐습니다.


▶️ 11부 — 220V 절연 장벽: 이번엔 계통 전압이 올라오는 판입니다. 절연 장벽을 재는 제 격자가 KiCad DRC와 열 번 어긋났고, 열 번 다 제 쪽이 더 관대했습니다.

🔧 시리즈 전체: 1부 · 2부 · 3부 · 4부 · 5부 · 6부 · 7부 · 8부 — 완성 · 9부 — 리뷰

문의