RS485 센서를 폴링해서 LoRa로 올리는 노드를 만들어 뒀는데, 보드 세 장이 책상에 굴러다니는 상태였습니다. 케이스가 필요했습니다.
- 구성: RAK19011 베이스보드 + RAK11310 LoRa 코어 + TTL↔RS485 변환보드
- 입출력: 5V 어댑터(DC잭) · RS485 3극 터미널 · SMA 외부 다이폴 안테나
- 결과: 109 × 80 × 28 mm, 2피스 나사 조립, STL 2개
- 도구: Blender 5.1 + BlenderMCP + Claude Code
지난번 3D 케이스 4종 제작기와 같은 스택인데, 이번엔 훨씬 많이 틀렸습니다. 그게 이 글의 내용입니다.

센서를 RS485로 물어보고 그 값을 LoRa로 올리는 노드입니다. 이 글은 가운데 회색 상자 — 세 보드를 담는 케이스 — 만 다룹니다.
케이스보다 먼저 있던 것들
펌웨어와 도구는 이미 돌고 있었습니다. 무선을 뚫고(1부), 센서를 흉내 내고(2부), 폴링과 감시 창을 만드는(3부) 일이 끝난 뒤였습니다.
케이스는 그걸 담을 상자가 없어서 만든 것입니다. 보드 세 장이 책상에 굴러다니는 상태를 제품으로 만드는 일이 남았습니다.
시작부터 전원모듈 링크 하나를 잘못 읽었다
“RAK19011 보드에 로라 모듈과 전원모듈 [알리 링크] 사이트에 첨부한 모듈을 이용하여 제품을 만드려고 하는데 케이스가 필요해”
AliExpress 상품 링크를 문장 그대로 읽고 전원모듈로 받아들였습니다. 그런데 AliExpress가 봇 차단으로 상품 페이지를 안 열어줬습니다. WebFetch도, 브라우저도 footer만 로드됐습니다.
여기서 갈림길이 있었습니다. 가격대(₩2,580)와 문맥으로 “소형 DC-DC 벅 컨버터겠거니” 하고 넘어갈 수도 있었습니다. 실제로 그렇게 넘어갔고, 케이스 내부에 벅 컨버터 자리까지 잡았습니다.
몇 번의 문답 뒤에 실체가 나왔습니다.
“첨부한 링크의 RS485 변환 보드를 이용해서 TTL 레벨을 RS485로 변경하여 통신을 하고 있어”
전원모듈이 아니라 RS485 변환보드였습니다. 전원은 5V 어댑터 직결이라 벅 컨버터 자체가 필요 없었습니다. 케이스 내부 배치를 통째로 다시 잡았습니다.
열리지 않는 자료는 추측하지 말고 물어봐야 합니다. 당연한 이야기인데, “문맥상 뻔하다”는 느낌이 들 때 가장 잘 깨집니다.
데이터시트 도면에서 좌표 뽑기
RAK19011 보드 외형은 직사각형이 아닙니다. 계단형 다각형이고 마운팅홀 4개가 비대칭으로 박혀 있습니다. 그리고 RAKwireless 데이터시트의 치수 도면에는 홀 좌표가 전부 명시되어 있지 않습니다. 이미지로만 있고 일부 치수선만 붙어 있습니다.
STEP 파일을 찾아봤지만 없었습니다. 그래서 도면 이미지에서 직접 뽑기로 했습니다.
마운팅홀이 색으로 칠해져 있다
RAK 도면은 마운팅홀 4개를 연두색으로 강조해 뒀습니다. 색 필터로 클러스터 중심을 잡으면 눈대중보다 훨씬 정확합니다.
gray = (abs(r-g)<10) & (abs(g-b)<10) & (r>70) & (r<120) # 보드 회색
# 연두색 링 클러스터 4개 -> 중심 픽셀 좌표
스케일은 알려진 치수로 잡고, 다른 치수로 검증한다
도면에 명시된 두 값(좌상단 홀 X=13.50, 우상단 홀 X=52.00)으로 X 스케일을 구했습니다.
S = (641.0 - 300.2) px / (52.00 - 13.50) mm = 8.8519 px/mm
그리고 이 스케일로 다른 홀을 계산했더니 좌하단 홀이 X=5.00 mm가 나왔습니다. 도면에 적힌 값과 정확히 일치. 스케일이 맞다는 독립 검증이 된 셈입니다.
Y축에서 한 번 헤맸다
X는 한 번에 맞았는데 Y가 안 맞았습니다. 보드 하단이 계단형이라 원점을 어디로 잡을지 헷갈렸기 때문입니다. 좌측부 하단과 우측 돌출부 하단이 5 mm 차이가 납니다.
결국 보드 최상단·최하단 픽셀을 X 스케일로 역산해서 원점을 확정했습니다.
| 홀 | X (mm) | Y (mm) | 도면 대조 |
|---|---|---|---|
| 좌상 | 13.50 | 56.80 | 도면 57.00 ✓ |
| 우상 | 52.00 | 64.12 | — |
| 좌하 | 5.00 | 9.95 | 좌측단 5.00 + 계단 5.00 ✓ |
| 우하 | 52.00 | 2.70 | 도면 2.70 ✓ |
홀 지름도 같은 방법으로 쟀습니다. Ø2.29~2.44, 패드 Ø4.5 — M2입니다.

