diff --git a/case/README.md b/case/README.md index 442f5be..cb3a13a 100644 --- a/case/README.md +++ b/case/README.md @@ -20,6 +20,7 @@ at least 210 × 115 mm. | [stl/body.stl](stl/body.stl) | upside down, top on the bed (as exported) | Sides, top and back wall. No supports needed. | | [stl/bezel.stl](stl/bezel.stl) | face down (as exported) | Front panel with the window and the display bosses. | | [stl/base.stl](stl/base.stl) | flat (as exported) | Floor with the board standoffs and the screw holes. | +| [stl/feet.stl](stl/feet.stl) | flat side down (as exported) | 4 feet, print in **TPU**. Each clamps under one of the base screws, with a spigot that locates in the screw's counterbore. | PETG is a good choice: the display warms the inside by a few degrees. PLA works if the case stays out of the sun. @@ -34,7 +35,7 @@ works if the case stays out of the sun. - 4 on the base's board standoffs - 4 × M3×8 to bolt the display to the bezel - 4 × M3×6 to hold the D1 board on its standoffs -- 4 × M3×8 to hold the base on, from below +- 4 × M3×8 to hold the base on, from below; **M3×10** with the TPU feet ## Assembly @@ -46,7 +47,9 @@ works if the case stays out of the sun. 5. Connect the display cable. The MAX3232 sits inline in the cable; tie it to the anchor on the base. 6. Put the body on the base and screw it together from below. The base holds - the bezel in place. + the bezel in place. With the feet, put a foot on each screw first (the + spigot faces the base) and use M3×10. Tighten until the foot is snug; the + TPU only needs light compression. ## Measure before printing @@ -78,6 +81,7 @@ with: openscad -D 'part="body"' --export-format binstl -o stl/body.stl vfd-case.scad openscad -D 'part="bezel"' --export-format binstl -o stl/bezel.stl vfd-case.scad openscad -D 'part="base"' --export-format binstl -o stl/base.stl vfd-case.scad +openscad -D 'part="feet"' --export-format binstl -o stl/feet.stl vfd-case.scad ``` `part="assembly"` shows everything with dummy display and board models, and @@ -85,7 +89,7 @@ openscad -D 'part="base"' --export-format binstl -o stl/base.stl vfd-case.scad each one must render as an empty object: - `check_body_bezel`, `check_body_display`, `check_bezel_display` -- `check_body_base`, `check_bezel_base`, `check_display_base` +- `check_body_base`, `check_bezel_base`, `check_display_base`, `check_feet_base` - `check_board` - `check_insertion`: sweeps the bezel and display along their slide-in path through the body. diff --git a/case/stl/feet.stl b/case/stl/feet.stl new file mode 100644 index 0000000..cc50466 Binary files /dev/null and b/case/stl/feet.stl differ diff --git a/case/vfd-case.scad b/case/vfd-case.scad index 2584851..271ba7f 100644 --- a/case/vfd-case.scad +++ b/case/vfd-case.scad @@ -62,6 +62,14 @@ screw_d = 3.4; // M3 clearance head_d = 6.2; // M3 head counterbore in the base head_depth = 2; +/* [TPU feet, held by the base screws (use M3x10 instead of M3x8)] */ +foot_d = 14; // fits inside the base outline at the rear corners +foot_h = 4.5; // below the base +foot_spigot_h = 1.8; // locates in the base's screw counterbore +foot_spigot_d = head_d - 0.2; +foot_head_d = 6.6; // pocket for the screw head (from below) +foot_head_depth = 3.5; // M3 socket head is 3 mm tall + /* [WEMOS D1 R1 (Arduino UNO footprint)] */ board_l = 68.58; // along the case depth, connector edge at the back board_w = 53.34; @@ -227,6 +235,27 @@ module base() { function board_xy(h) = [board_x0 + h[1], board_conn_y - h[0], 0]; +// One foot, top face at z = 0 (against the base's underside), centred on a screw. +module foot() { + difference() { + union() { + translate([0, 0, -foot_h]) cylinder(d = foot_d, h = foot_h); + translate([0, 0, -0.01]) cylinder(d = foot_spigot_d, h = foot_spigot_h + 0.01); + } + translate([0, 0, -foot_h - 1]) cylinder(d = screw_d, h = foot_h + foot_spigot_h + 2); + translate([0, 0, -foot_h - 1]) cylinder(d = foot_head_d, h = foot_head_depth + 1); + // soften the bottom edge + translate([0, 0, -foot_h - 0.01]) difference() { + cylinder(d = foot_d + 1, h = 1); + cylinder(d1 = foot_d - 2, d2 = foot_d + 0.01, h = 1.01); + } + } +} + +module feet_in_place() { + for (p = base_screws) translate([p[0], p[1], -base_t]) foot(); +} + module tie_anchor() { difference() { translate([-5, -3, 0]) cube([10, 6, 5]); @@ -265,6 +294,7 @@ if (part == "assembly") { color("SlateGray", 0.5) body(); color("DimGray") bezel(); color("Gainsboro") base(); + color("Black") feet_in_place(); color("SeaGreen") display_dummy(); color("SteelBlue") board_dummy(); } else if (part == "section") { @@ -283,6 +313,9 @@ if (part == "assembly") { translate([0, depth, height]) rotate([180, 0, 0]) body(); // top on the bed } else if (part == "bezel") { translate([0, 0, -lip]) multmatrix(M) bezel(); // front face on the bed +} else if (part == "feet") { + for (i = [0 : len(base_screws) - 1]) // 4 feet, flat side down + translate([i * (foot_d + 5), 0, foot_h]) foot(); } else if (part == "base") { translate([0, 0, base_t]) base(); } @@ -294,6 +327,7 @@ else if (part == "check_body_base") intersection() { body(); base(); } else if (part == "check_bezel_base") intersection() { bezel(); base(); } else if (part == "check_board") intersection() { union() { body(); bezel(); base(); display_dummy(); } board_dummy(); } else if (part == "check_display_base") intersection() { base(); display_dummy(); } +else if (part == "check_feet_base") intersection() { base(); feet_in_place(); } // The bezel slides in from below along the panel: sweep it (with the display) down and check. else if (part == "check_insertion") intersection() { body();