Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions shell/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Snips shell

One folder per board/shell revision. Keep old versions; start the next one by copying the folder.

```
shell/<version>/
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/<version>/snips_controller.step the board model for that revision (v1.1, v1.2)
```

## Exporting from Fusion
Write to `shell/<version>/export/` (use the version the Fusion doc belongs to), per component:
`createSTEPExportOptions(.../export/step/<Part>.step, comp)`, `createSTLExportOptions(comp, .../export/stl/<Part>.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`.
4 changes: 2 additions & 2 deletions shell/v1.1/export/print/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand All @@ -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 <bare print stl> <out stl> [--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 <bare print stl> <out stl> [--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.
Expand Down
3 changes: 2 additions & 1 deletion shell/v1.1/export/print/tools/build_sup.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 3 additions & 2 deletions shell/v1.1/export/print/tools/export_print.py
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
3 changes: 2 additions & 1 deletion shell/v1.1/export/print/tools/gen_supports.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
15 changes: 15 additions & 0 deletions shell/v1.1/export/print/tools/paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Where the print tools read and write. Everything is derived from this file's location, so the tools in
shell/<version>/export/print/tools/ always work on that version's files.

EXPORT shell/<version>/export (raw Fusion exports: stl/, step/)
PRINT shell/<version>/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')
5 changes: 3 additions & 2 deletions shell/v1.1/export/print/tools/step_orient.py
Original file line number Diff line number Diff line change
@@ -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'))
Expand Down
Loading