Files
MIS-Contro-Tower/rpi-case/rpi5_industrial_case_001.scad
2026-04-22 05:04:19 +00:00

290 lines
11 KiB
OpenSCAD
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================
// RPi5 Industrial Enclosure for Luckfox DHX-10.1" Touchscreen
// Version: 001
// ============================================================
// ── SCREEN PARAMETERS ───────────────────────────────────────
scr_w = 236; // screen outer width (mm)
scr_h = 144; // screen outer height (mm)
scr_d = 19; // screen outer depth (mm)
scr_active_w = 222; // active area width (mm) ← confirm
scr_active_h = 130; // active area height (mm) ← confirm
scr_mount_x = 75; // screen M2.5 mount pattern X (mm) ← verify
scr_mount_y = 75; // screen M2.5 mount 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 depth incl. 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 height between screen rear and Pi (mm)
// Pi offset from screen center (positive = up, right)
pi_offset_x = 0; // horizontal offset of Pi center from screen center
pi_offset_y = 5; // vertical offset upward from screen center
// ── ENCLOSURE PARAMETERS ─────────────────────────────────────
wall = 2.5; // wall thickness (mm)
chamfer = 1.5; // external edge chamfer (mm)
recess = 1.0; // screen recess depth in front bezel (mm)
gap = 0.3; // fit clearance between bezel and rear cover
// ── VENT PARAMETERS ──────────────────────────────────────────
vent_w = 3; // vent slot width (mm)
vent_l = 20; // vent slot length (mm)
vent_sp = 4; // slot pitch (edge to edge) (mm)
soc_vent_sz = 30; // SoC vent zone size (mm sq)
// ── CABLE GLAND PARAMETERS ───────────────────────────────────
gland_count = 2; // number of cable glands
gland_dia = 16.5; // M16 clearance hole diameter (mm)
gland_spacing = 40; // spacing between gland centers (mm)
// ── PEDESTAL PARAMETERS ──────────────────────────────────────
ped_tilt = 75; // tilt angle from vertical (deg) — screen tilts back
ped_depth = 80; // foot depth front-to-back (mm)
ped_width = 200; // foot width (mm)
ped_thick = 6; // foot plate thickness (mm)
ped_brace_h = 30; // height of triangular brace
// ── ASSEMBLY PARAMETERS ──────────────────────────────────────
m3_dia = 3.4; // M3 clearance hole
insert_dia = 4.2; // M3 heat-set insert OD
insert_h = 6; // heat-set insert depth
// ── DERIVED DIMENSIONS ───────────────────────────────────────
// Total rear cavity depth = standoffs + Pi + cable headroom
rear_d = pi_standoff + pi_d + 10; // 10 mm cable headroom
// Outer enclosure size
enc_w = scr_w + 2*wall;
enc_h = scr_h + 2*wall;
enc_d = rear_d + wall; // rear cover depth
// Pi center position relative to screen center
pi_cx = scr_w/2 + pi_offset_x;
pi_cy = scr_h/2 + pi_offset_y;
$fn = 48;
// ============================================================
// MODULES
// ============================================================
// Chamfered box (external chamfer via intersection with offset cube)
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]);
}
}
// Rounded slot (for vents)
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);
}
}
// M2.5 mounting hole
module m25_hole(d=10) {
cylinder(d=2.7, h=d);
}
// Heat-set insert boss + M3 hole
module insert_boss(h=insert_h+4) {
difference() {
cylinder(d=insert_dia+3, h=h);
cylinder(d=insert_dia, h=insert_h);
translate([0,0,insert_h]) cylinder(d=m3_dia, h=h);
}
}
// Single vent slot row (horizontal slots)
module vent_row(count, slot_len, slot_w, pitch, depth) {
for(i=[0:count-1]) {
translate([i*(slot_w+pitch), 0, 0])
slot(slot_len, slot_w, depth+0.1);
}
}
// ============================================================
// FRONT BEZEL
// ============================================================
module front_bezel() {
difference() {
// Outer chamfered shell
cbox(enc_w, enc_h, wall + recess);
// Active display window (recessed by 1 mm, then open)
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]);
// Bezel lip sits 1 mm over screen edge — recess pocket
translate([(enc_w - scr_w)/2,
(enc_h - scr_h)/2,
wall])
cube([scr_w, scr_h, recess + 0.1]);
// Corner M3 screw holes (through bezel flange, 4 corners)
for(x=[wall+6, enc_w-wall-6])
for(y=[wall+6, enc_h-wall-6])
translate([x, y, -0.1])
cylinder(d=m3_dia, h=wall+recess+0.2);
}
}
// ============================================================
// REAR COVER
// ============================================================
module rear_cover() {
difference() {
union() {
// Main body
cbox(enc_w, enc_h, enc_d);
// Pedestal foot (integral)
pedestal_foot();
// Heat-set insert bosses at 4 corners (inside)
for(x=[wall+6, enc_w-wall-6])
for(y=[wall+6, enc_h-wall-6])
translate([x, y, enc_d])
rotate([180,0,0])
insert_boss();
}
// Hollow interior
translate([wall, wall, wall])
cube([scr_w, scr_h, enc_d]);
// ── PORT CUTOUTS ──────────────────────────────────────
// USB-C power + 2× HDMI on LEFT edge (Pi left side)
// Pi left edge X position in enclosure coords
pi_left_x = pi_cx - pi_w/2 + wall;
// USB-C power (Pi left edge, near bottom of Pi)
translate([-0.1,
pi_cy - 8 + wall,
wall + pi_standoff + 2])
cube([wall+0.2, 10, 10]);
// HDMI #1
translate([-0.1,
pi_cx - pi_w/2 + wall + 15,
wall + pi_standoff + 2])
cube([wall+0.2, 16, 8]);
// HDMI #2
translate([-0.1,
pi_cx - pi_w/2 + wall + 34,
wall + pi_standoff + 2])
cube([wall+0.2, 16, 8]);
// Ethernet RJ45 on RIGHT edge
translate([enc_w - wall - 0.1,
pi_cy + pi_h/2 - 22 + wall,
wall + pi_standoff + 1])
cube([wall+0.2, 22, 16]);
// USB-A ×4 on RIGHT edge
translate([enc_w - wall - 0.1,
pi_cy - pi_h/2 + wall + 2,
wall + pi_standoff + 1])
cube([wall+0.2, 50, 14]);
// GPIO header on TOP edge
translate([pi_cx - 30 + wall,
enc_h - wall - 0.1,
wall + pi_standoff])
cube([52, wall+0.2, 12]);
// USB-C touch on left side edge of SCREEN (not Pi)
translate([-0.1, enc_h/2 - 6, wall + scr_d - 5])
cube([wall+0.2, 12, 8]);
// ── COOLING VENTS ──────────────────────────────────────
// Bottom intake slots
translate([enc_w/2 - (5*(vent_w+vent_sp))/2, -0.1, wall+8])
rotate([-90, 0, 0])
vent_row(5, vent_l, vent_w, vent_sp, wall+0.2);
// Top exhaust slots
translate([enc_w/2 - (5*(vent_w+vent_sp))/2,
enc_h - wall + 0.1,
wall+8])
rotate([90, 0, 0])
vent_row(5, vent_l, vent_w, vent_sp, wall+0.2);
// SoC direct vent (rear panel, over Pi SoC area)
// SoC assumed ~center of Pi board
translate([pi_cx - soc_vent_sz/2 + wall,
pi_cy - soc_vent_sz/2 + wall,
enc_d - wall - 0.1]) {
count_soc = floor(soc_vent_sz / (vent_w + vent_sp));
for(i=[0:count_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 ──────────────────────────────────────
for(i=[0:gland_count-1]) {
cx = enc_w/2 + (i - (gland_count-1)/2) * gland_spacing;
translate([cx, -0.1, wall + gland_dia/2 + 4])
rotate([-90,0,0])
cylinder(d=gland_dia, h=wall+0.2);
}
}
}
// ============================================================
// PEDESTAL FOOT (integral with rear cover)
// ============================================================
module pedestal_foot() {
// The foot projects from the bottom of the rear cover.
// It's a wedge that creates the tilt angle.
// When the assembly stands on the foot, the screen tilts back ped_tilt°.
//
// tilt_angle from vertical → wedge front height > back height.
// foot_front_h = ped_depth * tan(90-ped_tilt)
foot_front_h = ped_depth * tan(90 - ped_tilt);
foot_x0 = (enc_w - ped_width) / 2;
translate([foot_x0, 0, 0]) {
// Wedge base plate
hull() {
// Front edge (taller)
translate([0, -ped_depth, 0])
cube([ped_width, 0.1, foot_front_h + ped_thick]);
// Back edge (at enc base, flush)
translate([0, 0, 0])
cube([ped_width, 0.1, ped_thick]);
}
// Triangular side braces for rigidity
for(bx=[0, ped_width-ped_thick]) {
translate([bx, -ped_depth, 0])
linear_extrude(ped_thick)
polygon([[0,0],
[ped_depth, 0],
[ped_depth, foot_front_h]]);
}
}
}
// ============================================================
// RENDER — exploded assembly view
// ============================================================
// Front bezel at Z=0 (face down for printing, shown face up)
color("DarkSlateGray", 0.9)
translate([0, 0, enc_d + 5])
front_bezel();
// Rear cover
color("SlateGray", 0.9)
rear_cover();