case updates
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ Generated by the Feather Case Wizard.
|
||||
- FeatherWings: 1
|
||||
- Battery compartment: yes
|
||||
- 1/4-20 insert: yes
|
||||
- Approximate exterior: 88.6 × 59.1 × 40.4 mm
|
||||
- Approximate exterior: 88.6 × 61.1 × 40.4 mm
|
||||
- Formats: 3mf
|
||||
- Parts: `body`, `lid`, `lid_base`, `lid_accent`, `insert_coupon`, `switch_coupon`, `fit_coupon`
|
||||
- Custom cutouts: 0
|
||||
|
||||
+9
-4
@@ -3,7 +3,7 @@ schema_version: 1
|
||||
name: GPS
|
||||
slug: gps
|
||||
generator:
|
||||
sha256: 168dd3c04ca4015b07fe6c0295e7d4bb43969671f5f3552ffab31d8deffc3024
|
||||
sha256: 281917098487eeacd19a136ba27752698712e90cb4c03c6525a1ea3167c9ea13
|
||||
created_with: feather-case-wizard
|
||||
parameters:
|
||||
top_profile: gps
|
||||
@@ -37,6 +37,7 @@ parameters:
|
||||
battery_radial_clearance: 0.6
|
||||
battery_end_clearance: 1.0
|
||||
battery_partition_thickness: 1.8
|
||||
battery_board_clearance: 3.0
|
||||
rocker_cutout_size:
|
||||
- 12.9
|
||||
- 19.4
|
||||
@@ -46,6 +47,10 @@ parameters:
|
||||
- 21.0
|
||||
- 21.0
|
||||
rocker_artwork_gap: 2.0
|
||||
rocker_partition_offset: 2.0
|
||||
rocker_tab_panel_thickness: 2.0
|
||||
rocker_tab_land: 2.0
|
||||
rocker_tab_taper_length: 0.6
|
||||
tripod_insert_enabled: true
|
||||
tripod_insert_length: 5.0
|
||||
tripod_insert_hole_diameter: 7.2
|
||||
@@ -87,10 +92,10 @@ parameters:
|
||||
lid_label_size: 5.0
|
||||
lid_label_logo_gap: 2.0
|
||||
lid_art_margin: 8.5
|
||||
usb_opening_width: 12.5
|
||||
usb_opening_height: 7.0
|
||||
usb_opening_width: 13.5
|
||||
usb_opening_height: 8.0
|
||||
usb_opening_radius: 1.5
|
||||
usb_vertical_offset: 0.0
|
||||
usb_vertical_offset: 0.5
|
||||
cutouts: []
|
||||
outputs:
|
||||
formats:
|
||||
|
||||
@@ -28,10 +28,15 @@
|
||||
"battery_radial_clearance": "0.6",
|
||||
"battery_end_clearance": "1.0",
|
||||
"battery_partition_thickness": "1.8",
|
||||
"battery_board_clearance": "3.0",
|
||||
"rocker_cutout_size": "[12.9,19.4]",
|
||||
"rocker_corner_radius": "0.8",
|
||||
"rocker_body_size": "[15.0,21.0,21.0]",
|
||||
"rocker_artwork_gap": "2.0",
|
||||
"rocker_partition_offset": "2.0",
|
||||
"rocker_tab_panel_thickness": "2.0",
|
||||
"rocker_tab_land": "2.0",
|
||||
"rocker_tab_taper_length": "0.6",
|
||||
"tripod_insert_enabled": "true",
|
||||
"tripod_insert_length": "5.0",
|
||||
"tripod_insert_hole_diameter": "7.2",
|
||||
@@ -73,10 +78,10 @@
|
||||
"lid_label_size": "5.0",
|
||||
"lid_label_logo_gap": "2.0",
|
||||
"lid_art_margin": "8.5",
|
||||
"usb_opening_width": "12.5",
|
||||
"usb_opening_height": "7.0",
|
||||
"usb_opening_width": "13.5",
|
||||
"usb_opening_height": "8.0",
|
||||
"usb_opening_radius": "1.5",
|
||||
"usb_vertical_offset": "0.0"
|
||||
"usb_vertical_offset": "0.5"
|
||||
}
|
||||
},
|
||||
"fileFormatVersion": "1"
|
||||
|
||||
@@ -48,10 +48,15 @@ battery_diameter = 18;
|
||||
battery_radial_clearance = 0.6;
|
||||
battery_end_clearance = 1;
|
||||
battery_partition_thickness = 1.8;
|
||||
battery_board_clearance = 3;
|
||||
rocker_cutout_size = [12.9, 19.4];
|
||||
rocker_corner_radius = 0.8;
|
||||
rocker_body_size = [15, 21, 21];
|
||||
rocker_artwork_gap = 2;
|
||||
rocker_partition_offset = 2;
|
||||
rocker_tab_panel_thickness = 2;
|
||||
rocker_tab_land = 2;
|
||||
rocker_tab_taper_length = 0.6;
|
||||
|
||||
/* [Tripod mount] */
|
||||
tripod_insert_enabled = false;
|
||||
@@ -104,10 +109,10 @@ usb_guide_enabled = true;
|
||||
usb_connector_overhang = 2;
|
||||
usb_guide_wall_thickness = 1.2;
|
||||
usb_guide_end_gap = 1;
|
||||
usb_opening_width = 12.5;
|
||||
usb_opening_height = 7;
|
||||
usb_opening_width = 13.5;
|
||||
usb_opening_height = 8;
|
||||
usb_opening_radius = 1.5;
|
||||
usb_vertical_offset = 0;
|
||||
usb_vertical_offset = 0.5;
|
||||
|
||||
/* [Custom wall cutouts] */
|
||||
// Entry format: [face, shape, u, z, width, height, radius]
|
||||
@@ -191,7 +196,7 @@ profile_top_gap =
|
||||
top_profile == "oled128x64" ? oled_face_gap :
|
||||
generic_top_gap;
|
||||
|
||||
partition_y = board_origin_y + feather_width + 1;
|
||||
partition_y = board_origin_y + feather_width + battery_board_clearance;
|
||||
battery_center_y = partition_y + battery_partition_thickness
|
||||
+ battery_radial_clearance + battery_diameter / 2;
|
||||
battery_start_x = front_lid_boss_center + lid_boss_r
|
||||
@@ -212,10 +217,14 @@ case_width_battery = battery_center_y + battery_diameter / 2
|
||||
case_width = battery_enabled ? max(case_width_plain, case_width_battery)
|
||||
: case_width_plain;
|
||||
|
||||
rocker_center_x = case_length - wall_thickness - fit_clearance
|
||||
rocker_installed_center_x = case_length - wall_thickness - fit_clearance
|
||||
- lid_lip_thickness - fit_clearance - rocker_body_size[0] / 2;
|
||||
rocker_center_y = front_lid_boss_center + lid_boss_r + fit_clearance
|
||||
+ rocker_body_size[1] / 2;
|
||||
rocker_installed_center_y = front_lid_boss_center + lid_boss_r + fit_clearance
|
||||
+ rocker_body_size[1] / 2 + rocker_partition_offset;
|
||||
// The printable lid is flipped across Y when installed, so its local cutout
|
||||
// coordinate must be mirrored from the assembled switch location.
|
||||
rocker_lid_center_x = rocker_installed_center_x;
|
||||
rocker_lid_center_y = case_width - rocker_installed_center_y;
|
||||
|
||||
lid_artwork_enabled = lid_label != "" || lid_logo_enabled;
|
||||
lid_art_rotation =
|
||||
@@ -223,7 +232,7 @@ lid_art_rotation =
|
||||
lid_art_orientation == "usb_front" ? 90 :
|
||||
lid_art_orientation == "usb_right" ? 180 : 270;
|
||||
lid_art_safe_max_x = battery_enabled
|
||||
? rocker_center_x - rocker_cutout_size[0] / 2 - rocker_artwork_gap
|
||||
? rocker_lid_center_x - rocker_cutout_size[0] / 2 - rocker_artwork_gap
|
||||
: case_length - lid_art_margin;
|
||||
lid_art_physical_size = [
|
||||
lid_art_safe_max_x - lid_art_margin,
|
||||
@@ -294,6 +303,34 @@ lid_boss_xy = [
|
||||
case_width - wall_thickness - lid_boss_r + lid_boss_wall_overlap
|
||||
]
|
||||
];
|
||||
rocker_boss_clearance = min([
|
||||
for (p = lid_boss_xy)
|
||||
sqrt(
|
||||
pow(max(
|
||||
abs(p[0] - rocker_installed_center_x)
|
||||
- rocker_body_size[0] / 2,
|
||||
0
|
||||
), 2)
|
||||
+ pow(max(
|
||||
abs(p[1] - rocker_installed_center_y)
|
||||
- rocker_body_size[1] / 2,
|
||||
0
|
||||
), 2)
|
||||
) - lid_boss_r
|
||||
]);
|
||||
rocker_relief_half_size = [
|
||||
rocker_cutout_size[0] / 2,
|
||||
rocker_cutout_size[1] / 2 + rocker_tab_land + rocker_tab_taper_length
|
||||
];
|
||||
rocker_relief_boss_clearance = min([
|
||||
for (p = lid_boss_xy)
|
||||
sqrt(
|
||||
pow(max(abs(p[0] - rocker_lid_center_x)
|
||||
- rocker_relief_half_size[0], 0), 2)
|
||||
+ pow(max(abs(p[1] - rocker_lid_center_y)
|
||||
- rocker_relief_half_size[1], 0), 2)
|
||||
) - lid_boss_r
|
||||
]);
|
||||
|
||||
assert(wing_count >= 1, "wing_count must be at least one");
|
||||
assert(top_profile == "generic" || top_profile == "gps"
|
||||
@@ -301,6 +338,14 @@ assert(top_profile == "generic" || top_profile == "gps"
|
||||
assert(wall_thickness >= 1.2, "wall_thickness is too small for 0.6 mm FDM");
|
||||
assert(battery_partition_thickness >= 1.2,
|
||||
"battery_partition_thickness is too small for 0.6 mm FDM");
|
||||
assert(battery_board_clearance > 0,
|
||||
"battery_board_clearance must be positive");
|
||||
assert(rocker_tab_panel_thickness >= 1.2,
|
||||
"rocker tab panel needs at least two 0.6 mm lines");
|
||||
assert(rocker_tab_panel_thickness < lid_thickness,
|
||||
"rocker tab panel must be thinner than the lid");
|
||||
assert(rocker_tab_land > 0 && rocker_tab_taper_length > 0,
|
||||
"rocker tab relief land and taper must be positive");
|
||||
assert(lid_lip_thickness >= 1.2, "lid lip needs at least two 0.6 mm lines");
|
||||
assert(lid_art_orientation == "usb_left"
|
||||
|| lid_art_orientation == "usb_front"
|
||||
@@ -325,6 +370,13 @@ assert(!tripod_insert_enabled
|
||||
"Tripod insert boss does not have enough radial material");
|
||||
assert(usb_opening_enabled || !usb_guide_enabled,
|
||||
"USB guide requires the USB opening");
|
||||
assert(!usb_opening_enabled
|
||||
|| usb_center_z - usb_reserved_height / 2 >= effective_floor,
|
||||
"USB opening or guide intersects the case floor");
|
||||
assert(!usb_opening_enabled
|
||||
|| usb_center_z + usb_reserved_height / 2
|
||||
<= body_height - lid_lip_depth,
|
||||
"USB opening or guide intersects the lid lip");
|
||||
assert(!tripod_insert_enabled
|
||||
|| tripod_insert_outer_diameter >= tripod_insert_hole_diameter,
|
||||
"Tripod insert entry must not be smaller than its pilot");
|
||||
@@ -334,13 +386,35 @@ assert(!battery_enabled || !tripod_insert_enabled
|
||||
|| tripod_partition_clearance >= 1,
|
||||
"Tripod insert entry is too close to the battery partition");
|
||||
assert(!battery_enabled
|
||||
|| rocker_center_x - rocker_body_size[0] / 2
|
||||
|| rocker_installed_center_x - rocker_body_size[0] / 2
|
||||
>= board_origin_x + feather_length + fit_clearance,
|
||||
"Rocker body overlaps the Feather PCB");
|
||||
assert(!battery_enabled
|
||||
|| rocker_center_y + rocker_body_size[1] / 2
|
||||
|| rocker_installed_center_y + rocker_body_size[1] / 2
|
||||
<= partition_y - fit_clearance,
|
||||
"Rocker body overlaps the battery partition");
|
||||
assert(!battery_enabled
|
||||
|| rocker_installed_center_x - rocker_body_size[0] / 2
|
||||
>= wall_thickness + lid_lip_thickness + fit_clearance,
|
||||
"Rocker body overlaps the front lid lip");
|
||||
assert(!battery_enabled
|
||||
|| rocker_installed_center_x + rocker_body_size[0] / 2
|
||||
<= case_length - wall_thickness - lid_lip_thickness - fit_clearance,
|
||||
"Rocker body overlaps the rear lid lip");
|
||||
assert(!battery_enabled
|
||||
|| rocker_installed_center_y - rocker_body_size[1] / 2
|
||||
>= wall_thickness + lid_lip_thickness + fit_clearance,
|
||||
"Rocker body overlaps the Feather-side lid lip");
|
||||
assert(!battery_enabled || rocker_boss_clearance >= fit_clearance - eps,
|
||||
"Rocker body overlaps a lid boss");
|
||||
assert(!battery_enabled
|
||||
|| rocker_relief_boss_clearance >= fit_clearance - eps,
|
||||
"Rocker tab relief overlaps a lid boss scallop");
|
||||
assert(!battery_enabled
|
||||
|| abs(
|
||||
case_width - rocker_lid_center_y - rocker_installed_center_y
|
||||
) < eps,
|
||||
"Rocker lid cutout does not mirror to the installed switch location");
|
||||
assert(!battery_enabled
|
||||
|| body_height - rocker_body_size[2] >= effective_floor,
|
||||
"Rocker body intersects the case floor");
|
||||
@@ -803,13 +877,18 @@ module lid_cutouts() {
|
||||
);
|
||||
}
|
||||
|
||||
if (battery_enabled)
|
||||
translate([rocker_center_x, rocker_center_y, -eps])
|
||||
if (battery_enabled) {
|
||||
translate([rocker_lid_center_x, rocker_lid_center_y, -eps])
|
||||
centered_rounded_prism(
|
||||
rocker_cutout_size,
|
||||
lid_thickness + lid_lip_depth + 2 * eps,
|
||||
rocker_corner_radius
|
||||
);
|
||||
rocker_tab_reliefs(
|
||||
[rocker_lid_center_x, rocker_lid_center_y],
|
||||
rocker_cutout_size
|
||||
);
|
||||
}
|
||||
|
||||
if (top_profile == "oled128x64") {
|
||||
beveled_oled_window();
|
||||
@@ -820,6 +899,41 @@ module lid_cutouts() {
|
||||
}
|
||||
}
|
||||
|
||||
// Thin the horizontal top/bottom edges of the upright switch opening where the
|
||||
// spring tabs latch. Each full-width land overlaps the rounded opening by its
|
||||
// corner radius, then extends outward before tapering to the surrounding lid.
|
||||
module rocker_tab_reliefs(center, opening_size) {
|
||||
relief_depth = lid_thickness - rocker_tab_panel_thickness;
|
||||
opening_overlap = rocker_corner_radius;
|
||||
strip = 0.02;
|
||||
for (side = [-1, 1]) {
|
||||
edge_y = center[1] + side * opening_size[1] / 2;
|
||||
translate([
|
||||
center[0] - opening_size[0] / 2,
|
||||
edge_y - (side < 0 ? rocker_tab_land : opening_overlap),
|
||||
rocker_tab_panel_thickness
|
||||
])
|
||||
cube([opening_size[0], rocker_tab_land + opening_overlap,
|
||||
relief_depth + eps]);
|
||||
|
||||
hull() {
|
||||
translate([
|
||||
center[0] - opening_size[0] / 2,
|
||||
edge_y + side * rocker_tab_land - (side < 0 ? strip : 0),
|
||||
rocker_tab_panel_thickness
|
||||
])
|
||||
cube([opening_size[0], strip, relief_depth + eps]);
|
||||
translate([
|
||||
center[0] - opening_size[0] / 2,
|
||||
edge_y + side * (rocker_tab_land + rocker_tab_taper_length)
|
||||
- (side < 0 ? strip : 0),
|
||||
lid_thickness - strip
|
||||
])
|
||||
cube([opening_size[0], strip, strip + eps]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module lid_artwork_nominal_2d() {
|
||||
translate(lid_art_center)
|
||||
rotate(lid_art_rotation)
|
||||
@@ -983,15 +1097,15 @@ module reference_battery_and_switch() {
|
||||
cylinder(h = battery_length, d = battery_diameter);
|
||||
color([0.08, 0.08, 0.08, 0.85])
|
||||
translate([
|
||||
rocker_center_x - rocker_body_size[0] / 2,
|
||||
rocker_center_y - rocker_body_size[1] / 2,
|
||||
rocker_installed_center_x - rocker_body_size[0] / 2,
|
||||
rocker_installed_center_y - rocker_body_size[1] / 2,
|
||||
body_height + exploded_view - rocker_body_size[2]
|
||||
])
|
||||
cube(rocker_body_size);
|
||||
color([0.12, 0.12, 0.12, 0.95])
|
||||
translate([
|
||||
rocker_center_x - rocker_cutout_size[0] / 2,
|
||||
rocker_center_y - rocker_cutout_size[1] / 2,
|
||||
rocker_installed_center_x - rocker_cutout_size[0] / 2,
|
||||
rocker_installed_center_y - rocker_cutout_size[1] / 2,
|
||||
body_height + exploded_view + lid_thickness
|
||||
])
|
||||
cube([rocker_cutout_size[0], rocker_cutout_size[1], 2.5]);
|
||||
@@ -1049,7 +1163,7 @@ module switch_coupon() {
|
||||
coupon_height = lid_thickness;
|
||||
difference() {
|
||||
rounded_box([coupon_length, coupon_width, coupon_height], 3);
|
||||
for (i = [0 : len(coupon_steps) - 1])
|
||||
for (i = [0 : len(coupon_steps) - 1]) {
|
||||
translate([6 + i * spacing, coupon_width / 2, -eps])
|
||||
centered_rounded_prism(
|
||||
rocker_cutout_size
|
||||
@@ -1057,6 +1171,11 @@ module switch_coupon() {
|
||||
coupon_height + 2 * eps,
|
||||
rocker_corner_radius
|
||||
);
|
||||
rocker_tab_reliefs(
|
||||
[6 + i * spacing, coupon_width / 2],
|
||||
rocker_cutout_size + [coupon_steps[i], coupon_steps[i]]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user