Read this model as text
A stackable case for a Mini-ITX NAS board, sized so every part prints on a 180 mm bed (Bambu A1 mini). The stack is a base module that carries the board, bay modules with a bolt grid in the floor that take drive trays or anything else you design for the grid, and a lid with a honeycomb relief across its whole top that opens into a grille over the fan and pulls air up through the stack. Modules locate on each other with a lip and pocket and bolt together with M3 screws into captive nuts.
The image shows the solid OpenSCAD renders at part assembly · bay_modules 2 · hang_hdd true · explode 0 · show_hardware true · board 170 · board_clear 0.5 · standoff_h 6.5 · standoff_hole 2.6 · hole_rear_a 6.35 · hole_rear_b 163.83 · hole_side_a 10.16 · hole_side_b 165.1 · board_h 60 · button_d 16 · button_x 88 · button_z 36 · button_ring true · jack_d 12 · jack_pos rear · jack_x 150 · jack_z 42 · vents true · vent_w 2 · vent_pitch 6 · hdd_w 101.6 · hdd_l 147 · hdd_h 26.1 · hdd_gap 3 · grid_boss_h 3 · tray_t 3 · fan_size 80 · fan_t 25 · lid_relief 1 · lid_ch 2.5 · io_x 0 · io_w 170 · io_h 20 · wall 3 · floor_t 2.5 · top_t 2.5 · corner_r 2 · edge_ch 0.8 · lip_h 4 · lip_t 1.5 · lip_c 0.2 · nut_af 5.7 · foot_h 8 · color_case Silver.
Stackable Mini-ITX NAS case
mick/itx-nas-stack@1.5.0
Report
For a legal or policy problem: a license violation, personal data, somebody else’s work republished as their own. A model that prints badly is a comment, not a report.
Parameters
from sourceDescription
What is this
A stackable case for a Mini-ITX NAS board, sized so every part prints on a 180 mm bed (Bambu A1 mini). The stack is a base module that carries the board, bay modules with a bolt grid in the floor that take drive trays or anything else you design for the grid, and a lid with a honeycomb relief across its whole top that opens into a grille over the fan and pulls air up through the stack. Modules locate on each other with a lip and pocket and bolt together with M3 screws into captive nuts.
What you use it for
A slim, clean NAS around a 170 × 170 board with a pico PSU: DC barrel jack in the rear shield just above the ports (or in a side wall), a centred 16 mm vandal switch in the front, the rear I/O open above the board with a flat rear shield that slides down into grooves. Each bay module has a grid of 72 bosses on an 18 mm pitch; the 3.5" tray screws to the drive's bottom holes with standard 6-32 drive screws and bolts down on any four bosses with M3 × 8, so the drive can sit anywhere on the grid and the rest of the bay is free for a second tray, an SSD, a fan or whatever fits 18 mm steps. The grid holes go through the floor, so the hanging tray bolts a second drive upside down under the same floor, into the free air above a low CPU cooler in the board module: two drives in one bay, or a drive with no bay at all. Screw-on feet lift the base module for air under the floor. A rear cutout in every floor passes the SATA cables down to the board.
Design notes
The footprint is board + clearance + two walls, 177 mm by default, which is why the walls are three millimetres and the case is not wider. Every module has a pocket ring under its floor and a lip ring on top; the lip is the inner half of the wall so the outside stays flush, and a chamfer on the top edge draws a seam line at every joint; the lid carries a deeper chamfer so it reads as a cap. The lid top is one honeycomb: raised hexagons with a recessed wall network everywhere, and the same cells cut through over the fan, so the grille is part of the pattern instead of a hole in it. The fan screws from the inside into four bosses under the top plate, so nothing shows on top. Printed upside down, the tiles lie on the bed and the grooves are short bridges. The floor of every module sits on a rib grid so the pocket is a two millimetre bridge and nothing else is unsupported; the hanging tray carries pads that reach up between those ribs to the floor. Four bosses hang in the top corners of every module, each with a side slot that traps an M3 nut under 2.5 mm of material, so a bolt from the module above pulls the two together. The bosses taper at 45° so they print without support and sit above the ports in the rear corners. The feet plug into the corner cells of the rib grid and bolt through the same floor holes. The board module has no rear wall above the board, because the ports on these NAS boards run edge to edge; its rear lip is carried by the rear shield instead, and stops in every pocket block the stack from sliding rearward. Bolts: M3 × 12 between modules, for the feet and for the hanging tray, M3 × 35 for the lid, M3 × 30 for the fan, M3 × 8 for trays, 6-32 for the drive. Tolerances are tuned for PETG on an A1 mini: 0.2 mm on the lip, 0.5 mm around the board, 0.3 mm in holes, 0.2 mm on nuts.
Parameters
part picks the assembly or one printable part in print orientation. hang_hdd shows a drive hanging under the lowest bay in the assembly. hole_rear_a/b and hole_side_a/b are the standoff positions measured from the rear and left edges of the board; the defaults are the Mini-ITX spec, check them on your board. board_h sets the height of the board module; a hanging drive leaves board_h minus 44 mm for the CPU cooler above the board. button_d/x/z place the switch, button_ring recesses a ring around it. jack_pos puts the DC jack in the rear shield or a side wall, jack_x/jack_z place it. hdd_w/l/h size the drive and tray, hdd_gap the room above it, grid_boss_h the height of the floor grid. fan_size picks the fan (0 for a plain lid), lid_relief the depth of the honeycomb (0 for a flat lid), lid_ch the lid chamfer. io_x/io_w/io_h cut one opening in the rear shield. wall, lip_h, lip_t, lip_c and edge_ch tune the fit and the seam between modules; nut_af is the nut size across flats, foot_h the height of the feet.
Use with your agent
{
"mcpServers": {
"remixcad": {
"type": "http",
"url": "https://remix-cad.vercel.app/api/mcp"
}
}
}get_model("mick/itx-nas-stack@1.5.0")Returns the manifest, the source, the import closure and the license obligations. Full MCP setup.
Parameter table
Parsed from the Customizer annotations in main.scad| Name | Default | Range | Unit | Description |
|---|---|---|---|---|
| part | "assembly" | assembly, board_module, bay_module, tray_35, tray_35_hanging, lid, rear_shield, foot | ||
| bay_modules | 2 | 0 to 4 step 1 | ||
| hang_hdd | true | |||
| explode | 0 | 0 to 80 step 5 | ||
| show_hardware | true | |||
| board | 170 | 120 to 172 step 1 | ||
| board_clear | 0.5 | 0.3 to 1.5 step 0.1 | ||
| standoff_h | 6.5 | 4 to 10 step 0.5 | ||
| standoff_hole | 2.6 | 2.4 to 4.5 step 0.1 | ||
| hole_rear_a | 6.35 | 2 to 40 step 0.01 | ||
| hole_rear_b | 163.83 | 130 to 168 step 0.01 | ||
| hole_side_a | 10.16 | 2 to 40 step 0.01 | ||
| hole_side_b | 165.1 | 130 to 168 step 0.01 | ||
| board_h | 60 | 40 to 90 step 1 | ||
| button_d | 16 | 0 to 22 step 0.5 | ||
| button_x | 88 | 10 to 167 step 0.5 | ||
| button_z | 36 | 15 to 80 step 1 | ||
| button_ring | true | |||
| jack_d | 12 | 0 to 16 step 0.5 | ||
| jack_pos | "rear" | rear, right, left | ||
| jack_x | 150 | 10 to 160 step 1 | ||
| jack_z | 42 | 12 to 80 step 1 | ||
| vents | true | |||
| vent_w | 2 | 1.5 to 4 step 0.5 | ||
| vent_pitch | 6 | 4 to 12 step 0.5 | ||
| hdd_w | 101.6 | 69 to 102 step 0.1 | ||
| hdd_l | 147 | 100 to 150 step 0.1 | ||
| hdd_h | 26.1 | 7 to 30 step 0.1 | ||
| hdd_gap | 3 | 2 to 10 step 0.5 | ||
| grid_boss_h | 3 | 2 to 5 step 0.5 | ||
| tray_t | 3 | 2.5 to 4 step 0.1 | ||
| fan_size | 80 | 0, 40, 60, 80, 92, 120 | ||
| fan_t | 25 | 10 to 30 step 1 | ||
| lid_relief | 1 | 0 to 1.5 step 0.2 | ||
| lid_ch | 2.5 | 0 to 4 step 0.5 | ||
| io_x | 0 | 0 to 170 step 0.5 | ||
| io_w | 170 | 10 to 170 step 0.5 | ||
| io_h | 20 | 5 to 60 step 0.5 | ||
| wall | 3 | 2.5 to 4 step 0.1 | ||
| floor_t | 2.5 | 2 to 4 step 0.1 | ||
| top_t | 2.5 | 2 to 4 step 0.1 | ||
| corner_r | 2 | 0 to 3 step 0.5 | ||
| edge_ch | 0.8 | 0 to 1.5 step 0.1 | ||
| lip_h | 4 | 3 to 6 step 0.5 | ||
| lip_t | 1.5 | 1.2 to 2 step 0.1 | ||
| lip_c | 0.2 | 0.1 to 0.4 step 0.05 | ||
| nut_af | 5.7 | 5.4 to 6.2 step 0.1 | ||
| foot_h | 8 | 5 to 15 step 0.5 | ||
| color_case | "Silver" | Silver, Gainsboro, White, DimGray, Black, SlateGray, FireBrick, SteelBlue, ForestGreen, Goldenrod |
Lineage
0 models depend on this oneOnly what this model came from and what came from it.
License
Whoever downloads this takes these obligations along- mick/itx-nas-stack@1.5.0 is MIT
Source
main.scad is the entrypointmain.scad
// Stackable Mini-ITX NAS case for a small printer (180 mm bed).
// A base module carries the board, bay modules carry drive trays on a bolt grid,
// and a fan lid closes the stack and pulls air up through it. Modules print
// upright as one piece, the lid prints upside down, the shield, trays and feet flat.
// Modules bolt together with M3 screws into nuts trapped in corner bosses.
/* [Parts] */
// The whole stack, or one part in print orientation.
part = "assembly"; // [assembly, board_module, bay_module, tray_35, tray_35_hanging, lid, rear_shield, foot]
// Bay modules shown in the assembly.
bay_modules = 2; // [0:1:4]
// Show a drive hanging under the lowest bay, above the board.
hang_hdd = true;
// Pull the stack apart in the assembly view.
explode = 0; // [0:5:80]
// Show the board and the drives as ghosts in the assembly.
show_hardware = true;
/* [Board] */
// Board size, 170 for Mini-ITX.
board = 170; // [120:1:172]
// Gap between the board edge and the wall, each side.
board_clear = 0.5; // [0.3:0.1:1.5]
// Height of the printed standoffs under the board.
standoff_h = 6.5; // [4:0.5:10]
// Screw hole in the standoffs, 2.6 for a self tapping M3.
standoff_hole = 2.6; // [2.4:0.1:4.5]
// Mounting holes, measured from the rear (I/O) edge of the board.
hole_rear_a = 6.35; // [2:0.01:40]
hole_rear_b = 163.83; // [130:0.01:168]
// Mounting holes, measured from the left edge of the board, seen from the front.
hole_side_a = 10.16; // [2:0.01:40]
hole_side_b = 165.1; // [130:0.01:168]
// Height of the board module. With a hanging drive the cooler gets board_h minus 44 mm.
board_h = 60; // [40:1:90]
/* [Front, rear and sides] */
// Thread diameter of the power button, 16 for the common vandal switch. 0 for none.
button_d = 16; // [0:0.5:22]
// Button position from the left, and height from the module bottom. 88 is centred.
button_x = 88; // [10:0.5:167]
button_z = 36; // [15:1:80]
// Shallow ring recessed around the button.
button_ring = true;
// Panel mount DC jack hole, 0 for none.
jack_d = 12; // [0:0.5:16]
// Where the DC jack sits: in the rear shield above the ports, or in a side wall.
jack_pos = "rear"; // [rear, right, left]
// Jack position: from the left edge of the board (rear), or from the rear (sides).
jack_x = 150; // [10:1:160]
// Jack height from the module bottom.
jack_z = 42; // [12:1:80]
// Vertical vent slots in the side walls.
vents = true;
vent_w = 2; // [1.5:0.5:4]
vent_pitch = 6; // [4:0.5:12]
/* [Drives] */
// Size of the disk, 3.5" by default.
hdd_w = 101.6; // [69:0.1:102]
hdd_l = 147; // [100:0.1:150]
hdd_h = 26.1; // [7:0.1:30]
// Room above the disk.
hdd_gap = 3; // [2:0.5:10]
// Height of the bolt grid bosses on the bay floor.
grid_boss_h = 3; // [2:0.5:5]
// Thickness of the drive tray.
tray_t = 3; // [2.5:0.1:4]
/* [Lid] */
// Fan in the lid, 0 for a plain lid.
fan_size = 80; // [0, 40, 60, 80, 92, 120]
// Thickness of the fan.
fan_t = 25; // [10:1:30]
// Depth of the honeycomb relief over the whole lid. 0 for a flat lid.
lid_relief = 1; // [0:0.2:1.5]
// Chamfer on the top edge of the lid.
lid_ch = 2.5; // [0:0.5:4]
/* [Rear shield] */
// One opening in the rear shield: from the left edge of the board, its width, and its height from the shield bottom.
io_x = 0; // [0:0.5:170]
io_w = 170; // [10:0.5:170]
io_h = 20; // [5:0.5:60]
/* [Case] */
wall = 3; // [2.5:0.1:4]
floor_t = 2.5; // [2:0.1:4]
top_t = 2.5; // [2:0.1:4]
// Rounding of the vertical outer corners.
corner_r = 2; // [0:0.5:3]
// Chamfer on the top outer edge of every module, the seam line in the stack.
edge_ch = 0.8; // [0:0.1:1.5]
// Height and thickness of the stacking lip, and its play in the pocket.
lip_h = 4; // [3:0.5:6]
lip_t = 1.5; // [1.2:0.1:2]
lip_c = 0.2; // [0.1:0.05:0.4]
// M3 nut across flats, plus play.
nut_af = 5.7; // [5.4:0.1:6.2]
// Height of the screw-on feet.
foot_h = 8; // [5:0.5:15]
/* [Colour] */
// Display only, the STL carries no colour.
color_case = "Silver"; // [Silver, Gainsboro, White, DimGray, Black, SlateGray, FireBrick, SteelBlue, ForestGreen, Goldenrod]
/* [Hidden] */
$fn = 48;
pcb_t = 1.6;
S = board + 2 * (board_clear + wall);
skirt_t = wall - lip_t - lip_c;
rib_in = wall + lip_c + 0.1;
rib_t = 1.6;
grid_p = 18;
stop_len = 6;
stop_end = wall + stop_len;
groove_d = 1.0;
shield_t = 1.6;
bs = 9; // corner boss size
boss_h = 12;
nut_h = 2.8;
nut_ac = nut_af / cos(30); // across corners
nut_top = 2.5; // material above a trapped nut
bolt_d = 3.4;
bc = wall + bs / 2; // bolt centre from the outer faces
z0 = lip_h + floor_t;
board_z = z0 + standoff_h;
rear_top = board_z - 0.5;
cell_in = rib_in + rib_t; // corner cell starts here
plug = grid_p - rib_t / 2 - cell_in - 0.6;
bay_h = z0 + grid_boss_h + tray_t + hdd_h + hdd_gap;
lid_wall = rib_in + rib_t;
fan_boss_h = 3;
lid_h = top_t + (fan_size > 0 ? fan_boss_h + fan_t + 1.5 : 5);
fan_hole = lookup(fan_size, [[40, 32], [60, 50], [80, 71.5], [92, 82.5], [120, 105]]);
hex_af = 6; // honeycomb cell across flats
hex_w = 1.8; // honeycomb wall
tray_span = ceil((hdd_w + 8) / grid_p) * grid_p; // flange hole spacing, a grid multiple
tray_fx = (hdd_w - tray_span) / 2; // flange hole x, left of the drive edge
tray_l = 140;
tray_x = grid_p + 9 - tray_fx; // drive left edge in the bay
tray_y = grid_p; // drive rear edge in the bay
hang_pad = lip_h + 0.3; // pads reach past the ribs to the floor
// ---- 2D outlines ----
module outer2d() {
offset(r = corner_r) offset(delta = -corner_r) square([S, S]);
}
module inset2d(k) {
offset(r = -k) outer2d();
}
module ring2d(a, b) {
difference() { inset2d(a); inset2d(b); }
}
// Rib grid under the floor.
module ribs2d() {
for (p = [grid_p : grid_p : S - grid_p / 2]) {
translate([p - rib_t / 2, 0]) square([rib_t, S]);
translate([0, p - rib_t / 2]) square([S, rib_t]);
}
}
// Blocks in the rear corners of the pocket: they stop the stack sliding rearward.
module stops2d() {
for (m = [0, 1]) translate([m ? S : 0, 0]) mirror([m, 0])
translate([skirt_t - 0.05, skirt_t - 0.05]) {
square([rib_in - skirt_t + 0.6, stop_end - skirt_t + 0.05]);
square([stop_end - skirt_t + 0.05, rib_in - skirt_t + 0.6]);
}
}
// Lip ring on top of a module, kept clear of the corners.
module lip2d(wt) {
difference() {
ring2d(wt - lip_t, wt);
for (m = [0, 1], n = [0, 1]) translate([m ? S : 0, n ? S : 0]) mirror([m, 0]) mirror([0, n])
square([stop_end + 0.3, stop_end + 0.3]);
}
}
// The four corners, as a transform: children are drawn in the rear left corner,
// with the side wall along x = 0 and the rear wall along y = 0.
module corners() {
for (m = [0, 1], n = [0, 1])
translate([m ? S : 0, n ? S : 0, 0]) mirror([m, 0, 0]) mirror([0, n, 0]) children();
}
// Honeycomb of pointy top hexagons centred on the origin, covering a w by w area.
module hex_field2d(w) {
p = hex_af + hex_w;
n = ceil(w / p / 2) + 1;
for (j = [-n : n], i = [-n : n])
translate([(i + (j % 2 == 0 ? 0 : 0.5)) * p, j * p * cos(30)])
rotate(90) circle(d = hex_af / cos(30), $fn = 6);
}
// ---- Shared shell ----
module body(h, ch) {
hull() {
linear_extrude(h - ch) outer2d();
translate([0, 0, h - 0.01]) linear_extrude(0.01) inset2d(ch);
}
}
module shell(h, wt, has_floor, has_lip, cap, ch) {
cav_z = has_floor ? z0 : -1;
cav_h = cap > 0 ? h - cap - cav_z : h + lip_h + 2;
union() {
difference() {
body(h, ch);
// cavity
translate([0, 0, cav_z]) linear_extrude(cav_h) inset2d(wt);
// pocket ring for the lip of the module below
translate([0, 0, -1]) linear_extrude(lip_h + 1) ring2d(skirt_t, rib_in);
// hollow under the floor, leaving the rib grid
if (has_floor)
translate([0, 0, -1]) linear_extrude(lip_h + 1)
difference() { inset2d(cell_in); ribs2d(); }
}
linear_extrude(lip_h) stops2d();
if (has_lip) {
translate([0, 0, h]) linear_extrude(lip_h - 0.3) lip2d(wt);
corner_bosses(h);
}
}
}
// A boss in each top corner. An M3 nut slides in from the side and is trapped under
// nut_top of material; the boss tapers at 45 degrees from the side wall so it prints
// without support.
module corner_bosses(h) {
corners() difference() {
hull() {
translate([wall - 0.01, wall - 0.01, h - boss_h]) cube([bs, bs, boss_h]);
translate([wall - 0.01, wall - 0.01, h - boss_h - bs]) cube([0.02, bs, 0.02]);
}
translate([bc, bc, h - boss_h - bs - 1]) cylinder(d = bolt_d, h = boss_h + bs + 2);
translate([bc - nut_af / 2, bc - nut_ac / 2, h - nut_top - nut_h]) cube([nut_af, 20, nut_h]);
}
}
// Bolt holes through the floor corners: down into the bosses of the module below,
// or into the feet under the base.
module floor_bolt_holes() {
corners() translate([bc, bc, -1]) cylinder(d = bolt_d, h = z0 + 2);
}
module floor_slots(ys, w) {
for (y = ys)
translate([wall + 10, y, lip_h]) cube([S - 2 * wall - 20, w, floor_t + 1]);
}
module side_vents(h, with_jack) {
for (m = [0, 1], y = [wall + 18 : vent_pitch : S - wall - 18])
if (!(with_jack && jack_d > 0 && jack_pos != "rear" && ((jack_pos == "right") == (m == 1)) && abs(y - jack_x) < jack_d / 2 + 5))
translate([m ? S - wall - 1 : -1, y, 8]) cube([wall + 2, vent_w, h - 16]);
}
// ---- Board module ----
module standoffs() {
for (hx = [hole_side_a, hole_side_b], hy = [hole_rear_a, hole_rear_b])
translate([wall + board_clear + hx, wall + board_clear + hy, z0 - 0.01])
difference() {
cylinder(d = 7, h = standoff_h + 0.01);
translate([0, 0, 1]) cylinder(d = standoff_hole, h = standoff_h + 1);
}
}
module board_module() {
difference() {
union() {
difference() {
shell(board_h, wall, true, true, 0, edge_ch);
floor_slots([wall + 12 : 9 : S - wall - 12], 3);
}
standoffs();
}
floor_bolt_holes();
// rear open above the board, the ports run edge to edge
translate([wall - 0.01, -1, rear_top])
cube([S - 2 * wall + 0.02, wall + 1.01, board_h + lip_h + 2]);
// grooves the rear shield slides down into
for (m = [0, 1])
translate([m ? S - wall - 0.01 : wall - groove_d, 1.0, rear_top])
cube([groove_d + 0.01, shield_t + 0.2, board_h + lip_h + 2]);
if (button_d > 0) {
translate([button_x, S - wall - 1, button_z]) rotate([-90, 0, 0])
cylinder(d = button_d + 0.3, h = wall + 2);
if (button_ring)
translate([button_x, S - 1, button_z]) rotate([-90, 0, 0])
cylinder(d = button_d + 12, h = 2);
}
if (jack_d > 0 && jack_pos != "rear")
translate([jack_pos == "right" ? S - wall - 1 : -1, jack_x, jack_z]) rotate([0, 90, 0])
cylinder(d = jack_d + 0.3, h = wall + 2);
if (vents) side_vents(board_h, true);
}
}
// ---- Bay module ----
// A floor grid of bosses on the 18 mm rib pitch, each with a self tapping M3 hole
// that goes through the floor. Anything with holes on the same pitch bolts down
// anywhere on the floor, or hangs under it.
module grid_bosses() {
for (i = [0 : 8], j = [1 : 8]) {
x = grid_p * i + 9;
y = grid_p * j + 9;
if (x < S - wall - 6 && y < S - wall - 6)
translate([x, y, z0 - 0.01]) difference() {
cylinder(d = 7, h = grid_boss_h + 0.01);
translate([0, 0, -z0]) cylinder(d = 2.6, h = z0 + grid_boss_h + 2);
}
}
}
module bay_module() {
difference() {
union() {
difference() {
shell(bay_h, wall, true, true, 0, edge_ch);
// two vent slots per grid cell, between the bosses and the ribs
floor_slots([32 : grid_p : S - wall - 8], 2);
floor_slots([38 : grid_p : S - wall - 8], 2);
}
grid_bosses();
}
floor_bolt_holes();
// cable pass-through behind the drive
translate([S / 2 - 55, wall - 0.01, -1]) cube([110, tray_y - wall, z0 + 2]);
if (vents) side_vents(bay_h, false);
}
}
// ---- Drive tray ----
// A frame the 3.5" drive screws onto from below through its bottom holes (SFF-8301),
// with flanges either side that bolt to the bay grid. Drawn flat, drive rear edge at
// y = 0, drive left edge at x = 0. With pads it hangs under a bay floor instead: the
// pads reach up between the ribs, the drive hangs upside down below the tray.
module tray_35(pads = 0) {
x0 = tray_fx - 6;
tw = tray_span + 12;
difference() {
union() {
translate([x0, 0, 0]) cube([tw, tray_l, tray_t]);
if (pads > 0)
for (x = [tray_fx, tray_fx + tray_span], y = [9 : grid_p : tray_l - 5])
translate([x, y, tray_t - 0.01]) cylinder(d = 7, h = pads + 0.01);
}
// open centre, air reaches the drive board
translate([12, 12, -1]) cube([hdd_w - 24, tray_l - 24, tray_t + 2]);
// grid holes in the flanges
for (x = [tray_fx, tray_fx + tray_span], y = [9 : grid_p : tray_l - 5])
translate([x, y, -1]) cylinder(d = bolt_d, h = tray_t + pads + 2);
// drive screw slots: the required pair and both optional pairs
for (x = [3.18, 3.18 + 95.25], y = [41.28, 76.2, 101.6])
hull() for (dy = [-1.2, 1.2])
translate([x, y + dy, -1]) cylinder(d = 3.7, h = tray_t + 2);
}
}
// ---- Foot ----
// Plugs into a corner cell of the rib grid and bolts through the floor hole.
// Drawn in the rear left corner, pad down.
module foot() {
difference() {
union() {
translate([0.5, 0.5, 0]) cube([17, 17, foot_h]);
translate([cell_in + 0.3, cell_in + 0.3, foot_h - 0.01]) cube([plug, plug, lip_h - 0.3]);
}
translate([bc, bc, -1]) cylinder(d = bolt_d, h = foot_h + lip_h + 2);
translate([bc - nut_af / 2, bc - nut_ac / 2, foot_h - nut_top - nut_h]) cube([nut_af, 20, nut_h]);
}
}
// ---- Lid ----
// One honeycomb over the whole top: raised tiles with a recessed wall network, and
// the same cells cut through over the fan. The fan hangs from four bosses under the
// plate and is screwed from the inside, so the top carries no screw heads.
module fan_bosses() {
for (sx = [-1, 1], sy = [-1, 1])
translate([S / 2 + sx * fan_hole / 2, S / 2 + sy * fan_hole / 2, 0]) children();
}
module lid() {
difference() {
union() {
shell(lid_h, lid_wall, false, false, top_t, lid_ch);
// full height columns in the corners for the long lid bolts
corners() translate([rib_in, rib_in, 0]) cube([wall + bs - rib_in, wall + bs - rib_in, lid_h - 0.5]);
if (fan_size > 0)
fan_bosses() translate([0, 0, lid_h - top_t - fan_boss_h]) cylinder(d = 7, h = fan_boss_h + 0.01);
}
corners() {
translate([bc, bc, -1]) cylinder(d = bolt_d, h = lid_h + 2);
translate([bc, bc, lid_h - 7]) cylinder(d = 6.5, h = 8);
}
// the recessed wall network of the honeycomb, inside the chamfer border
if (lid_relief > 0)
translate([0, 0, lid_h - lid_relief]) linear_extrude(lid_relief + 1)
offset(r = 0.3) offset(r = -0.3)
difference() {
inset2d(lid_ch + 2);
translate([S / 2, S / 2]) hex_field2d(S);
}
if (fan_size > 0) {
// open cells over the fan
translate([S / 2, S / 2, lid_h - top_t - 1]) linear_extrude(top_t + 2)
intersection() { circle(d = fan_size - 4); hex_field2d(fan_size); }
// self tapping holes for the fan screws
fan_bosses() translate([0, 0, lid_h - top_t - fan_boss_h - 1]) cylinder(d = 2.6, h = fan_boss_h + 2);
}
}
}
// ---- Rear shield ----
// Modelled flat: x along the case width, y up the case, z inward.
module rear_shield() {
sw = S - 2 * wall + 2 * groove_d - 0.3;
sh = board_h - rear_top;
bx = groove_d + board_clear - 0.15;
lip_in = stop_len + groove_d + 0.15;
difference() {
union() {
cube([sw, sh, shield_t]);
// the rear lip of the board module lives on the shield
translate([lip_in, sh - 0.01, 0.3])
cube([sw - 2 * lip_in, lip_h - 0.3 + 0.01, shield_t - 0.3]);
}
translate([bx + io_x, -1, -1]) cube([io_w, io_h + 1, shield_t + 2]);
if (jack_d > 0 && jack_pos == "rear")
translate([bx + jack_x, jack_z - rear_top, -1]) cylinder(d = jack_d + 0.3, h = shield_t + 2);
}
}
// ---- Ghost hardware ----
module ghost_board() {
color("DarkGreen", 0.5)
translate([wall + board_clear, wall + board_clear, board_z]) cube([board, board, pcb_t]);
}
module ghost_hdd(z) {
color("Silver", 0.5)
translate([tray_x, tray_y, z]) cube([hdd_w, hdd_l, hdd_h]);
}
// ---- Layout ----
module assembly() {
color(color_case) board_module();
color(color_case) corners() translate([0, 0, -foot_h - explode / 2]) foot();
color(color_case)
translate([wall - groove_d + 0.15, 1.1 + shield_t, rear_top]) rotate([90, 0, 0]) rear_shield();
if (show_hardware) ghost_board();
if (bay_modules > 0)
for (i = [0 : bay_modules - 1])
translate([0, 0, board_h + i * bay_h + (i + 1) * explode]) {
color(color_case) bay_module();
color(color_case) translate([tray_x, tray_y, z0 + grid_boss_h]) tray_35();
if (show_hardware) ghost_hdd(z0 + grid_boss_h + tray_t);
if (i == 0 && hang_hdd) {
color(color_case) translate([tray_x, tray_y, -0.3 - tray_t]) tray_35(hang_pad);
if (show_hardware) ghost_hdd(-0.3 - tray_t - hdd_h);
}
}
translate([0, 0, board_h + bay_modules * bay_h + (bay_modules + 1) * explode])
color(color_case) lid();
}
if (part == "board_module") color(color_case) board_module();
else if (part == "bay_module") color(color_case) bay_module();
else if (part == "tray_35") color(color_case) translate([-tray_fx + 6, 0, 0]) tray_35();
else if (part == "tray_35_hanging") color(color_case) translate([-tray_fx + 6, 0, 0]) tray_35(hang_pad);
else if (part == "lid") color(color_case) translate([0, S, lid_h]) rotate([180, 0, 0]) lid();
else if (part == "rear_shield") color(color_case) rear_shield();
else if (part == "foot") color(color_case) foot();
else assembly();
Comments
Context, not a score. Comments never move a model up or down the results.No comments yet
Printed it? A note about your material and the clearance you landed on saves the next person a failed print.
