Files
feather-case/README.md
T

195 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Parametric Feather Case
An OpenSCAD enclosure generator for the Adafruit ESP32 Feather V2, stacked
FeatherWings, an optional protected 18650 pack, and an optional 1/4-20 camera
mount. It produces a body, removable lid, OLED button plungers, and fit
calibration coupons.
## Interactive Ruby wizard
The HighLine wizard asks the project-specific questions, saves the answers in
YAML, and builds a self-contained case directory with OpenSCAD source, STL
and/or 3MF geometry, and rendered previews.
Install the Ruby dependency into this repository:
```bash
bundle install
```
Then run:
```bash
bin/feather-case
```
The menu can create a case, reopen one for dimensional tuning after a test
print, or rebuild an existing case. Generated definitions live under
`cases/<name>/`; exports, previews, revision history, and `vendor/bundle` are
ignored by Git.
OpenSCAD and Blender must be available on `PATH`. On Ubuntu:
```bash
sudo apt-get install openscad blender
```
Set `OPENSCAD=/path/to/openscad` or `BLENDER=/path/to/blender` when either
program is installed elsewhere. The wizard checks both tools before replacing
an existing package.
The wizard can add clearance beyond either short end of the Feather PCB for
right-angle headers, plug housings, and wire bends. Front clearance moves the
board and its standoffs away from the USB-C wall; rear clearance extends the
opposite end of the case.
USB programming access can be omitted for a closed front wall or paired with
an enclosed plug guide. The guide runs from the wall toward the connector and
automatically stops short based on the configured connector overhang and end
gap. New cases default to a 2 mm USB connector overhang, an enabled wall
opening, and an enabled guide; with the standard 2 mm front clearance the guide
has no inward length and behaves as the normal wall opening.
Each generated directory contains a dependency-free `build.rb`. After copying
that directory to another Ubuntu machine, run `ruby build.rb` to reproduce its
exports and previews. The saved generator source is used by default so a
fine-tuning pass cannot silently pick up later geometry changes.
OpenSCAD's 3MF output contains portable model geometry. It does not contain a
Bambu printer, filament, plate, or process profile; select those settings after
opening the files in Bambu Studio.
The design targets support-free FDM printing with a 0.6 mm nozzle. PLA and PETG
are suitable for general use; ASA is the preferred starting material for
outdoor exposure. The enclosure is not weather-sealed.
## Reference geometry
All dimensions are millimetres. Board coordinates come from Adafruit's source
files:
- [ESP32 Feather V2 PCB](https://github.com/adafruit/Adafruit-ESP32-Feather-V2-PCB)
- [ESP32 Feather V2 CAD](https://github.com/adafruit/Adafruit_CAD_Parts/tree/main/5400%20ESP32%20Feather%20V2)
- [128x64 OLED FeatherWing PCB](https://github.com/adafruit/Adafruit-OLED-FeatherWing-PCB)
- [128x64 OLED FeatherWing CAD](https://github.com/adafruit/Adafruit_CAD_Parts/tree/main/4650%20OLED%20FeatherWing)
- [Adafruit 69 x 18 mm protected 18650 pack](https://www.adafruit.com/product/1781)
The board origin is its USB edge at `(0, 0)`. The case uses X from the USB wall
toward the rear, Y from the plain side toward the battery/JST side, and Z up
from the exterior bottom.
## Generate parts
Open [feather_case.scad](feather_case.scad) in OpenSCAD and use the Customizer,
or override values from the command line:
```bash
# Generic one-Wing case
openscad -o body.stl -D 'part="body"' feather_case.scad
openscad -o lid.stl -D 'part="lid"' feather_case.scad
# Three-Wing GPS case with battery and camera mount
openscad -o gps-body.stl \
-D 'part="body"' \
-D 'top_profile="gps"' \
-D 'wing_count=3' \
-D 'battery_enabled=true' \
-D 'tripod_insert_enabled=true' \
feather_case.scad
openscad -o gps-lid.stl \
-D 'part="lid"' \
-D 'top_profile="gps"' \
-D 'wing_count=3' \
-D 'battery_enabled=true' \
-D 'tripod_insert_enabled=true' \
feather_case.scad
# 128x64 OLED lid and all four captive buttons
openscad -o oled-lid.stl \
-D 'part="lid"' \
-D 'top_profile="oled128x64"' \
-D 'button_reset=true' \
feather_case.scad
openscad -o oled-buttons.stl \
-D 'part="buttons"' \
-D 'top_profile="oled128x64"' \
-D 'button_reset=true' \
feather_case.scad
```
The standard stack height is `wing_count * wing_pitch`, with a 12.25 mm default
pitch. Set `stack_height_override` to the measured distance from the top surface
of the Feather PCB to the top surface of the uppermost FeatherWing PCB when
using unusual headers. Do not include components on the Wing; profile-specific
component heights and top gaps are added separately. The measured override
takes precedence over the computed height.
For the 128×64 OLED profile, `oled_component_height` is the height of the
tallest board feature (the switch tops), while `oled_display_height` controls
the display-face reference shown in the assembly preview. The defaults are
2.4 mm and 1.5 mm above the Wing PCB, respectively. The enclosure ceiling
remains based on the taller switches plus `oled_face_gap`, placing the display
face about 1.7 mm below the lid's inner plane. The default 0.7 mm captive-button
contact extension spans most of the 0.8 mm switch-to-lid gap.
## Custom wire egress
`extra_cutouts` accepts any number of entries:
```openscad
// [face, shape, u, z, width, height, radius]
extra_cutouts = [
["left", "circle", 35, 10, 8, 8, 4],
["rear", "roundrect", 20, 12, 14, 7, 2],
["right", "slot", 28, 15, 18, 5, 2.5]
];
```
Faces are `front` (the USB-C short wall), `rear` (the opposite short wall),
`left` (the plain/non-JST long wall), and `right` (the JST/battery long wall).
For front/rear faces, `u` is the global Y coordinate; for left/right faces it
is global X. The wizard presents this as distance from the selected wall's
left edge while viewing it from outside. The Z value is the opening centre.
Shapes are `circle`, `rect`, `roundrect`, and `slot`. Cutouts that enter the
floor or lid-lip keepout, approach another opening too closely, or overlap the
USB opening or guide keepout raise an assertion instead of silently weakening
those features.
## Calibration
Heat-set insert holes vary significantly by insert brand, filament, nozzle,
temperature, and printer calibration. Treat the supplied values as starting
points.
1. Export and print `part="insert_coupon"` in the intended material.
2. Test both M2.5 and 1/4-20 inserts in the five stepped holes.
3. Set `m25_insert_hole_diameter` and `tripod_insert_hole_diameter` to the best
coupon values.
4. Print `part="switch_coupon"` and choose the best hole for the actual DMWD
switch batch.
5. Print `part="fit_coupon"` and tune `fit_clearance` before committing to the
complete lid and body.
For ASA, tune dimensional compensation with coupons rather than applying an
assumed global shrink percentage. Start with four or more walls, good chamber
temperature control, and the same extrusion settings intended for the case.
## Assembly
1. Heat-set the optional 1/4-20 insert from inside the case. Its threaded
opening faces the exterior bottom.
2. Heat-set four M2.5 inserts into the board standoffs.
3. Fasten the ESP32 Feather V2, then install the stacking headers and Wings.
4. For battery builds, place the protected 69 x 18 mm pack in the cradle, route
its lead through the partition notch, and mount the latching switch in the
battery-side wall.
5. Heat-set the four lid inserts downward into the corner bosses.
6. For OLED builds, insert each enabled printed plunger through the lid from
the inside. The elongated flange stays in the internal recess.
7. Engage the lid rim and fasten four standard M2.5 socket-head screws into the
2.5 mm-deep counterbores.
Confirm the USB plug, switch, battery, insert, and lid fits without force before
leaving a lithium-ion battery installed. The battery cradle is intended for
Adafruit's protected pack, not an unprotected loose cell.