Blender MCP의 boolean 함정
Blender MCP의 boolean 적용을 거치는 중간에 뚜껑이 통째로 사라졌습니다. 정확히는 작은 원통(3.4 × 3.4 × 8.75)으로 변해 있었습니다.
원인은 bpy.ops.object.modifier_apply였습니다. 이 환경에서는 target과 cutter가 뒤집혀 적용됩니다. 뚜껑에서 나사홀을 빼려고 했는데 나사홀 실린더에서 뚜껑을 빼는 결과가 나온 것입니다. 단계별로 dimensions를 찍어보고서야 어디서 깨지는지 잡았습니다.
1 plate (99.0, 80.0, 2.5)
2 ring (93.6, 74.6, 3.0)
3 joined (99.0, 80.0, 5.5) <- 여기까진 정상
4 holes (3.4, 3.4, 13.75) <- 여기서 깨짐

bpy.ops를 버리고 depsgraph로 직접 메쉬를 굽는 방식으로 바꾸니 해결됐습니다. 컨텍스트에 의존하지 않아서 안정적입니다.
def bake(obj):
"""modifier_apply 가 target/cutter 를 뒤집으므로 depsgraph 로 직접 굽는다."""
dg = bpy.context.evaluated_depsgraph_get()
me = bpy.data.meshes.new_from_object(obj.evaluated_get(dg))
obj.modifiers.clear()
old = obj.data
obj.data = me
if old.users == 0:
bpy.data.meshes.remove(old)
def bop(target, cutter, op):
m = target.modifiers.new('B', 'BOOLEAN')
m.object = cutter; m.operation = op; m.solver = 'EXACT'
bake(target)
bpy.data.objects.remove(cutter, do_unlink=True)
return target
STL 출력 전 조립 간섭검사를 붙였다
조립 간섭검사는 STL을 뽑기 전에 자동으로 보게 했습니다. 두 오브젝트를 복제해서 INTERSECT boolean을 걸고, 결과 메쉬의 부피를 재는 방식입니다.
def inter(o1, o2, label):
a = dup(o1, 'ca'); b = dup(o2, 'cb')
m = a.modifiers.new('B', 'BOOLEAN')
m.object = b; m.operation = 'INTERSECT'; m.solver = 'EXACT'
bake(a)
bm = bmesh.new(); bm.from_mesh(a.data)
print('%-24s %9.4f %s' % (label, bm.calc_volume(),
'OK' if len(bm.verts) == 0 else '*** 간섭 ***'))
이건 진짜 잡아냈다
STL 직전 검사에서 조립 불가 3건이 걸렸습니다.
- 뚜껑 립 ↔ 코너 나사보스 — 립 코너(X 46.8
48.8)와 보스(X 4249)가 겹쳐서 뚜껑이 아예 안 닫히는 상태였습니다. 립 코너에 7.6 × 7.6 노치를 냈습니다. - 통풍 슬릿 ↔ 립 — 최상단 슬릿이 립과 같은 높이대라 립이 슬릿을 안에서 막고 있었습니다. 슬릿 4단을 3.5 mm씩 내렸습니다.
- 개구 cutter가 보스를 파먹음 — 벽만 잘라야 하는데 cutter를 Y로 20 mm 뻗어놔서 안쪽 나사보스에 구멍이 뚫렸습니다. cutter 두께를 벽 두께 + 2 mm로 제한했습니다.
이 셋은 그대로 뽑았으면 필라멘트만 버렸을 것들입니다.
간섭검사가 못 잡은 조립 불가가 더 많았다
간섭검사가 못 잡은 조립 불가, 여기부터가 진짜입니다. 간섭검사가 계속 0.0000 mm³ OK를 찍는 동안 조립 불가가 세 번 더 나왔습니다. 전부 사람이 잡았습니다.
1. “모듈 고정은 어떻게 해? 그냥 공중에 띄우라는 거야?”
제가 “보드는 리브 포켓에 앉히고 뚜껑이 눌러 고정합니다”라고 설명했습니다. 그런데 뚜껑에 누르는 구조물을 실제로 만들지 않았습니다. 뚜껑은 평판 + 립뿐이었고, 보드 위로 18 mm 공간이 비어 있었습니다. 누를 수가 없습니다.
RS485 변환보드는 더 심했습니다. 렌더의 그 박스는 공간 표시용 더미였을 뿐 고정 수단이 아예 없었습니다.
설명과 모델이 어긋나 있었는데, 검사는 이걸 볼 수 없습니다. 없는 형상은 간섭도 안 나기 때문입니다.
2. “터미널 블럭이 뚜껑 홀 부분이랑 간섭나는데”
검사 결과는 BASE n RS485_term 0.0000 OK였습니다. 통과였습니다.
그런데 실제 여유가 0.5 mm였습니다. 3D 프린트 공차, 터미널블럭 높이 추정치, 조립 시 손이 들어갈 공간을 생각하면 0.5 mm는 간섭입니다. 저는 숫자가 0이라는 이유로 통과시켰습니다.
여유를 4 mm로 늘렸습니다.
| 항목 | 전 | 후 |
|---|---|---|
| 터미널 ↔ 코너 나사보스 | 0.5 mm | 4.0 mm |
| 터미널 ↔ 뚜껑 립 | (미확인) | 5.4 mm |
| 배선 여유 | 7.5 mm | 11.0 mm |
3. 플랫폼이 납땜 돌기를 누르고 있었다
RS485 보드를 받치려고 바닥에 3 mm 높이 플랫폼을 깔았습니다. 보드 밑면 전체를 받치는 판입니다.
검사에서는 문제가 없었습니다. 더미 PCB를 평평한 판으로 모델링했기 때문입니다. 실물 PCB 밑면에는 스루홀 납땜 돌기가 있습니다. 평평한 판으로 받치면 그게 눌립니다.
플랫폼을 걷어내고 보스 4개만 남겼습니다. 지금은 보드 밑면 아래가 4 mm 비어 있습니다.
4. 커넥터 몸통이 보드를 뚫고 지나갔다
처음엔 DC잭과 RS485 터미널을 후면 벽 한가운데, 그러니까 메인보드 바로 뒤에 배치했습니다. 보드 뒤 여유는 4 mm였습니다.
패널마운트 DC잭은 몸통이 안으로 20 mm쯤 들어옵니다. 4 mm 뒤에 보드가 있으면 부딪힙니다. 검사가 못 잡은 이유는 간단합니다 — 잭 몸통을 모델링하지 않았기 때문입니다. 뚫은 건 구멍뿐이었습니다.
커넥터를 전부 보드가 없는 우측 베이와 보드 위 높이로 옮겼습니다.
- DC잭 · RS485 → 우측 베이(보드 없음)
- SMA → 전면이되 z=14 mm, 즉 보드 윗면 위로 지나감

