From 892e9d04c6538d47071e2a98749f648d740f2c7e Mon Sep 17 00:00:00 2001 From: "DESKTOP-PUHFO60\\dsx2016" Date: Sat, 17 Oct 2026 15:20:09 +0800 Subject: [PATCH] Optimize case v1.1 with rounded corners and FDM cantilever snaps. Adds catch windows, locating pegs, and a snap coupon for print tuning; keep lip alignment and rear DHT bay. Co-authored-by: Cursor --- README.md | 11 +- cad/README.md | 42 ++-- cad/export/back.stl | Bin 55684 -> 94284 bytes cad/export/front.stl | Bin 28084 -> 105184 bytes cad/export/mate.json | 14 +- cad/export/snap_coupon.stl | Bin 0 -> 12484 bytes cad/generate_stl.py | 395 ++++++++++++++++++++++++++----------- cad/viewer.html | 7 +- 8 files changed, 331 insertions(+), 138 deletions(-) create mode 100644 cad/export/snap_coupon.stl diff --git a/README.md b/README.md index a59b3ce..6e22b0a 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ pio device monitor -b 115200 ## 3D 外壳 -桌面斜立分体壳(前框 + 后盖支架 + DHT11 通风仓),可直接打印: +v1.1 圆角分体壳(前框 + 后盖 + 四侧悬臂卡扣 + 后盖 DHT 卡位),可直接打印: -- STL:[`cad/export/front.stl`](cad/export/front.stl)、[`cad/export/back.stl`](cad/export/back.stl) +- STL:[`cad/export/front.stl`](cad/export/front.stl)、[`cad/export/back.stl`](cad/export/back.stl)、[`cad/export/snap_coupon.stl`](cad/export/snap_coupon.stl)(试打卡扣) - 浏览器预览:[`cad/viewer.html`](cad/viewer.html)(需本地 HTTP,见下) -- 参数源 / 说明:[`cad/README.md`](cad/README.md) +- 参数与打印建议:[`cad/README.md`](cad/README.md) ```bash # 浏览器查看 @@ -53,11 +53,11 @@ python -m http.server 8765 --directory cad # 打开 http://localhost:8765/viewer.html # 重新导出 STL -pip install trimesh manifold3d numpy +pip install trimesh manifold3d numpy shapely python cad/generate_stl.py ``` -固定用 `4 × M3×10`;DHT11 装后盖通风仓,线接 CN1。 +合盖以卡扣为主、止口对齐;四角 `M3×10` 可选。建议 PETG;DHT11 装后盖背面卡位,线接 CN1。 ## 项目结构 @@ -112,3 +112,4 @@ git reset --hard v1.0-case-closed | 2026-10-17 | 外壳改定:DHT11 后盖卡位微突出;前后盖止口合盖 | | 2026-10-17 | 去掉旁侧多余凸块;修复合盖对齐;DHT 改为后盖平面卡位 | | 2026-10-17 | 打标签 `v1.0-case-closed` 作为可回滚稳定版 | +| 2026-10-17 | 外壳 v1.1:外圆角 R3.5、四侧悬臂卡扣、定位柱、卡扣试打样件 | diff --git a/cad/README.md b/cad/README.md index e95b16b..813330a 100644 --- a/cad/README.md +++ b/cad/README.md @@ -1,21 +1,39 @@ -# CYD 温湿度仪表盘 3D 外壳 +# CYD 温湿度仪表盘 3D 外壳(v1.1) -## 结构说明(当前版) +## 结构说明 -只有两件:**前框** + **后盖**。 +只有两件:**前框** + **后盖**。外轮廓圆角 R=3.5mm,主要靠 **4 处悬臂卡扣** 合盖(止口仍保留对齐;四角 M3 可选)。 | 部位 | 作用 | |------|------| -| 前框 | 屏窗;公止口,合盖时插入后盖 | -| 后盖 | 装板子;母止口;**背面中心 DHT11 卡位通风口**(探头微突出约 1.6mm) | -| DHT 示意 | 预览里蓝色/灰块,表示传感器装在后盖背面卡位里 | +| 前框 | 屏窗;公止口;长边各 2 根悬臂卡扣(钩朝外) | +| 后盖 | 装板子;母止口;卡扣窗口 + 卡台;**背面中心 DHT11 卡位通风口**(探头微突出约 1.6mm) | +| 定位柱 | 四角短 peg / 孔,合盖防错位 | +| `snap_coupon.stl` | 单独试打卡扣样件,调间隙后再打整壳 | -**没有**外壳旁边的大“格子”。旧版里那两块是:侧向支脚块、外挂 DHT 仓——已删除,避免误解。 +**没有**外壳旁边的大“格子”(旧支脚块 / 外挂仓已删)。 + +## 卡扣参数(按 FDM 常见经验) + +参考悬臂卡扣实践(应变控制、根部过渡、配合间隙、PETG 反复开合更稳): + +| 参数 | 本壳取值 | 说明 | +|------|----------|------| +| 自由臂长 L | 11 mm | 偏短可再加长降低应变 | +| 根厚 / 尖厚 | 1.7 → 0.95 mm | 锥形臂,应力分散 | +| 钩深 undercut | 0.75 mm | 含 lead-in 斜面 | +| 侧向间隙 | 0.45 mm | FDM 合盖/卡扣常用约 0.4–0.5 | +| 止口间隙 | 0.45 mm | 同左 | +| 材料建议 | **PETG** | PLA 可试装,反复开合易脆 | + +打印:卡扣臂尽量落在 **XY 弯曲平面**(不要让弯曲撕开层层)。先打 `snap_coupon.stl`,太紧就略加大间隙或减钩深。 ## 合盖 -前框止口落入后盖槽;预览默认合盖(开合度 0%)。 -对齐数据在 `export/mate.json`。 +前框止口落入后盖槽,卡扣钩入后盖窗口卡台;预览默认合盖(开合度 0%)。 +对齐数据在 `export/mate.json`(`version: 1.1-snaps`)。 + +稳定旧版(无卡扣、仅止口)标签:仓库根 README 的 `v1.0-case-closed`。 ## 浏览器预览 @@ -31,11 +49,13 @@ python -m http.server 8765 --directory cad ## 导出 STL ```bash -pip install trimesh manifold3d numpy +pip install trimesh manifold3d numpy shapely python cad/generate_stl.py ``` +输出:`export/front.stl`、`back.stl`、`snap_coupon.stl`、`mate.json`。 + ## 装配 1. DHT11 从**后盖背面**按入中心卡位,探头朝外略突出,线进腔内接 CN1/GPIO22 -2. CYD 放入后盖,前框合盖,四角 M3×10 可选固定 +2. CYD 放入后盖,前框对准止口/定位柱合盖,听四侧卡扣入位;四角 M3×10 可选 diff --git a/cad/export/back.stl b/cad/export/back.stl index 6d61b3968d0da925013ab0114ba0a1bd123e52ef..cf91c0801f02512426365eb4aa321998858061f1 100644 GIT binary patch literal 94284 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 luE6b^Y;(GZeQ=Vi|h8cT(z$^|7XNx1apYE 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 literal 55684 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 HuKD;clv1=G literal 0 HcmV?d00001 diff --git a/cad/generate_stl.py b/cad/generate_stl.py index 8ef61ce..3ab41ff 100644 --- a/cad/generate_stl.py +++ b/cad/generate_stl.py @@ -1,31 +1,59 @@ #!/usr/bin/env python3 """ -CYD climate case — clean clamshell. +CYD climate case v1.1 — rounded clamshell + FDM snap clips. -- Front: screen bezel + male lip -- Back: cavity + female groove + DHT11 snap pocket flush in back wall (tip proud ~1.6mm) -- No side “boxes”: removed bulky stand block and external DHT hang-on bay +Design refs (FDM snap-fit best practice): + - Cantilever L≈12–16mm, root t≈1.6–2.0mm, width≥5mm + - Undercut ≈0.7mm, lead-in ≈35°, root fillet ≥0.5·t + - Mating clearance ≈0.4–0.5mm (FDM) + - Prefer PETG for repeated open/close; print snap arms in XY bend plane + +Features: + - Outer R=3.5mm / inner R≈2.0mm rounded shell + - 4 side cantilever snaps (front) + catch windows (back) + - Corner locating pegs / sockets for 合盖对齐 + - DHT11 flush rear pocket with slight proud grill + - Optional M3 bosses kept as backup """ from __future__ import annotations +import json from pathlib import Path +import numpy as np import trimesh -from trimesh.creation import box, cylinder +from shapely.geometry import Point, box +from trimesh.creation import cylinder, extrude_polygon +# ---- board ---- PCB_L, PCB_W = 86.0, 50.0 MH_INSET = 4.0 DISP_X, DISP_L, DISP_W, DISP_H = 8.0, 69.0, 50.0, 4.0 VIEW_L, VIEW_W, VIEW_IX, VIEW_IY = 59.5, 45.0, 7.0, 2.5 -WALL, GAP = 2.4, 0.35 + +# ---- shell ---- +WALL, GAP = 2.4, 0.40 +CORNER_R = 3.5 +INNER_R = 2.0 BEZEL_T = 2.2 CAVITY = 8.0 -LIP_H, LIP_CLEAR = 2.2, 0.2 +LIP_H = 2.0 +LIP_CLEAR = 0.45 # FDM clearance around lip USB_W, USB_H, USB_Y = 15.0, 9.0, 30.5 SCREW, BOSS_OD, BOSS_ID = 3.3, 7.0, 2.5 -# DHT11 module pocket (from OUTSIDE of back face z=0) +# ---- snap (cantilever) ---- +SNAP_W = 6.5 +SNAP_L = 11.0 # free length +SNAP_T_ROOT = 1.7 +SNAP_T_TIP = 0.95 +SNAP_HOOK = 0.75 # undercut +SNAP_LEAD = 0.9 # lead-in ramp height along arm +SNAP_CLEAR = 0.45 # side gap around moving arm +SNAP_Z_ROOT = 1.2 # root starts below front rim into skirt + +# ---- DHT ---- DHT_L, DHT_W, DHT_H = 16.0, 12.5, 7.5 DHT_PROUD = 1.6 @@ -34,8 +62,7 @@ INNER_W = PCB_W + 2 * GAP OUTER_L = INNER_L + 2 * WALL OUTER_W = INNER_W + 2 * WALL SKIRT = DISP_H + 1.0 -# Back total height to mating plane (top of female groove floor) -BACK_BODY_H = WALL + CAVITY # rim starts here +BACK_BODY_H = WALL + CAVITY FRONT_BODY_H = BEZEL_T + SKIRT MH = [ @@ -45,6 +72,17 @@ MH = [ (MH_INSET, PCB_W - MH_INSET), ] +# snap centers along long sides (x), inset from ends +SNAP_XS = [OUTER_L * 0.28, OUTER_L * 0.72] + + +def rounded_prism(l: float, w: float, h: float, r: float, z0: float = 0.0) -> trimesh.Trimesh: + r = min(r, l / 2 - 0.05, w / 2 - 0.05) + poly = box(r, r, l - r, w - r).buffer(r, resolution=8) + mesh = extrude_polygon(poly, height=h) + mesh.apply_translation([0, 0, z0]) + return mesh + def aabb(x0, y0, z0, x1, y1, z1) -> trimesh.Trimesh: xa, xb = sorted((float(x0), float(x1))) @@ -52,8 +90,8 @@ def aabb(x0, y0, z0, x1, y1, z1) -> trimesh.Trimesh: za, zb = sorted((float(z0), float(z1))) dx, dy, dz = xb - xa, yb - ya, zb - za if min(dx, dy, dz) < 1e-6: - raise ValueError(f"degenerate {[xa, ya, za, xb, yb, zb]}") - m = box(extents=[dx, dy, dz]) + raise ValueError(f"degenerate box {xa,ya,za,xb,yb,zb}") + m = trimesh.creation.box(extents=[dx, dy, dz]) m.apply_translation([xa + dx / 2, ya + dy / 2, za + dz / 2]) return m @@ -65,168 +103,295 @@ def U(*ms: trimesh.Trimesh) -> trimesh.Trimesh: return r -def D(a: trimesh.Trimesh, *ss: trimesh.Trimesh) -> trimesh.Trimesh: +def Diff(a: trimesh.Trimesh, *ss: trimesh.Trimesh) -> trimesh.Trimesh: r = a for s in ss: r = r.difference(s, engine="manifold") return r -def make_front() -> trimesh.Trimesh: +def cantilever_snap(x_center: float, y_wall: float, outward_sign: int) -> trimesh.Trimesh: """ - Z=0: outer screen face - Z=FRONT_BODY_H: open rim with male lip extending to FRONT_BODY_H+LIP_H + Snap arm on front: root near FRONT_BODY_H, extends +Z (into back when closed). + Hook faces outward (+/- Y). + outward_sign: +1 for +Y wall (hook +Y), -1 for -Y wall. """ - body = aabb(0, 0, 0, OUTER_L, OUTER_W, FRONT_BODY_H) - hollow = aabb(WALL, WALL, BEZEL_T, OUTER_L - WALL, OUTER_W - WALL, FRONT_BODY_H + 1) + # Build in local: arm along +Z, thickness in Y, width in X + # Root fillet approximated by stepped thickening + pieces = [] + n = 6 + for i in range(n): + t = i / (n - 1) + # taper thickness root -> tip + th = SNAP_T_ROOT * (1 - t) + SNAP_T_TIP * t + z0 = FRONT_BODY_H - SNAP_Z_ROOT + t * (SNAP_L + SNAP_Z_ROOT) + z1 = FRONT_BODY_H - SNAP_Z_ROOT + (t + 1 / n) * (SNAP_L + SNAP_Z_ROOT) + 0.05 + # arm sits inside wall face, hook later + if outward_sign > 0: + y0 = y_wall - WALL + SNAP_CLEAR + y1 = y0 + th + else: + y1 = y_wall + WALL - SNAP_CLEAR + y0 = y1 - th + pieces.append(aabb(x_center - SNAP_W / 2, y0, z0, x_center + SNAP_W / 2, y1, z1)) + arm = U(*pieces) + + # hook wedge at tip (lead-in ramp) — min thickness keeps manifold volumes valid + tip_z = FRONT_BODY_H - SNAP_Z_ROOT + SNAP_L + SNAP_Z_ROOT + hook_steps = [] + for i in range(5): + t = (i + 1) / 5 # start above 0 so h>0 + h = max(0.25, SNAP_HOOK * min(1.0, t / 0.55)) + z0 = tip_z - SNAP_LEAD + (i / 5) * SNAP_LEAD + z1 = tip_z - SNAP_LEAD + ((i + 1) / 5) * SNAP_LEAD + 0.08 + if outward_sign > 0: + y0 = y_wall - WALL + SNAP_CLEAR + SNAP_T_TIP + y1 = y0 + h + else: + y1 = y_wall + WALL - SNAP_CLEAR - SNAP_T_TIP + y0 = y1 - h + hook_steps.append(aabb(x_center - SNAP_W / 2 + 0.4, y0, z0, x_center + SNAP_W / 2 - 0.4, y1, z1)) + return U(arm, *hook_steps) + + +def catch_window(x_center: float, y_wall: float, outward_sign: int) -> trimesh.Trimesh: + """Opening / ledge cut in back wall for snap hook.""" + # Window through wall where hook passes, then a ledge below for catch + win_h = SNAP_L + 2.5 + z0 = BACK_BODY_H - 1.0 + z1 = z0 + win_h + if outward_sign > 0: + return aabb( + x_center - SNAP_W / 2 - SNAP_CLEAR, + y_wall - WALL - 0.2, + z0, + x_center + SNAP_W / 2 + SNAP_CLEAR, + y_wall + 0.6, + z1, + ) + return aabb( + x_center - SNAP_W / 2 - SNAP_CLEAR, + y_wall - 0.6, + z0, + x_center + SNAP_W / 2 + SNAP_CLEAR, + y_wall + WALL + 0.2, + z1, + ) + + +def catch_ledge(x_center: float, y_wall: float, outward_sign: int) -> trimesh.Trimesh: + """Internal ledge the hook seats under (retention).""" + z0 = BACK_BODY_H + 0.3 + z1 = z0 + 1.4 + if outward_sign > 0: + return aabb( + x_center - SNAP_W / 2 + 0.3, + OUTER_W - WALL - 0.2, + z0, + x_center + SNAP_W / 2 - 0.3, + OUTER_W - WALL + SNAP_HOOK + 0.3, + z1, + ) + return aabb( + x_center - SNAP_W / 2 + 0.3, + WALL - SNAP_HOOK - 0.3, + z0, + x_center + SNAP_W / 2 - 0.3, + WALL + 0.2, + z1, + ) + + +def make_front() -> trimesh.Trimesh: + body = rounded_prism(OUTER_L, OUTER_W, FRONT_BODY_H, CORNER_R, 0) + hollow = rounded_prism(INNER_L, INNER_W, FRONT_BODY_H + 1, INNER_R, BEZEL_T) + hollow.apply_translation([WALL, WALL, 0]) + out = Diff(body, hollow) + + # view + pocket vx = WALL + GAP + DISP_X + VIEW_IX vy = WALL + GAP + VIEW_IY - view = aabb(vx - 0.2, vy - 0.2, -0.5, vx + VIEW_L + 0.2, vy + VIEW_W + 0.2, BEZEL_T + 0.5) - + out = Diff(out, aabb(vx - 0.2, vy - 0.2, -0.5, vx + VIEW_L + 0.2, vy + VIEW_W + 0.2, BEZEL_T + 0.5)) sx = WALL + GAP + DISP_X - 0.2 - pocket = aabb( - sx, WALL + GAP - 0.1, BEZEL_T - 0.05, - sx + DISP_L + 0.4, WALL + GAP + DISP_W + 0.1, BEZEL_T + DISP_H + 0.6, + out = Diff( + out, + aabb(sx, WALL + GAP - 0.1, BEZEL_T - 0.05, sx + DISP_L + 0.4, WALL + GAP + DISP_W + 0.1, BEZEL_T + DISP_H + 0.6), ) - out = D(body, hollow, view, pocket) - # male lip: thin wall ring protruding past rim - lip_out = aabb( - WALL - 1.0, WALL - 1.0, FRONT_BODY_H - 0.05, - OUTER_L - (WALL - 1.0), OUTER_W - (WALL - 1.0), FRONT_BODY_H + LIP_H, - ) - lip_in = aabb( - WALL + LIP_CLEAR, WALL + LIP_CLEAR, FRONT_BODY_H - 0.2, - OUTER_L - WALL - LIP_CLEAR, OUTER_W - WALL - LIP_CLEAR, FRONT_BODY_H + LIP_H + 0.5, - ) - out = U(out, D(lip_out, lip_in)) + # male lip (rounded ring approx via outer-inner) + lip_out = rounded_prism(OUTER_L - 1.2, OUTER_W - 1.2, LIP_H, CORNER_R - 0.6, FRONT_BODY_H - 0.05) + lip_out.apply_translation([0.6, 0.6, 0]) + lip_in = rounded_prism(INNER_L + LIP_CLEAR * 2, INNER_W + LIP_CLEAR * 2, LIP_H + 0.6, INNER_R, FRONT_BODY_H - 0.2) + lip_in.apply_translation([WALL - LIP_CLEAR, WALL - LIP_CLEAR, 0]) + out = U(out, Diff(lip_out, lip_in)) + # locating pegs (导柱) near corners — stick into back sockets + pegs = [] + for px, py in [(8.0, 8.0), (OUTER_L - 8.0, 8.0), (OUTER_L - 8.0, OUTER_W - 8.0), (8.0, OUTER_W - 8.0)]: + peg = cylinder(radius=1.4, height=LIP_H + 2.2, sections=20) + peg.apply_translation([px, py, FRONT_BODY_H + (LIP_H + 2.2) / 2 - 0.3]) + pegs.append(peg) + out = U(out, *pegs) + + # 4 snaps on long sides + snaps = [] + for x in SNAP_XS: + snaps.append(cantilever_snap(x, OUTER_W, +1)) + snaps.append(cantilever_snap(x, 0.0, -1)) + out = U(out, *snaps) + + # optional screw holes (backup) for px, py in MH: - hole = cylinder(radius=SCREW / 2 + 0.1, height=FRONT_BODY_H + LIP_H + 4, sections=28) + hole = cylinder(radius=SCREW / 2 + 0.1, height=FRONT_BODY_H + LIP_H + 6, sections=24) hole.apply_translation([WALL + GAP + px, WALL + GAP + py, FRONT_BODY_H / 2]) - out = D(out, hole) + out = Diff(out, hole) out.merge_vertices() return out def make_back() -> trimesh.Trimesh: - """ - Z=0: exterior back face (DHT grill here, slightly proud) - Z=BACK_BODY_H: mating plane; female groove from BACK_BODY_H to BACK_BODY_H+LIP_H - """ total_h = BACK_BODY_H + LIP_H - body = aabb(0, 0, 0, OUTER_L, OUTER_W, total_h) - cavity = aabb(WALL, WALL, WALL, OUTER_L - WALL, OUTER_W - WALL, total_h + 1) - out = D(body, cavity) + body = rounded_prism(OUTER_L, OUTER_W, total_h, CORNER_R, 0) + cavity = rounded_prism(INNER_L, INNER_W, total_h + 1, INNER_R, WALL) + cavity.apply_translation([WALL, WALL, 0]) + out = Diff(body, cavity) - # female groove: cut a channel in the top rim for the male lip - # outer wall of groove - groove = aabb( - WALL - 1.0 - LIP_CLEAR, WALL - 1.0 - LIP_CLEAR, BACK_BODY_H + 0.1, - OUTER_L - (WALL - 1.0 - LIP_CLEAR), OUTER_W - (WALL - 1.0 - LIP_CLEAR), total_h + 0.2, - ) - groove_keep = aabb( - WALL + 0.05, WALL + 0.05, BACK_BODY_H - 0.1, - OUTER_L - WALL - 0.05, OUTER_W - WALL - 0.05, total_h + 0.3, - ) - out = D(out, D(groove, groove_keep)) + # female groove for lip + groove = rounded_prism(OUTER_L - 0.8, OUTER_W - 0.8, LIP_H + 0.3, CORNER_R - 0.4, BACK_BODY_H + 0.1) + groove.apply_translation([0.4, 0.4, 0]) + keep = rounded_prism(INNER_L + 0.2, INNER_W + 0.2, LIP_H + 0.6, INNER_R, BACK_BODY_H - 0.1) + keep.apply_translation([WALL - 0.1, WALL - 0.1, 0]) + out = Diff(out, Diff(groove, keep)) + + # locating sockets + for px, py in [(8.0, 8.0), (OUTER_L - 8.0, 8.0), (OUTER_L - 8.0, OUTER_W - 8.0), (8.0, OUTER_W - 8.0)]: + sock = cylinder(radius=1.55, height=3.2, sections=20) + sock.apply_translation([px, py, BACK_BODY_H + 1.4]) + out = Diff(out, sock) + + # snap catch windows + ledges + for x in SNAP_XS: + out = Diff(out, catch_window(x, OUTER_W, +1)) + out = Diff(out, catch_window(x, 0.0, -1)) + out = U(out, catch_ledge(x, OUTER_W, +1)) + out = U(out, catch_ledge(x, 0.0, -1)) # USB uy0 = WALL + GAP + USB_Y - USB_W / 2 - out = D(out, aabb(-0.5, uy0, WALL + 1.0, WALL + 1.0, uy0 + USB_W, WALL + 1.0 + USB_H)) + out = Diff(out, aabb(-0.5, uy0, WALL + 1.0, WALL + 1.0, uy0 + USB_W, WALL + 1.0 + USB_H)) - # button holes + # buttons for y in (12.0, 22.0): - btn = cylinder(radius=2.2, height=WALL + 2, sections=20) + btn = cylinder(radius=2.2, height=WALL + 2, sections=18) btn.apply_translation([WALL + GAP + 10, WALL + GAP + y, WALL / 2]) - out = D(out, btn) + out = Diff(out, btn) - # screw bosses + # M3 bosses backup bosses = [] for px, py in MH: x, y = WALL + GAP + px, WALL + GAP + py - boss = cylinder(radius=BOSS_OD / 2, height=CAVITY - 0.5, sections=28) + boss = cylinder(radius=BOSS_OD / 2, height=CAVITY - 0.5, sections=24) boss.apply_translation([x, y, WALL + (CAVITY - 0.5) / 2]) - hole = cylinder(radius=BOSS_ID / 2, height=CAVITY + 1, sections=20) + hole = cylinder(radius=BOSS_ID / 2, height=CAVITY + 1, sections=18) hole.apply_translation([x, y, WALL + CAVITY / 2]) - bosses.append(D(boss, hole)) + bosses.append(Diff(boss, hole)) out = U(out, *bosses) - # ---- DHT11 flush pocket in back wall (NOT a side box) ---- - # Center on back face - cx = OUTER_L * 0.5 - cy = OUTER_W * 0.5 - # Pocket carved from outside into wall+cavity enough for module - pocket = aabb( - cx - DHT_L / 2 - 0.3, cy - DHT_W / 2 - 0.3, -0.05, - cx + DHT_L / 2 + 0.3, cy + DHT_W / 2 + 0.3, WALL + DHT_H - 1.0, + # DHT pocket + proud rounded grill + cx, cy = OUTER_L / 2, OUTER_W / 2 + out = Diff( + out, + aabb(cx - DHT_L / 2 - 0.3, cy - DHT_W / 2 - 0.3, -0.05, cx + DHT_L / 2 + 0.3, cy + DHT_W / 2 + 0.3, WALL + DHT_H - 1.0), ) - out = D(out, pocket) - - # Snap rails (卡位) left/right inside pocket — thin ledges - rail_z0, rail_z1 = 1.2, 1.2 + 2.2 - left = aabb(cx - DHT_L / 2 - 0.3, cy - 3.2, rail_z0, cx - DHT_L / 2 + 1.0, cy + 3.2, rail_z1) - right = aabb(cx + DHT_L / 2 - 1.0, cy - 3.2, rail_z0, cx + DHT_L / 2 + 0.3, cy + 3.2, rail_z1) - # bottom stop (prevents falling inward) - stop = aabb(cx - 5, cy - DHT_W / 2 + 0.5, WALL + DHT_H - 2.2, cx + 5, cy + DHT_W / 2 - 0.5, WALL + DHT_H - 1.0) - out = U(out, left, right, stop) - - # Proud grill ring on exterior (the only intentional protrusion) - grill_ring = aabb( - cx - DHT_L / 2 - 1.0, cy - DHT_W / 2 - 1.0, -DHT_PROUD, - cx + DHT_L / 2 + 1.0, cy + DHT_W / 2 + 1.0, 0.05, + out = U( + out, + aabb(cx - DHT_L / 2 - 0.3, cy - 3.2, 1.2, cx - DHT_L / 2 + 1.0, cy + 3.2, 3.4), + aabb(cx + DHT_L / 2 - 1.0, cy - 3.2, 1.2, cx + DHT_L / 2 + 0.3, cy + 3.2, 3.4), + aabb(cx - 5, cy - DHT_W / 2 + 0.5, WALL + DHT_H - 2.2, cx + 5, cy + DHT_W / 2 - 0.5, WALL + DHT_H - 1.0), ) - grill_hole = aabb( - cx - DHT_L / 2 + 1.5, cy - DHT_W / 2 + 1.5, -DHT_PROUD - 0.2, - cx + DHT_L / 2 - 1.5, cy + DHT_W / 2 - 1.5, 0.2, + # rounded proud grill via buffered square + grill_poly = box(cx - DHT_L / 2 - 0.8, cy - DHT_W / 2 - 0.8, cx + DHT_L / 2 + 0.8, cy + DHT_W / 2 + 0.8).buffer( + 1.2, resolution=6 ) - # slot vents in proud face + grill = extrude_polygon(grill_poly, height=DHT_PROUD + 0.1) + grill.apply_translation([0, 0, -DHT_PROUD]) + hole_poly = box(cx - DHT_L / 2 + 1.6, cy - DHT_W / 2 + 1.6, cx + DHT_L / 2 - 1.6, cy + DHT_W / 2 - 1.6).buffer( + 0.8, resolution=5 + ) + ghole = extrude_polygon(hole_poly, height=DHT_PROUD + 0.4) + ghole.apply_translation([0, 0, -DHT_PROUD - 0.2]) slots = [] for i in range(4): - slots.append(aabb( - cx - 5 + i * 2.8, cy - 4.5, -DHT_PROUD - 0.2, - cx - 5 + i * 2.8 + 1.2, cy + 4.5, 0.2, - )) - out = U(out, D(grill_ring, grill_hole, *slots)) - - # tiny wire path already open via pocket into cavity - - # Simple thin kickstand rib (not a hollow “格子”) — optional small triangle - # Skip bulky stand entirely per user feedback. + slots.append( + aabb(cx - 5 + i * 2.8, cy - 4.2, -DHT_PROUD - 0.2, cx - 5 + i * 2.8 + 1.2, cy + 4.2, 0.15) + ) + out = U(out, Diff(grill, ghole, *slots)) out.merge_vertices() return out +def make_snap_coupon() -> trimesh.Trimesh: + """Small test piece: one snap + one catch for tuning before full print.""" + base = aabb(0, 0, 0, 40, 28, 3) + # fake front strip with one snap + strip = aabb(5, 20, 3, 35, 28, 3 + FRONT_BODY_H * 0.35) + snap = cantilever_snap(20, 28, +1) + # shift snap down a bit for coupon + front = U(strip, snap) + # fake back catch wall + wall = aabb(5, 0, 0, 35, 3.2, 18) + win = catch_window(20, 3.2, +1) + # remap catch to coupon coords roughly + catch = aabb(20 - SNAP_W / 2 - 0.5, -0.2, 8, 20 + SNAP_W / 2 + 0.5, 3.5, 18) + ledge = aabb(20 - SNAP_W / 2 + 0.3, 2.5, 10, 20 + SNAP_W / 2 - 0.3, 2.5 + SNAP_HOOK + 0.4, 11.4) + back = U(Diff(wall, catch), ledge) + # place back beside front + back.apply_translation([0, -8, 0]) + label = aabb(2, 12, 3, 3.2, 18, 4.5) # marker nub + return U(base, front, back, label) + + def main() -> None: out = Path(__file__).resolve().parent / "export" out.mkdir(parents=True, exist_ok=True) - print("front…") + + print("front (rounded + snaps)…") front = make_front() - print("back…") + print("back (rounded + catches)…") back = make_back() + print("snap coupon…") + coupon = make_snap_coupon() + front.export(out / "front.stl") back.export(out / "back.stl") + coupon.export(out / "snap_coupon.stl") - # write mate info for viewer - meta = out / "mate.json" - meta.write_text( - "{\n" - f' "outer_l": {OUTER_L},\n' - f' "outer_w": {OUTER_W},\n' - f' "front_body_h": {FRONT_BODY_H},\n' - f' "back_body_h": {BACK_BODY_H},\n' - f' "lip_h": {LIP_H},\n' - f' "dht_proud": {DHT_PROUD}\n' - "}\n", + meta = { + "outer_l": OUTER_L, + "outer_w": OUTER_W, + "front_body_h": FRONT_BODY_H, + "back_body_h": BACK_BODY_H, + "lip_h": LIP_H, + "dht_proud": DHT_PROUD, + "corner_r": CORNER_R, + "snap_w": SNAP_W, + "snap_l": SNAP_L, + "snap_hook": SNAP_HOOK, + "lip_clear": LIP_CLEAR, + "version": "1.1-snaps", + } + (out / "mate.json").write_text( + json.dumps(meta, indent=2) + "\n", encoding="utf-8", ) - print(f"front {front.extents} watertight={front.is_watertight}") - print(f"back {back.extents} watertight={back.is_watertight}") - print("closed stack height ≈", BACK_BODY_H + FRONT_BODY_H, "mm (lips nest, not add full)") - print("Wrote STLs + mate.json") + + print(f"front {front.extents} wt={front.is_watertight}") + print(f"back {back.extents} wt={back.is_watertight}") + print(f"coupon {coupon.extents} wt={coupon.is_watertight}") + print("Wrote front/back/snap_coupon + mate.json") if __name__ == "__main__": diff --git a/cad/viewer.html b/cad/viewer.html index 0e912ae..671942c 100644 --- a/cad/viewer.html +++ b/cad/viewer.html @@ -62,8 +62,8 @@

- 后盖中心微凸的是 DHT11 卡位通风口(传感器按入后盖背面,探头略突出)。
- 已去掉旁边多余的大“格子”(旧版支脚块 / 外挂仓)。 + v1.1:外轮廓圆角 + 长边四侧悬臂卡扣合盖;后盖中心微凸是 DHT11 卡位通风口。
+ 已去掉旁边多余的大“格子”。旧无卡扣版见标签 v1.0-case-closed。

加载中…
@@ -231,7 +231,8 @@ root.add(backG); root.add(frontG); root.add(dhtG); setLid(0); setExp(0); fit(); - msg(`合盖对齐已按 mate.json · 外壳 ${mate.outer_l}×${mate.outer_w} mm · DHT 突出 ${mate.dht_proud} mm`); + const ver = mate.version ? ` · ${mate.version}` : ""; + msg(`合盖对齐已按 mate.json${ver} · 外壳 ${mate.outer_l}×${mate.outer_w} mm · R${mate.corner_r ?? "?"} · DHT 突出 ${mate.dht_proud} mm`); } catch (e) { console.error(e); msg("加载失败:请用 python -m http.server 8765 --directory cad", true);