diff --git a/shell/README.md b/shell/README.md new file mode 100644 index 0000000..22f4995 --- /dev/null +++ b/shell/README.md @@ -0,0 +1,25 @@ +# Snips shell + +One folder per board/shell revision. Keep old versions; start the next one by copying the folder. + +``` +shell// + fusion/SnipsShell.f3d the Fusion master (plus lib.py, sc_*.json used by the rebuild scripts) + export/stl, export/step raw per-part exports from Fusion (as modelled) + export/print/stl, print/step print-ready files (oriented, on Z=0), README.md, tools/ + export/reference/ non-printing reference parts + export/_export_log.txt + photos/ +PCB/step//snips_controller.step the board model for that revision (v1.1, v1.2) +``` + +## Exporting from Fusion +Write to `shell//export/` (use the version the Fusion doc belongs to), per component: +`createSTEPExportOptions(.../export/step/.step, comp)`, `createSTLExportOptions(comp, .../export/stl/.stl)` +(high refinement, binary), and `createFusionArchiveExportOptions(.../fusion/SnipsShell.f3d)`. +Then regenerate the print files (below). + +## Print files +The tools in `export/print/tools/` find their folders from their own location, so run them from that version's +`tools/` folder and they read `export/stl|step` and write `export/print/stl|step`. Override with +`SNIPS_EXPORT_DIR` / `SNIPS_PRINT_DIR` if the files live somewhere else. See `export/print/README.md`. diff --git a/shell/v1.1/export/print/README.md b/shell/v1.1/export/print/README.md index 82d9b5f..78e8305 100644 --- a/shell/v1.1/export/print/README.md +++ b/shell/v1.1/export/print/README.md @@ -6,7 +6,7 @@ Designed for a **0.4 mm nozzle**, ~0.2 mm layers. | Part | Orientation | Supports | |---|---|---| | TopShell | seam rim on the bed (as modelled), one piece (no split) | slicer supports for the roof, or use `TopShell_with_buck.stl` (see Support blocks) | -| BottomShell | flipped, rim on the bed, belly up | slicer supports for the belly (interior scarring OK). The alignment lip now stops 1.2 mm above the bed plane, so it needs support under its top edge too (supports everywhere, not just touching build plate) | +| BottomShell | flipped, rim on the bed, belly up | slicer supports for the belly (interior scarring OK). The alignment lip is level with the screw mounts (top at z 1.99), so the rim, lip and mounts all sit on the bed | | BatteryPanel | flat, belly (outer face) on the bed, cradle up; the snap arms flex in the bed plane | none needed (the front hook tabs are short; add a little support under them if your slicer complains) | | BumperCap | flat front face on the bed (face down) | slicer supports, small: under the side flange ties (about 2.4 mm wide overhang each side). New simple design: a flat button (34 x 6.7 mm) that goes through the window from INSIDE before the PCB, with a flange on each side behind the front wall and a 4.5 mm post on each flange | | Trigger | on its side, the +X arm face down, spring ear (the little block with the wire channel) up | none needed (`Trigger.stl`). The ear has a 45 deg gusset, and the only overhangs left are tiny bridges inside the 0.6 mm wire channel (about 6 mm2) | @@ -21,7 +21,7 @@ Designed for a **0.4 mm nozzle**, ~0.2 mm layers. - TopShell: 10 blocks: the big one in the main cavity (about 13.5 cm3), one by the posts (about 3.4 cm3), and 8 small ones around the face buttons and under the thumbstick (side strips, between the button columns, beside and behind the stick; 0.5 to 2.3 cm3 each, all at least 0.3 mm from the part). The one out front under the OLED housing was dropped (`--max-y 50`). BottomShell: 2 side blocks (about 4 cm3 each). - Each block keeps 0.3 mm or more from the part on every side, and its flat top is lifted to about 0.2 mm under the lowest roof point above it. The sloped parts of the roof, and everything else, still use normal slicer supports. - In OrcaSlicer load the STL and answer yes to "split into parts". Give the block parts 1 wall and about 5% infill, no supports. -- Regenerate with `tools/gen_buck.py [--max-y 50] [--band -20.5 22.5]` (`--band` adds the small face-button/thumbstick blocks; TopShell uses both flags) (needs numpy, scipy, scikit-image, trimesh, rtree). +- Run the tools from this version's `tools/` folder; they find `export/stl|step` and `print/` from their own location (override with `SNIPS_EXPORT_DIR` / `SNIPS_PRINT_DIR`). Regenerate with `tools/gen_buck.py [--max-y 50] [--band -20.5 22.5]` (`--band` adds the small face-button/thumbstick blocks; TopShell uses both flags) (needs numpy, scipy, scikit-image, trimesh, rtree). ## Built-in breakaway supports - Tapered pillars: 1.0 mm base, 0.6 mm tip (0.7/0.5 mm in tight spots), ending 0.2 mm below the part so they snap off. diff --git a/shell/v1.1/export/print/tools/build_sup.py b/shell/v1.1/export/print/tools/build_sup.py index e60b2b4..645e8f2 100644 --- a/shell/v1.1/export/print/tools/build_sup.py +++ b/shell/v1.1/export/print/tools/build_sup.py @@ -1,7 +1,8 @@ import numpy as np, os, json, math import orient as O, gen_supports as G from scipy import ndimage -d='/mnt/user-data/uploads/SnipsControllers/shell/export/stl' +import paths as P +d=P.SRC_STL GAP=0.2; BASE_W=1.0; TIP_W=0.6 def pillar_mesh(x,y,z0,z1,bw=None,tw=None): h0=(bw or BASE_W)/2; h1=(tw or TIP_W)/2 diff --git a/shell/v1.1/export/print/tools/export_print.py b/shell/v1.1/export/print/tools/export_print.py index 68aeba2..8cc4cbf 100644 --- a/shell/v1.1/export/print/tools/export_print.py +++ b/shell/v1.1/export/print/tools/export_print.py @@ -1,8 +1,9 @@ import numpy as np, os, struct, json import orient as O, build_sup as B import trimesh -src='/mnt/user-data/uploads/SnipsControllers/shell/export/stl' -out='/mnt/user-data/outputs/print/stl'; os.makedirs(out,exist_ok=True) +import paths as P +src=P.SRC_STL +out=P.OUT_STL; os.makedirs(out,exist_ok=True) ORI={'TriggerPost':'-Z up (flipped)','TopShell':'+Z up (as modelled)','BottomShell':'-Z up (flipped)','BatteryPanel':'+Z up (as modelled)','BumperCap':'+Y up','Trigger':'-X up'} for n in ['HallBridge','PowerPlate']+['FaceCap%d'%i for i in range(1,7)]: ORI[n]='+Z up (as modelled)' ORI['PowerPlate']='+Y up' diff --git a/shell/v1.1/export/print/tools/gen_supports.py b/shell/v1.1/export/print/tools/gen_supports.py index adb2bd7..793d52f 100644 --- a/shell/v1.1/export/print/tools/gen_supports.py +++ b/shell/v1.1/export/print/tools/gen_supports.py @@ -54,7 +54,8 @@ def pillars(tris, R, cell=0.3, pitch=2.4, edge_margin=0.6): return out, zmin if __name__ == '__main__': - d = '/mnt/user-data/uploads/SnipsControllers/shell/export/stl' + import paths as P + d = P.SRC_STL jobs = {'BumperCap': '-Z up (flipped)', 'Trigger': '-X up'} res = {} for n, o in jobs.items(): diff --git a/shell/v1.1/export/print/tools/paths.py b/shell/v1.1/export/print/tools/paths.py new file mode 100644 index 0000000..30a6c0d --- /dev/null +++ b/shell/v1.1/export/print/tools/paths.py @@ -0,0 +1,15 @@ +"""Where the print tools read and write. Everything is derived from this file's location, so the tools in +shell//export/print/tools/ always work on that version's files. + + EXPORT shell//export (raw Fusion exports: stl/, step/) + PRINT shell//export/print (print-ready output: stl/, step/) + +Override for a scratch checkout or a container with SNIPS_EXPORT_DIR / SNIPS_PRINT_DIR.""" +import os +HERE = os.path.dirname(os.path.abspath(__file__)) +EXPORT = os.environ.get('SNIPS_EXPORT_DIR') or os.path.normpath(os.path.join(HERE, '..', '..')) +PRINT = os.environ.get('SNIPS_PRINT_DIR') or os.path.normpath(os.path.join(HERE, '..')) +SRC_STL = os.path.join(EXPORT, 'stl') +SRC_STEP = os.path.join(EXPORT, 'step') +OUT_STL = os.path.join(PRINT, 'stl') +OUT_STEP = os.path.join(PRINT, 'step') diff --git a/shell/v1.1/export/print/tools/step_orient.py b/shell/v1.1/export/print/tools/step_orient.py index 6b3aecb..194fef4 100644 --- a/shell/v1.1/export/print/tools/step_orient.py +++ b/shell/v1.1/export/print/tools/step_orient.py @@ -1,8 +1,9 @@ import os from build123d import import_step, export_step, Pos, Rot import export_print_cfg as C -src='/mnt/user-data/uploads/SnipsControllers/shell/export/step' -out='/mnt/user-data/outputs/print/step'; os.makedirs(out,exist_ok=True) +import paths as P +src=P.SRC_STEP +out=P.OUT_STEP; os.makedirs(out,exist_ok=True) RR={'+Z up (as modelled)':Rot(0,0,0),'-Z up (flipped)':Rot(X=180),'-Y up':Rot(X=90),'+Y up':Rot(X=-90),'-X up':Rot(Y=-90),'+X up':Rot(Y=90)} for n,o in C.ORI.items(): s=RR[o]*import_step(os.path.join(src,n+'.step'))