5. 그리고 보스가 아예 없었다
가장 오래 못 잡은 것. 나사 보스와 포켓 리브를 만들어 넣고, 렌더를 보고 “잘 됐다”고 넘어갔습니다. 실제로는 바닥에 붙는 형상이 전부 사라져 있었습니다.
원인은 Blender EXACT solver의 coplanar UNION입니다. 보스 하단면(z=2.5)이 케이스 바닥 상면(z=2.5)과 정확히 일치하면 UNION이 조용히 실패합니다. 에러도 없고 형상만 없어집니다.
간섭검사는 이걸 절대 못 잡습니다. 없는 형상은 간섭도 안 나니까 계속 0.0000 OK였습니다. 렌더로도 못 알아봤습니다 — 벽 모서리와 통풍 슬릿 그림자를 리브로 착각했습니다.
결국 “형상이 실제로 있느냐”를 묻는 검사를 따로 만들고서야 발견했습니다. 있어야 할 자리에 작은 원기둥을 놓고 케이스와 INTERSECT해서 부피를 재는 방식입니다.
def probe(x, y, z0, z1, r=1.5):
"""(x,y) 의 z0~z1 구간에 실체가 있는지 부피로 확인. 0 이면 아무것도 없다."""
a = dup(base)
p = cylinder(r, z1 - z0, (x, y, (z0 + z1) / 2))
intersect(a, p)
return volume(a)
결과가 이랬습니다.
[RAK19011 마운팅 보스] vol= 0.00 *** 없음 *** (4곳 전부)
[RAK19011 포켓 리브] vol= 0.00 *** 없음 *** (4곳 전부)
[RS485 마운팅 보스] vol= 0.00 *** 없음 *** (4곳 전부)
[RS485 포켓 리브] vol= 0.00 *** 없음 *** (3곳 전부)
[코너 나사보스] vol= 12.19 OK
코너 나사보스만 살아 있었습니다. 이건 바닥에서 z=8부터 시작해 바닥과 안 닿는 유일한 형상이었습니다. 그게 결정적인 힌트였습니다.
수정은 한 줄입니다. 바닥에 얹히는 형상을 바닥 안으로 0.5 mm 파고들게 만들면 접촉면이 일치하지 않아 UNION이 정상 동작합니다.
MERGE = 0.5 # 바닥에 얹히는 UNION 형상은 바닥을 파고들게 (coplanar UNION 회피)
base = bop(base, cyl('t', POST_D/2, STANDOFF + MERGE,
(x, y, FLOOR + STANDOFF/2 - MERGE/2)), 'UNION')
고친 뒤 19개 형상 전부 PASS. 그때서야 렌더에 보스와 리브가 나타났습니다.

