290 lines
11 KiB
OpenSCAD
290 lines
11 KiB
OpenSCAD
// ============================================================
|
||
// 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();
|