From b06a18d9fdc9f7b654fe9527b8d7ea23e5f502da Mon Sep 17 00:00:00 2001 From: Chris Guidry Date: Sun, 26 Apr 2026 20:22:04 -0400 Subject: [PATCH] enclosure: GRS 3FR-4 speaker fit, L-shaped cable clip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated for the actual speaker on the bench (GRS 3FR-4, not the Adafruit 1314 we initially specced — same 60 mm M3 mounting pattern but a much deeper magnet). Reference doc renamed and rewritten with the new specs. Geometry consequences: * Speaker posts grow from 22 mm to 44 mm to position the frame plate with 1 mm of clearance below the magnet (vibration isolation; the alternative of resting the magnet on the plate would couple bass into the nightstand surface). * Chamber inner height grows to 46 mm (44 mm post + 2 mm foam tape on top of the frame, compressed against the cover underside). * Speaker frame extent goes from 78 mm to 95 mm (the GRS is wider across the mounting ears), so the chassis grows to ~107×162×49 mm assembled. Cable clip rework: * Was a closed rectangular tunnel centered on the back wall — over- engineered (the goal was strain relief, not a zip-tie pass-through) and conflicted with the centered back snap-fit tab. * Now an open L-shape (post + cap), positioned ~14 mm from the side wall to clear the snap tab. The cable drops in from above during assembly and rests in the L corner — post on the chamber-interior side, cap extending toward the side wall, cable contained on three sides with the open side facing the wall. * Cable notch in the back wall and matching notch in the back edge of the bottom plate shifted to match the L-clip's X position. Co-Authored-By: Claude Opus 4.7 (1M context) --- enclosure/lib/params.scad | 110 ++++++++++++++-------------- enclosure/parts/bottom-plate.scad | 52 ++++++------- enclosure/parts/chassis.scad | 5 +- reference/signal-chain.md | 4 +- reference/speakers/adafruit-1314.md | 48 ------------ reference/speakers/grs-3fr-4.md | 51 +++++++++++++ 6 files changed, 140 insertions(+), 130 deletions(-) delete mode 100644 reference/speakers/adafruit-1314.md create mode 100644 reference/speakers/grs-3fr-4.md diff --git a/enclosure/lib/params.scad b/enclosure/lib/params.scad index cabc15a..2544bcc 100644 --- a/enclosure/lib/params.scad +++ b/enclosure/lib/params.scad @@ -15,16 +15,13 @@ atom_d = 24; atom_body_h = 16.8; atom_corner_r = 3; -// USB-C cutout in the Atom's own back face (vertically centered on body). atom_usb_w_native = 11.6; atom_usb_h_native = 7; -// Bottom-face male HY2.0-4P GROVE connector. grove_body_w = 8; grove_body_d = 4.5; grove_body_h = 2.5; -// Bottom-face press-fit headers (the "Atom Stack" interface). header_pitch = 2.54; header_left_pin_count = 5; header_right_pin_count = 4; @@ -40,16 +37,20 @@ max_d = 16; max_pcb_t = 1.6; // ============================================================ -// Speaker — Adafruit 1314 (3" full-range, 4Ω 3W) -// See: reference/speakers/adafruit-1314.md +// Speaker — GRS 3FR-4 (3" full-range, 4Ω, 25W max). +// See: reference/speakers/grs-3fr-4.md +// +// Listed dimensions (Amazon / Parts Express): 3.2" × 3.7" × 2". +// Treating 3.7" (94 mm) as the largest lateral extent (across the +// mounting ears), and the magnet hangs ~43 mm below the frame plate +// based on user measurement. spk_post_h is set to give 1 mm of +// clearance between magnet bottom and bottom plate. // ============================================================ -spk_frame = 77.8; // square frame outer -spk_total_d = 25.49; // total depth incl. magnet -spk_mount_pattern = 60; // square M3 hole pattern (centers) -spk_mount_hole_d = 3.4; // M3 clearance -spk_cone_cutout = 67; // baffle opening; estimate, measure & update -spk_magnet_clearance = 30; // air below baffle for magnet + breathing +spk_frame = 95; // largest lateral extent (mounting-ear to mounting-ear) +spk_mount_pattern = 60; // square M3 hole pattern (centers) +spk_mount_hole_d = 3.4; // M3 clearance +spk_cone_cutout = 67; // baffle opening (estimate; measure & update) // ============================================================ // Daughterboard — protoboard the Atom presses onto. @@ -58,8 +59,8 @@ spk_magnet_clearance = 30; // air below baffle for magnet + breathing dboard_t = 1.6; dboard_w = atom_w + 14; dboard_d = atom_d + 14; -dboard_pin_h = 6; // male pin height above the daughterboard -dboard_standoff_h = 6; // air below the daughterboard +dboard_pin_h = 6; +dboard_standoff_h = 6; // ============================================================ // Snooze cap + well @@ -86,6 +87,29 @@ grille_hole_d = 2.5; grille_pitch = 5; grille_diameter = spk_cone_cutout; +// ============================================================ +// Speaker mounting posts on the bottom plate. +// +// Speaker rests on top of the posts; M3 self-tap screws come down +// through the speaker's mounting tabs into the post tops. With the +// speaker thus mounted to the base, the cover above is purely +// cosmetic — no fasteners pass through it. +// +// Post height: 44 mm puts the magnet 1 mm above the bottom plate +// (verified against the GRS 3FR-4's ~43 mm magnet protrusion). Bump +// up if you want more vibration isolation; drop to 42 mm if you want +// the magnet to seat on the plate (not recommended — couples magnet +// vibration to the plate and onward to the nightstand surface). +// ============================================================ + +spk_post_h = 44; +spk_post_d = 6; +spk_post_pilot_d = 2.5; + +// Foam tape on top of the speaker frame, compressed against the cover +// underside when assembled. Adds vibration damping + a light air seal. +foam_tape_t = 2; + // ============================================================ // Enclosure — overall printed shell // ============================================================ @@ -107,73 +131,53 @@ back_margin = 6; inner_w = max(dboard_w + 8, spk_frame + 6); inner_d = front_margin + snooze_well_d + zone_gap + spk_frame + back_margin; -inner_h = max(spk_magnet_clearance + 4, +inner_h = max(spk_post_h + foam_tape_t, dboard_standoff_h + dboard_t + dboard_pin_h + atom_body_h + 3); outer_w = inner_w + 2 * wall_t; outer_d = inner_d + 2 * wall_t; outer_h = inner_h + top_t; -// ============================================================ -// Speaker mounting posts on the bottom plate. -// Speaker rests on top of the posts, M3 self-tap screws come down -// through the speaker's mounting tabs into the post tops. With the -// speaker thus mounted to the base, the cover panel above is purely -// cosmetic — no fasteners pass through it. -// -// Post height targets the speaker frame plate at ~22 mm above the -// bottom plate, leaving ~3 mm clearance below the cover for a foam -// donut between frame and cover underside. Re-tune `spk_post_h` once -// you've measured the actual cone protrusion / magnet depth on a -// physical unit. -// ============================================================ - -spk_post_h = 22; -spk_post_d = 6; -spk_post_pilot_d = 2.5; - // ============================================================ // USB-C cable: routed internally, exits through a small notch at the -// bottom of the back wall. A printed strain-relief tunnel on the -// bottom plate grips the cable so a tug doesn't transfer to the -// connector. +// bottom of the back wall. The exit is offset to ~1/4 of the way +// across the back so it clears the centered snap-fit tab. An L-shaped +// clip on the bottom plate at the same X position routes and tensions +// the cable. // ============================================================ -cable_diameter = 4; // typical USB-C cable jacket OD +cable_diameter = 4; + +cable_x_offset = 14; // X position of the cable centerline (close to the side wall) cable_notch_w = cable_diameter + 2; cable_notch_h = cable_diameter + 2; -cable_clip_inner_w = cable_diameter + 0.4; // snug horizontal fit -cable_clip_inner_h = cable_diameter + 0.4; // snug vertical fit -cable_clip_wall_t = 1.5; -cable_clip_l = 8; // length along cable axis -cable_clip_y_from_back = 12; // from the back wall inside face +// L-clip dimensions. Post on one side of the cable, cap above +// extending laterally over the cable. The cable presses sideways into +// the open side of the L, and the post + cap + bottom plate contain +// it on three sides. +clip_post_w = 2; +clip_cap_h = 1.5; +clip_cap_overhang = cable_diameter + 1; +clip_l = 6; // length along the cable axis +clip_y_from_back = 14; // distance from the back wall to clip center // ============================================================ // Snap-fit cover retention. -// -// Four tabs rise from the bottom plate's top face, one centered on -// each side. Each tab carries a small hemispherical bump near its -// top, which catches in a matching detent recess on the chassis -// inner wall. Drop the chassis on, hear the snap; pull straight up -// firmly to remove. // ============================================================ snap_tab_w = 14; snap_tab_t = 2; snap_tab_h = 8; -snap_tab_clearance = 0.3; // gap between tab and chassis inner wall +snap_tab_clearance = 0.3; -snap_bump_d = 2; // hemisphere diameter -snap_bump_inset_from_top = 1.5; // bump center below tab top +snap_bump_d = 2; +snap_bump_inset_from_top = 1.5; -// Recess on the chassis inner wall — slightly larger than the bump -// for a positive click without binding. snap_recess_w = snap_tab_w + 2; snap_recess_h = snap_bump_d + 1; snap_recess_d = snap_bump_d / 2 + 0.4; -// Vertical center of the recess in chassis coords (chassis open bottom = z=0). snap_recess_cz = snap_tab_h - snap_bump_inset_from_top; // ============================================================ diff --git a/enclosure/parts/bottom-plate.scad b/enclosure/parts/bottom-plate.scad index cc82075..82ee9aa 100644 --- a/enclosure/parts/bottom-plate.scad +++ b/enclosure/parts/bottom-plate.scad @@ -37,10 +37,10 @@ module bottom_plate() { translate([0, 0, -bottom_plate_t]) rounded_prism([outer_w, outer_d, bottom_plate_t], chassis_round_r); - // Cable notch in the back edge of the plate, aligning with the - // chassis cable notch in the back wall — together they form a - // small rectangular hole flush with the bottom of the unit. - translate([(outer_w - cable_notch_w) / 2, + // Cable notch in the back edge of the plate, aligned with + // the chassis notch — together they form a small rectangular + // hole flush with the bottom of the unit. + translate([cable_x_offset - cable_notch_w / 2, outer_d - wall_t - EPS, -bottom_plate_t - EPS]) cube([cable_notch_w, wall_t + 2 * EPS, bottom_plate_t + 2 * EPS]); @@ -89,28 +89,30 @@ module speaker_posts() { } } -// A short rectangular tunnel for the USB cable. The cable threads -// through it during assembly; pulls on the cable transfer to the -// tunnel walls (and thus the bottom plate) instead of the connector. +// L-shaped cable clip: a short vertical post on the chamber-interior +// side of the cable with a horizontal cap above, extending toward the +// side wall. Cable rests in the inside corner of the L; cable is +// dropped in from above during assembly. Position matches the back- +// wall cable notch (offset horizontally) so the cable runs straight +// from the clip to the notch. module cable_clip() { - cy_center = outer_d - wall_t - cable_clip_y_from_back; - outer_w_l = cable_clip_inner_w + 2 * cable_clip_wall_t; - outer_h_l = cable_clip_inner_h + cable_clip_wall_t; // open at the bottom - - translate([(outer_w - outer_w_l) / 2, - cy_center - cable_clip_l / 2, - 0]) - difference() { - cube([outer_w_l, cable_clip_l, outer_h_l]); - - // Hollow the tunnel along the cable axis. - translate([cable_clip_wall_t, - -EPS, - 0]) // open at z=0 so the cable can drop in from above - cube([cable_clip_inner_w, - cable_clip_l + 2 * EPS, - cable_clip_inner_h]); - } + post_h = cable_diameter + clip_cap_h; + cap_w = clip_post_w + clip_cap_overhang; + cap_z = post_h - clip_cap_h; + // Post sits on the chamber-interior side of the cable; cap extends + // outward (toward the side wall). + post_x = cable_x_offset + cable_diameter / 2; + cap_x = post_x + clip_post_w - cap_w; + clip_y = outer_d - wall_t - clip_y_from_back; + + translate([0, clip_y - clip_l / 2, 0]) { + // Vertical post (right leg of the L, on the chamber-interior side). + translate([post_x, 0, 0]) + cube([clip_post_w, clip_l, post_h]); + // Horizontal cap (top leg, extending toward the side wall). + translate([cap_x, 0, cap_z]) + cube([cap_w, clip_l, clip_cap_h]); + } } // Four snap-fit tabs centered on each side of the cavity. Each carries diff --git a/enclosure/parts/chassis.scad b/enclosure/parts/chassis.scad index 2741267..4ade912 100644 --- a/enclosure/parts/chassis.scad +++ b/enclosure/parts/chassis.scad @@ -37,9 +37,10 @@ module chassis() { // the speaker; no M3 holes anywhere on the top panel. speaker_grille(); - // Cable notch in the back wall, at the bottom edge. The USB + // Cable notch in the back wall, at the bottom edge. Offset + // horizontally to clear the centered snap-fit tab. The USB // cable plugs into the Atom internally and exits here. - translate([(outer_w - cable_notch_w) / 2, + translate([cable_x_offset - cable_notch_w / 2, outer_d - wall_t - EPS, 0]) cube([cable_notch_w, wall_t + 2 * EPS, cable_notch_h]); diff --git a/reference/signal-chain.md b/reference/signal-chain.md index 0974c43..1ed271a 100644 --- a/reference/signal-chain.md +++ b/reference/signal-chain.md @@ -29,7 +29,7 @@ The onboard NS4168 on the Atom Echo is itself an I2S amp — the MAX98357A is in │ bridge-tied speaker output (V+ / V−) │ no common ground to the speaker ▼ - Adafruit 1314 (4Ω 3W) + GRS 3FR-4 (4Ω 25W max) ``` ## MAX98357A specs @@ -112,7 +112,7 @@ Free GPIOs on the Atom Echo after accounting for mic / amp / LED / button: | ---- | ------ | ----- | | M5Stack Atom Echo | owned | | | MAX98357A breakout | [Adafruit 3006][adafruit-3006] (~$6) or generic Amazon/AliExpress (~$3) | need 2 total for both units | -| Adafruit 1314 speaker | owned | | +| GRS 3FR-4 speaker | owned | see [reference/speakers/grs-3fr-4.md](./speakers/grs-3fr-4.md) | | 5V 2A USB wall adapter + USB-C cable | off-the-shelf | UL-listed brick | | Dupont wires / hookup wire | stock | | diff --git a/reference/speakers/adafruit-1314.md b/reference/speakers/adafruit-1314.md deleted file mode 100644 index 10b7c55..0000000 --- a/reference/speakers/adafruit-1314.md +++ /dev/null @@ -1,48 +0,0 @@ -# Adafruit 1314 — 3" speaker, 4Ω 3W - -Full-range driver, generic Chinese OEM, sold by Adafruit as ["Speaker - 3" Diameter - 4 Ohm 3 Watt"][adafruit-1314]. Chris already has two. - -## Published specs - -| Spec | Value | -| ----------- | ----- | -| Impedance | 4 Ω | -| Max power | 3 W | -| Cone diameter | 3" (76 mm nominal) | -| Frame (L×W×D) | 77.8 × 77.8 × 25.49 mm | -| Weight | 50.48 g | -| Mounting | 4 tabs, 60 mm apart | - -## Unknown / to measure from physical unit - -These aren't in the Adafruit listing and the Verical-hosted datasheet was unreachable at the time of this research. We'll measure when we have a unit on the bench: - -- **Cone cutout diameter** (baffle hole) — estimate ~65–70 mm based on standard 3" driver dimensions -- **Mounting hole diameter** (what screw fits the tabs) — likely M3 or similar -- **Magnet diameter and depth** — sets rear clearance needed inside the enclosure -- **Basket depth above / below the mounting flange** -- **Frequency response** — not published; irrelevant for white noise but would matter if we wanted music quality -- **Thiele-Small parameters** (Fs, Qts, Vas) — not published; fine, we're using a sealed box and not tuning - -## Why this is fine for our use - -- **Power match**: 3 W handling vs. MAX98357A delivering ~3.2 W into 4 Ω at 5V. Essentially matched; white noise never runs near max anyway. -- **Impedance match**: MAX98357A is rated for 4Ω loads. Exact match. -- **Size match**: 78 mm baffle + a few mm per side for the enclosure wall gives a face ~90 mm square. Reasonable nightstand footprint. -- **White noise doesn't care about bass extension**, so a sealed box with any sensible internal volume (~0.3 L+) will sound fine. Fill with polyfill / pillow stuffing to damp standing waves. - -## Enclosure design notes - -- Baffle opening will need to be cut to match the cone cutout (TBD from measurement). -- Four M3 (assumed) mounting holes in a 60 mm square pattern on the inside of the baffle. -- Magnet clearance at the rear: leave at least 30 mm behind the mounting flange until we measure. -- The 25.49 mm total depth means the whole driver (including magnet) fits within ~26 mm of baffle depth. -- Seal the baffle-to-frame joint (gasket, foam, or printed lip) to avoid air leaks that kill bass coupling. - -## Sources - -- [Adafruit product page for 1314][adafruit-1314] -- [Verical datasheet link (currently unreachable)][verical-1314] — referenced here for future attempts - -[adafruit-1314]: https://www.adafruit.com/product/1314 -[verical-1314]: https://www.verical.com/datasheet/adafruit-speakers-1314-5770604.pdf diff --git a/reference/speakers/grs-3fr-4.md b/reference/speakers/grs-3fr-4.md new file mode 100644 index 0000000..aa25c34 --- /dev/null +++ b/reference/speakers/grs-3fr-4.md @@ -0,0 +1,51 @@ +# GRS 3FR-4 — 3" full-range driver, 4 Ω, 25 W max + +Full-range driver from GRS, sold via Amazon and Parts Express. Chris has two. + +## Published specs + +| Spec | Value | +| ---- | ----- | +| Impedance | 4 Ω | +| Max power | 25 W | +| Frequency response | up to ~20 kHz (no low-end roll-off published) | +| Cone diameter | 3" (76 mm nominal) | +| Item dimensions (D × W × H) | 3.2 × 3.7 × 2 in (≈ 81 × 94 × 51 mm) | +| Mounting | 4 tabs at 60 mm pattern | + +## Measured / inferred from the unit on the bench + +These came out of sizing the enclosure to the actual hardware: + +- **Magnet protrusion below the frame plate**: ≈ 43 mm. The bottom-plate posts in the enclosure are sized 44 mm tall to give 1 mm of magnet-to-plate clearance. +- **Cone protrusion above the frame plate**: ≈ 8 mm (= total depth 51 − magnet 43, approximately). +- **Frame outer extent**: ≈ 94 mm at the largest lateral dimension (likely tip-to-tip across the mounting ears). Reflected in `spk_frame = 95` in the enclosure params. + +## Unknown / to measure when convenient + +- **Cone cutout diameter** (the baffle hole that needs to clear the moving cone) — estimated at ~67 mm in the params; verify with a caliper and update. +- **Mounting hole diameter** — assumed M3 clearance. Verify against the actual ears. +- **Frequency response curve** — not published. Irrelevant for white noise. +- **Thiele-Small parameters** (Fs, Qts, Vas) — not published. Fine, our enclosure isn't tuned. + +## Why this driver is fine for our use + +- **Power match**: 25 W handling vs. MAX98357A delivering ~3.2 W into 4 Ω at 5 V. Massive headroom — the amp is the limit, never the driver. +- **Impedance match**: MAX98357A is rated for 4 Ω loads. Exact match. +- **Size**: 3" full-range, ~95 mm frame, sits comfortably on a nightstand. The ~50 mm depth (deeper magnet than a 3 W full-range driver would have) drives a slightly taller enclosure but nothing dramatic. +- **White noise doesn't care about bass extension**, so a non-sealed printed box stuffed with polyfill (or not) will sound fine. + +## Enclosure design notes + +- Baffle opening (grille pattern in the cover) is sized to ~67 mm — tune to the actual cone cutout once measured. +- Four M3 mounting holes in a 60 mm square pattern. Speaker mounts to four 44 mm tall posts on the bottom plate, M3 self-tap into the post tops; no screws or holes through the cover top panel. +- Magnet hangs ~43 mm below the frame; with 44 mm posts the magnet bottom sits 1 mm above the bottom plate (vibration isolation; not resting on the plate). +- Foam tape on top of the frame compresses against the cover underside when the cover snaps on, giving a light air seal + damping any frame-to-cover rattle. + +## Sources + +- [GRS 3FR-4 product listing on Amazon][amazon-grs-3fr-4] +- [GRS speakers on Parts Express][parts-express-grs] — search "3FR-4" + +[amazon-grs-3fr-4]: https://www.amazon.com/dp/B00K2ESJZ2 +[parts-express-grs]: https://www.parts-express.com/cat/grs-speakers/178 -- 2.51.2