간섭검사가 못 보는 것들의 공통점
다섯 번의 조립 불가는 다 같은 구조였습니다.
간섭검사는 제가 모델링한 형상끼리만 봅니다. 모델에 없는 것은 검사도 없습니다.
- 납땜 돌기 → 더미 PCB가 평평한 판이라 모델에 없음
- 잭 몸통 → 구멍만 뚫고 몸통은 모델링 안 함
- 조립 여유 → 0.5 mm도 수학적으로는 0 mm³
- 누름 구조 → 말로만 설명하고 형상은 안 만듦
- 사라진 보스 → 형상 자체가 없으니 간섭이 날 리가 없음
마지막이 제일 고약합니다. 앞의 넷은 검사가 덜 본 경우지만, 이건 검사가 정상 동작하면서 정반대 결론을 준 경우입니다. 형상이 사라질수록 간섭검사 점수는 좋아집니다. 그래서 검사를 세 종류로 나눴습니다.
| 검사 | 묻는 것 | 통과 조건 |
|---|---|---|
| 간섭 | 서로 겹치나? | 0 mm³ |
| 존재 | 있어야 할 게 있나? | 0보다 큼 |
| 여유 | 충분히 떨어졌나? | mm 실측값 |
여유는 부피가 0인지만 보지 않고 실제 거리를 mm로 찍게 했습니다.
--- 여유 실측 ---
터미널 뒤끝 Y=26.50 / 코너보스 앞면 Y=30.50 -> 여유 4.00 mm
터미널 윗면 z=17.10 / 뚜껑 립 밑면 z=22.50 -> 여유 5.40 mm
DC잭 몸통 끝 X=25.50 / RS485 플랫폼 시작 X=26.70 -> 여유 1.20 mm
이렇게 놓으면 “0인가?”가 아니라 “충분한가?”를 묻게 됩니다.
RS485 변환보드 좌표도 제품 이미지에서
RS485 변환보드 마운팅홀 위치를 물었더니 제품 이미지를 받았습니다. 53 mm와 21.7 mm 치수선이 그려진 그림이었습니다.
RAK 도면과 같은 방법을 썼습니다. 빨간 PCB 영역의 bbox로 스케일을 잡고, 보드 내부의 밝은 원을 라벨링해서 중심을 뽑았습니다.
red = (r>110) & (r-g>45) & (r-b>45) # 보드 영역
bright = (r>225) & (g>225) & (b>225) & inside # 내부 구멍
lab, n = ndimage.label(bright)
# 면적 250px 이상 + 가로세로 차 6px 이내(원형)만 채택
교차검증이 잘 됐습니다. X 스케일과 Y 스케일 비가 1.013 — 도면이 왜곡 없이 그려졌다는 뜻입니다.
| 홀 | X (mm) | Y (mm) | 지름 (mm) |
|---|---|---|---|
| 좌하 | 4.11 | 2.88 | 3.69 |
| 좌상 | 4.08 | 18.84 | 3.63 |
| 우하 | 36.05 | 2.98 | 3.37 |
| 우상 | 35.97 | 18.80 | 3.46 |
Y 중심이 10.86이고 보드 높이가 21.7이니 정확히 절반. 대칭이 맞습니다. 지름 3.4~3.7이면 M3입니다.
자를 대고 재는 것보다 이게 빠르고 정확했습니다. 치수선이 하나라도 그려진 이미지면 좌표를 뽑을 수 있습니다.
LoRa 노드 케이스 최종 사양




