219 lines
9.3 KiB
Markdown
219 lines
9.3 KiB
Markdown
# 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, Blender, and Python 3 must be available on `PATH`. On Ubuntu:
|
||
|
||
```bash
|
||
sudo apt-get install openscad blender python3
|
||
```
|
||
|
||
Set `OPENSCAD=/path/to/openscad`, `BLENDER=/path/to/blender`, or
|
||
`PYTHON=/path/to/python3` when a program is installed elsewhere. The wizard
|
||
checks all three 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.
|
||
|
||
When the battery compartment and tripod insert are both enabled, the generator
|
||
adds board-side clearance to keep the insert centered across the case width and
|
||
moves it 5 mm toward the USB wall to clear the nearest Feather standoff. The
|
||
battery partition defaults to three 0.6 mm extrusion lines and can be adjusted
|
||
with `battery_partition_thickness`.
|
||
|
||
## Two-color lid artwork
|
||
|
||
Set `lid_label` to a device name and/or enable `lid_logo_enabled` to add flush
|
||
second-color artwork to non-OLED lids. Choose `lid_art_orientation` from
|
||
`usb_left`, `usb_front`, `usb_right`, or `usb_rear`; it describes where the USB
|
||
edge sits when the exterior artwork is upright. OLED profiles reject lid
|
||
artwork until a window/button-safe layout is defined.
|
||
|
||
Generated artwork packages include separate `lid_base` and `lid_accent` meshes,
|
||
a complete single-color `lid`, and `lid_multicolor.3mf`. The multicolor file is
|
||
one aligned multipart object with its base assigned to filament 1 and its logo
|
||
and title assigned to filament 2. Print the lid exterior-face-down.
|
||
|
||
## 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. These parameters are the finished pilot diameters in the
|
||
model; `hole_compensation` is not added to heat-set pockets. The coupon uses
|
||
the same tapered pocket geometry as the cases.
|
||
4. Print `part="switch_coupon"` and choose the best rounded-rectangle opening
|
||
for the actual KCD1-101 rocker-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 and
|
||
route its lead through the combined front partition/JST opening and beneath
|
||
the Feather PCB.
|
||
5. Snap the KCD1-101 rocker switch into the rear lid opening, connect its bent
|
||
quick-connect terminals or low-profile wiring, and lower the wired lid onto
|
||
the case.
|
||
6. Heat-set the four lid inserts downward into the corner bosses.
|
||
7. For OLED builds, insert each enabled printed plunger through the lid from
|
||
the inside. The elongated flange stays in the internal recess.
|
||
8. 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.
|