pre-bemis

This commit is contained in:
Marcelo
2026-04-22 05:04:19 +00:00
parent ac1a7900c8
commit 80d27f83b6
91 changed files with 11769 additions and 820 deletions

View File

@@ -0,0 +1,354 @@
// ============================================================
// RPi5 Industrial Enclosure — 7" Capacitive Touchscreen
// Version: 005
//
// ASSEMBLY LOGIC (read before printing):
//
// THREE separate printed parts:
//
// 1. REAR COVER — the main box. Open face points toward screen.
// Four corner TOWERS rise from the open front face; each tower
// has a self-tapping M3 pilot hole that opens toward the screen.
// The kickstand prong columns rise from the inner bottom face.
//
// 2. FRONT BEZEL — the display frame. Four countersunk M3 holes at
// the corners align with the rear cover's tower holes.
// Assembly: lay screen face-down, place rear cover over it,
// lay bezel over the front, drive 4× M3×30 self-tapping screws
// from the bezel face through into the corner towers.
//
// 3. KICKSTAND — separate wedge plate. Slide its 3 prongs upward
// into the 3 slots in the case bottom wall. The prong guide
// columns inside the case prevent the prongs from falling into
// the main cavity and give a solid 14 mm engagement.
//
// Changes vs 004:
// - Screen resized to 164.9 × 124.27 mm (7" 1024×600 capacitive)
// - Corner towers replace insert bosses: visible M3 holes on the
// OPEN front face of the rear cover — no hidden geometry
// - Prong guide columns (nested-difference CSG) give the slots a
// closed ceiling so the kickstand prongs cannot fall through
// - Left-wall USB-C touch cutout permanently removed
// - Wall 4 mm retained
// ============================================================
// ── SCREEN PARAMETERS ───────────────────────────────────────
scr_w = 164.9; // screen outer width (mm)
scr_h = 124.27; // screen outer height (mm)
scr_d = 12; // screen body depth (mm) ← confirm with calipers
scr_active_w = 154; // active display width (mm) ← confirm
scr_active_h = 90; // active display height (mm) ← confirm
scr_mount_x = 75; // rear M2.5 hole pattern X (mm) ← verify
scr_mount_y = 75; // rear M2.5 hole pattern Y (mm) ← verify
// ── RASPBERRY PI 5 PARAMETERS ────────────────────────────────
pi_w = 85; // Pi board width (mm)
pi_h = 56; // Pi board height (mm)
pi_d = 17; // Pi board + tallest component (mm)
pi_mnt_x = 58; // Pi mount hole pattern X (mm)
pi_mnt_y = 49; // Pi mount hole pattern Y (mm)
pi_standoff = 5; // standoff: screen rear → Pi PCB (mm)
pi_offset_x = 0; // Pi centre X offset from screen centre (mm)
pi_offset_y = 0; // Pi centre Y offset from screen centre (mm)
// ── ENCLOSURE PARAMETERS ─────────────────────────────────────
wall = 4.0; // wall thickness (mm)
chamfer = 1.5; // external edge chamfer (mm)
recess = 1.0; // screen recess depth in front bezel (mm)
// ── VENT PARAMETERS ──────────────────────────────────────────
vent_w = 3; // slot width (mm)
vent_l = 18; // slot length (mm)
vent_sp = 4; // gap edge-to-edge (mm)
soc_vent_sz = 28; // SoC vent zone (mm, square)
// ── CABLE GLAND PARAMETERS ───────────────────────────────────
gland_count = 2; // number of M16 cable glands
gland_dia = 16.5; // M16 clearance hole diameter (mm)
gland_spacing= 36; // gland centre-to-centre (mm)
// ── KICKSTAND PARAMETERS ─────────────────────────────────────
ks_tilt = 75; // screen angle from horizontal when standing (deg)
ks_depth = 60; // plate reach behind rear face (mm)
ks_thick = 5; // plate thickness at thin (prong) end (mm)
ks_prong_n = 3; // number of prongs
ks_prong_w = 12; // prong width in X (mm)
ks_prong_h = 14; // prong engagement height (mm) — guided inside column
ks_prong_t = 5; // prong thickness in Z (mm)
ks_prong_clr = 0.25; // clearance per side for slide fit (mm)
// ── ASSEMBLY PARAMETERS ──────────────────────────────────────
m3_dia = 3.4; // M3 clearance hole (mm)
m3_pilot = 2.5; // M3 self-tapping pilot hole (mm)
m3_cs_dia = 6.5; // M3 countersink OD (mm)
m3_cs_depth = 3.5; // countersink depth (mm)
// Corner tower — a full-depth solid pillar at each inner corner.
// The M3 pilot hole is drilled from the open front face of the rear cover.
tower_w = 10; // tower footprint width and depth (mm)
tower_hole_d = 12; // M3 pilot hole depth from front face (mm)
// ── DERIVED DIMENSIONS ───────────────────────────────────────
rear_d = pi_standoff + pi_d + 10; // rear cavity depth = 32 mm
enc_w = scr_w + 2*wall; // outer width = 172.9 mm
enc_h = scr_h + 2*wall; // outer height = 132.27 mm
enc_d = rear_d + wall; // rear cover depth = 36 mm
// Pi centre in enclosure coordinates
pi_enc_cx = wall + scr_w/2 + pi_offset_x;
pi_enc_cy = wall + scr_h/2 + pi_offset_y;
pi_z = wall + pi_standoff; // Pi PCB Z from rear face
// Corner tower position — inset so tower is entirely within the wall zone
// (tower must NOT overlap the screen footprint X=wall..wall+scr_w)
tower_cx = wall/2; // tower centre offset from outer edge
// Four tower centre positions
tower_xs = [tower_cx, enc_w - tower_cx];
tower_ys = [tower_cx, enc_h - tower_cx];
// Kickstand wedge geometry
ks_drop = ks_depth * tan(90 - ks_tilt); // tip drop ≈ 16 mm
// Prong column Z extent (guide column behind and into cavity)
col_z_size = ks_prong_t + 2*wall; // = 13 mm
col_y_size = ks_prong_h; // = 14 mm (above inner bottom face)
col_x_size = ks_prong_w + wall; // = 16 mm (centred on prong)
$fn = 48;
// ============================================================
// PRIMITIVES
// ============================================================
module cbox(w, h, d, c=chamfer) {
hull() {
translate([c, c, 0]) cube([w-2*c, h-2*c, d ]);
translate([0, c, c]) cube([w, h-2*c, d-2*c ]);
translate([c, 0, c]) cube([w-2*c, h, d-2*c ]);
}
}
module slot(len, w, d) {
r = w/2;
hull() {
translate([0, -len/2+r, 0]) cylinder(r=r, h=d);
translate([0, len/2-r, 0]) cylinder(r=r, h=d);
}
}
module vent_row(n, len, w, spacing, depth) {
for(i = [0:n-1])
translate([i*(w+spacing), 0, 0])
slot(len, w, depth);
}
// Countersunk M3 through-hole for bezel face
module m3_countersunk(total_depth) {
cylinder(d=m3_dia, h=total_depth+0.1);
cylinder(d1=m3_cs_dia, d2=m3_dia, h=m3_cs_depth+0.1);
}
// Prong slot cutter — used in both the rear cover and the guide column
// Origin at the prong centre-X, outer bottom face (Y=0), prong-Z start
module prong_slot_cut() {
translate([-ks_prong_w/2 - ks_prong_clr,
-0.1,
-ks_prong_clr])
cube([ks_prong_w + 2*ks_prong_clr,
wall + ks_prong_h + 0.2,
ks_prong_t + 2*ks_prong_clr]);
}
// ============================================================
// KICKSTAND (separate removable piece, print separately)
// ============================================================
module kickstand() {
ks_front_h = ks_thick + ks_drop; // height at the thick/front end
// Wedge plate — thin at prong end (Z=0), thick at desk end (Z=-ks_depth)
hull() {
translate([0, -ks_thick, 0])
cube([enc_w, ks_thick, wall]);
translate([0, -ks_front_h, -ks_depth])
cube([enc_w, ks_front_h, wall]);
}
// Three tapered prongs on the top edge (rear/thin end)
for(i = [0:ks_prong_n-1]) {
px = enc_w * (i+1) / (ks_prong_n+1);
translate([px - ks_prong_w/2, 0, 0]) {
// Body of prong
cube([ks_prong_w, ks_prong_h - 2, ks_prong_t]);
// Tapered tip (last 2 mm, narrowed 1 mm per side)
translate([0, ks_prong_h - 2, 0])
hull() {
cube([ks_prong_w, 0.01, ks_prong_t]);
translate([1, 2, 0])
cube([ks_prong_w - 2, 0.01, ks_prong_t]);
}
}
}
}
// ============================================================
// FRONT BEZEL (removable — 4× M3 countersunk screws)
// ============================================================
module front_bezel() {
difference() {
cbox(enc_w, enc_h, wall + recess);
// Display window
translate([(enc_w - scr_active_w)/2,
(enc_h - scr_active_h)/2,
-0.1])
cube([scr_active_w, scr_active_h, wall+recess+0.2]);
// 1 mm recess pocket — bezel lip grips screen edge
translate([(enc_w - scr_w)/2,
(enc_h - scr_h)/2,
wall])
cube([scr_w, scr_h, recess+0.1]);
// 4× M3 countersunk screw holes, aligned to corner towers
for(x = tower_xs) for(y = tower_ys)
translate([x, y, 0])
m3_countersunk(wall + recess);
}
}
// ============================================================
// REAR COVER
// ============================================================
//
// CORNER TOWER DESIGN — replaces hidden insert bosses:
// Each corner has a solid square tower (tower_w × tower_w) that
// runs the FULL DEPTH of the cavity (from inner rear face to the
// open front at Z=enc_d). An M3 pilot hole enters from the front
// face (Z=enc_d) and goes tower_hole_d into the tower body.
// Because the tower reaches the front opening, the holes are
// plainly visible from the front of the assembled unit — no
// hidden geometry.
//
// PRONG COLUMN DESIGN — prevents prongs falling into cavity:
// A solid rectangular column rises from the inner bottom face at
// each prong position. The prong slot cuts through the bottom wall
// AND the column. The column ceiling is at Y=wall+ks_prong_h,
// which acts as the hard stop for the prong — it cannot travel
// beyond that height. The column is added AFTER the main interior
// hollow is subtracted (nested-difference CSG), so the hollow
// does not remove it.
//
module rear_cover() {
n_vent = 5;
vent_block_w = n_vent*(vent_w+vent_sp) - vent_sp;
difference() {
// ── SOLID GEOMETRY ────────────────────────────────────
union() {
// 1. Main shell with interior already removed
// (nested so subsequent additions are NOT removed by hollow)
difference() {
cbox(enc_w, enc_h, enc_d);
// Interior hollow — from rear inner face to front opening
translate([wall, wall, wall])
cube([scr_w, scr_h, enc_d]);
}
// 2. Corner towers — full cavity height, clearly visible from front
for(x = tower_xs) for(y = tower_ys)
translate([x - tower_w/2, y - tower_w/2, wall])
cube([tower_w, tower_w, enc_d - wall]);
// 3. Prong guide columns — solid pillars on inner bottom face
// One per prong, gives 14 mm of guided engagement
for(i = [0:ks_prong_n-1]) {
px = enc_w * (i+1) / (ks_prong_n+1);
translate([px - col_x_size/2,
wall,
0])
cube([col_x_size, col_y_size, col_z_size]);
}
}
// ── ALL CUTOUTS ───────────────────────────────────────
// Corner tower M3 pilot holes (from front/open face, going inward)
for(x = tower_xs) for(y = tower_ys)
translate([x, y, enc_d + 0.1])
rotate([180, 0, 0])
cylinder(d=m3_pilot, h=tower_hole_d);
// ── PORT CUTOUTS ──────────────────────────────────────
pi_bot = pi_enc_cy - pi_h/2;
pi_top = pi_enc_cy + pi_h/2;
// LEFT WALL — USB-C power + HDMI ×2
translate([-0.1, pi_bot + 3, pi_z + 2]) cube([wall+0.2, 11, 11]);
translate([-0.1, pi_bot + 16, pi_z + 2]) cube([wall+0.2, 17, 9]);
translate([-0.1, pi_bot + 35, pi_z + 2]) cube([wall+0.2, 17, 9]);
// RIGHT WALL — RJ45 + USB-A ×4
translate([enc_w-wall-0.1, pi_top - 24, pi_z + 1])
cube([wall+0.2, 22, 16]);
translate([enc_w-wall-0.1, pi_bot + 2, pi_z + 1])
cube([wall+0.2, 50, 15]);
// ── COOLING VENTS ─────────────────────────────────────
// Bottom intake
translate([enc_w/2 - vent_block_w/2, -0.1, wall + 6])
rotate([-90, 0, 0])
vent_row(n_vent, vent_l, vent_w, vent_sp, wall+0.2);
// Top exhaust
translate([enc_w/2 - vent_block_w/2, enc_h - wall + 0.1, wall + 6])
rotate([90, 0, 0])
vent_row(n_vent, vent_l, vent_w, vent_sp, wall+0.2);
// SoC direct-vent on rear panel
translate([pi_enc_cx - soc_vent_sz/2,
pi_enc_cy - soc_vent_sz/2,
enc_d - wall - 0.1]) {
n_soc = floor(soc_vent_sz / (vent_w + vent_sp));
for(i = [0:n_soc-1])
translate([i*(vent_w+vent_sp), soc_vent_sz/2 - vent_l/2, 0])
slot(vent_l, vent_w, wall+0.2);
}
// ── CABLE GLANDS — rear panel face ────────────────────
for(i = [0:gland_count-1]) {
cx = enc_w/2 + (i - (gland_count-1)/2) * gland_spacing;
translate([cx, wall + gland_dia/2 + 4, -0.1])
cylinder(d=gland_dia, h=wall+0.2);
}
// ── KICKSTAND PRONG SLOTS ─────────────────────────────
// Each slot cuts through the outer bottom wall AND the guide
// column above it. The column ceiling at Y=wall+ks_prong_h
// is the hard stop — the prong cannot fall through.
for(i = [0:ks_prong_n-1]) {
px = enc_w * (i+1) / (ks_prong_n+1);
translate([px, 0, 0])
prong_slot_cut();
}
}
}
// ============================================================
// SCENE — three parts exploded for visual clarity
// ============================================================
// FRONT BEZEL — floated forward (toward viewer)
color("DarkSlateGray", 0.92)
translate([0, 0, enc_d + 14])
front_bezel();
// REAR COVER — at origin
color("SlateGray", 0.88)
rear_cover();
// KICKSTAND — floated below the case to show it is a separate piece
color("DimGray", 0.85)
translate([0, -(ks_thick + ks_drop + 20), 0])
kickstand();