| 항목 | 값 |
|---|---|
| 외형 | 109 × 80 × 28 mm |
| 내부 | 104 × 75 × 23 mm, 벽 2.5 mm |
| 구조 | 2피스 (본체 + 뚜껑), 립 3 mm 끼워맞춤 |
| RAK19011 고정 | M2 × 6 mm ×4 — 보스 Ø4.5, 셀프탭 Ø1.7 |
| RS485 고정 | M3 × 6~8 mm ×4 — 보스 Ø5.5, 셀프탭 Ø2.5 (물림 5.5 mm) |
| 뚜껑 | M3 × 12~16 mm ×4 |
| 후면 | DC잭 Ø8 + RS485 3극 개구, 5V DC / A B G 음각 |
| 전면 | SMA Ø6.5, ANT 음각 |
| 기타 | 측면 통풍 슬릿 4단 × 양쪽, 바닥 고무발 자리 10 × 10 |
STL은 둘 다 non-manifold 0, 바닥 z=0 정렬. 뚜껑은 평판이 베드에 닿고 립이 위로 향하게 뒤집어 내보내서 서포트가 필요 없습니다.
파라메트릭 스크립트라 상단 파라미터만 바꾸면 전체가 재생성됩니다. 아직 확인 못 한 값(보드 위 실장 높이 18 mm 추정)에는 [미확정] 주석을 달아 뒀습니다.
세부



