openscad XL4015 chasis

// --- RENDER CONTROLS ---
show_enclosure = true;
show_lid = true;

// --- XL4015 Dimensions ---
pcb_w = 26.5;
pcb_l = 50.9;
wall = 3.2;
inner_w = pcb_w + 1.2;
inner_l = pcb_l + 1.2;
total_h = 24.0;

// --- M3 Nut & Bolt Settings ---
nut_hex_d = 6.4;
nut_depth = 2.8;
bolt_d = 3.4;

module parallelogram_cut(w, h, thickness, slant=3) {
poly_points = [[0, 0], [w, 0], [w + slant, h], [slant, h]];
rotate([90, 0, 90])
linear_extrude(height = thickness)
polygon(points = poly_points);
}

module enclosure() {
ext_w = inner_w + 2wall;
ext_l = inner_l + 2
wall;

difference() {    // 1. Solid Outer Shell    cube([ext_w, ext_l, total_h]);    // 2. Internal Cavity    translate([wall, wall, wall])         cube([inner_w, inner_l, total_h + 5]);    // --- 4 SMALL SQUARE FLOOR CUTOUTS ---    sq = 7.5;     translate([ext_w/2 - sq - 1.5, ext_l/2 - sq - 1.5, -1]) cube([sq, sq, wall + 2]);    translate([ext_w/2 + 1.5, ext_l/2 - sq - 1.5, -1]) cube([sq, sq, wall + 2]);    translate([ext_w/2 - sq - 1.5, ext_l/2 + 1.5, -1]) cube([sq, sq, wall + 2]);    translate([ext_w/2 + 1.5, ext_l/2 + 1.5, -1]) cube([sq, sq, wall + 2]);    // --- 4 HEX NUT HOLES (PCB MOUNT) ---    p_inset = 4.5;     translate([wall, wall, 0]) {        for(pos = [[p_inset, p_inset], [inner_w-p_inset, p_inset], [p_inset, inner_l-p_inset], [inner_w-p_inset, inner_l-p_inset]]) {            translate([pos[0], pos[1], -0.1]) {                cylinder(d=nut_hex_d / cos(30), h=nut_depth, $fn=6);                cylinder(d=bolt_d, h=wall + 1, $fn=24);            }        }    }    // --- 2 CHASSIS MOUNTING HOLES ---    translate([ext_w / 2, wall + 5, -1]) cylinder(d=bolt_d, h=wall + 2, $fn=24);    translate([ext_w / 2, ext_l - wall - 5, -1]) cylinder(d=bolt_d, h=wall + 2, $fn=24);    // --- SIDE PARALLELOGRAM VENTS ---    para_w = 7;    para_h = 10;    spacing = 11;    for(x_pos = [-0.5, ext_w - wall - 0.5]) {        for(y_off = [wall + 10 : spacing : ext_l - wall - 15]) {            translate([x_pos, y_off, wall + 6])                parallelogram_cut(para_w, para_h, wall + 1, 3);        }    }    // --- IMPROVED TERMINAL ACCESS (U-SHAPED SLOTS) ---    // We cut from a lower Z point all the way past the top (total_h)    terminal_width = inner_w - 4; // Widened for easier wire management    // Input Side    translate([(ext_w - terminal_width)/2, -1, wall + 4])         cube([terminal_width, wall + 2, total_h]);     // Output Side    translate([(ext_w - terminal_width)/2, ext_l - wall - 1, wall + 4])         cube([terminal_width, wall + 2, total_h]); }

}

module lid() {
lid_w = inner_w + 2wall;
lid_l = inner_l + 2
wall;
difference() {
union() {
cube([lid_w, lid_l, 2.0]);
translate([wall + 0.3, wall + 0.3, 2.0])
difference() {
cube([inner_w - 0.6, inner_l - 0.6, 4.0]);
translate([1.5, 1.5, -0.1])
cube([inner_w - 3.6, inner_l - 3.6, 5.0]);
}
}
// Lid Windows
win_w = 12;
win_l = 18;
translate([lid_w/2 - win_w - 2, lid_l/2 - win_l - 2, -1]) cube([win_w, win_l, 10]);
translate([lid_w/2 + 2, lid_l/2 - win_l - 2, -1]) cube([win_w, win_l, 10]);
translate([lid_w/2 - win_w - 2, lid_l/2 + 2, -1]) cube([win_w, win_l, 10]);
translate([lid_w/2 + 2, lid_l/2 + 2, -1]) cube([win_w, win_l, 10]);
}
}

// Render
if (show_enclosure) enclosure();
if (show_lid) translate([show_enclosure ? (inner_w + wall * 6) : 0, 0, 0]) lid();