뚜껑 립 코너를 사각으로 잘라낸 게 보입니다. 여기가 코너 나사보스와 부딪혀 뚜껑이 안 닫히던 자리입니다.

배운 것 — 간섭 0과 조립 가능은 다른 질문이다
1. “간섭 0”과 “형상 있음”은 완전히 다른 질문입니다. 형상이 사라지면 간섭검사 점수는 오히려 좋아집니다. 만들어 넣은 게 실제로 거기 있는지 묻는 검사를 따로 두지 않으면, 없어진 걸 영영 모릅니다.
2. 간섭 0은 조립 가능이 아닙니다. 여유를 mm로 정하고 그 기준으로 봐야 합니다. 부피가 0인지만 보면 0.5 mm짜리 함정을 그대로 통과시킵니다.
3. 더미 모델의 단순함이 그대로 검사의 맹점이 됩니다. 평평한 PCB 더미는 납땜 돌기를 모르고, 구멍만 뚫은 벽은 잭 몸통을 모릅니다. 검사 결과를 신뢰하려면 모델이 실물의 어디까지 담고 있는지를 먼저 알아야 합니다.
4. 설명과 모델이 어긋날 수 있습니다. “뚜껑이 눌러서 고정합니다”라고 써 놓고 누르는 구조물을 안 만들었습니다. 말로 설명한 기능은 모델에서 형상으로 확인해야 합니다.
5. 렌더는 증거가 아닙니다. 벽 모서리와 슬릿 그림자를 리브로 착각해서 “잘 됐다”고 넘어갔습니다. 눈으로 본 것보다 숫자로 잰 것을 믿어야 합니다 — 단, 그 숫자가 맞는 질문에 답하고 있을 때만요.
6. 못 여는 자료는 물어봅니다. 링크 하나를 문맥으로 때웠다가 케이스 내부 배치를 통째로 다시 잡았습니다.
7. 도면 이미지는 치수선 하나면 좌표가 나옵니다. 단 반드시 교차검증할 것. X 스케일로 뽑은 값이 도면의 다른 치수와 맞는지, X/Y 스케일 비가 1에 가까운지 — 이게 맞아야 그 좌표를 믿을 수 있습니다.
다섯 번의 “이렇게 하면 조립이 안 되잖아”가 없었으면 지금쯤 안 맞는 케이스를 두어 개 뽑아 놓고 원인을 찾고 있었을 겁니다.
자동 검사는 빠릅니다. 그런데 이번에 가장 오래 숨어 있던 결함은 검사가 못 본 것이 아니라, 검사가 정상 동작하면서 통과시킨 것이었습니다. 보스가 통째로 사라진 케이스에 대고 “간섭 0 mm³, 이상 없음”이라고 계속 답하고 있었으니까요. 검사는 제가 던진 질문에만 답합니다. 무엇을 묻지 않고 있는지는 알려주지 않습니다.
간섭 0 mm³는 조립 가능이 아니라, 모델에 있는 형상끼리만 안 부딪힌다는 뜻입니다.
▶️ 다음 편 — 서버는 OK를 주는데 절반이 사라진다: 이 케이스에 담긴 노드들을 Class C 폴링으로 모아 서버로 올렸더니, 5분마다 보낸 데이터가 10분 간격으로만 쌓였습니다. 원인을 세 번 잘못 짚은 이야기입니다.
🔧 시리즈 전체: 1부 — 무수신과 sync word · 2부 — 센서 시뮬레이터 · 3부 — 기다리지 않는 폴러 · 4부 (이 글) · 5부 — 전송 디버깅
문의
- Email : [email protected]
- Insta : https://www.instagram.com/going.sen/
- Website : https://intosen.com/kr/consult/
댓글
닉네임만 입력하면 바로 댓글을 남길 수 있어요. Google/GitHub 로그인도 가능합니다.