openscad/project_box.scad

216 lines
6.8 KiB
OpenSCAD
Raw Normal View History

2022-12-06 15:58:59 +00:00
/* Project box
2022-12-06 21:19:45 +00:00
A parametric box for electronics projects using perforated circuit boards. The
board is held above the bottom of the box by four corner supports, and snaps
into place to hold it snugly while allowing easy removal.
2022-12-07 15:40:32 +00:00
Shapes provided as children will be used as cutouts, translated to the origin
point of the top of the circuit board. Modules are provided for cutting out
two-dimensional shapes from each wall face as well as the lid.
2022-12-06 15:58:59 +00:00
*/
$fn=50;
2022-12-06 21:19:45 +00:00
mode = "case"; // ["case", "lid", "all"]
2022-12-06 15:58:59 +00:00
board_x = 50;
board_y = 70;
2022-12-06 20:10:11 +00:00
board_thickness = 1; // [1:10]
clearance_above = 20; // [5:50]
clearance_below = 10; // [5:50]
2022-12-06 15:58:59 +00:00
fit_tolerance = 0.5;
2022-12-06 20:10:11 +00:00
corner_radius=3; // [1:10]
support_radius=5; // [1:10]
wall_width=3; // [3:10]
2022-12-06 15:58:59 +00:00
module _rounded_box(box, r) {
2022-12-06 15:58:59 +00:00
hull() {
translate([0 + r,0 + r,0])
cylinder(h=box.z,r=r);
translate([box.x - r,0 + r,0])
cylinder(h=box.z, r=r);
translate([box.x - r,box.y - r,0])
cylinder(h=box.z, r=r);
translate([0 + r,box.y - r,0])
cylinder(h=box.z, r=r);
2022-12-06 15:58:59 +00:00
}
}
module corner_post(h, r) {
intersection() {
translate([-0.001,-0.001,-0.001])
cube([r*1.1, r*1.1, h*1.2]);
cylinder(h=h, r=r);
}
}
module lid_base(dimensions, slot_depth=1.5) {
2022-12-06 20:10:11 +00:00
polyhedron([// bottom face
[0, 0, 0],
[dimensions.x, 0, 0],
[dimensions.x, dimensions.y, 0],
[0, dimensions.y, 0],
2022-12-06 20:10:11 +00:00
// top face
[slot_depth, 0, dimensions.z],
[dimensions.x - slot_depth, 0, dimensions.z],
[dimensions.x - slot_depth, dimensions.y, dimensions.z],
[slot_depth, dimensions.y, dimensions.z]],
2022-12-06 20:10:11 +00:00
[[0,1,2,3],
[4,5,1,0],
[7,6,5,4],
[5,6,2,1],
[6,7,3,2],
[7,4,0,3]]);
2022-12-06 19:59:31 +00:00
}
module lid(dimensions, slot_depth=1.5, wall_width=3, fit_tolerance=0.5) {
indent_width = dimensions.x / 4;
2022-12-06 21:19:45 +00:00
difference() {
union() {
lid_base([dimensions.x, dimensions.y, dimensions.z], slot_depth);
2022-12-06 23:34:30 +00:00
// locking tab
translate([dimensions.x / 2 - indent_width / 2 - fit_tolerance,
dimensions.y - wall_width - fit_tolerance,
0])
2022-12-06 21:19:45 +00:00
rotate([0, 90, 0])
cylinder(h=dimensions.x / 4, r=2*fit_tolerance);
2022-12-06 21:19:45 +00:00
}
2022-12-06 23:34:30 +00:00
// pull handle
translate([dimensions.x / 2 - indent_width / 2 - fit_tolerance,
dimensions.y - wall_width + fit_tolerance + 0.001,
-0.001]) {
cube([indent_width,wall_width - 2 * fit_tolerance,0.6 * dimensions.z]);
cube([indent_width,2 + wall_width - 2 * fit_tolerance,0.3 * dimensions.z]);
}
2022-12-06 21:19:45 +00:00
}
}
module project_box(box,
2022-12-06 15:58:59 +00:00
below=10,
board_thickness=1,
fit_tolerance=0.5,
corner_radius=3,
support_radius=5,
2022-12-06 21:19:45 +00:00
wall_width=3,
mode="case") {
width=box.x + (fit_tolerance * 2);
depth=box.y + (fit_tolerance * 2);
2022-12-06 19:59:31 +00:00
lid_width = width + wall_width; // Extends halfway into each side wall
lid_depth = depth + wall_width; // Extends out of one wall
lid_height = wall_width; // Replaces most of the top wall
height=board_thickness + box.z + below + (fit_tolerance * 2) + lid_height;
2022-12-06 15:58:59 +00:00
2022-12-06 21:19:45 +00:00
// case
if ((mode == "case") || (mode == "all")) {
difference() {
2022-12-07 15:40:32 +00:00
union() {
// hollow shell
difference() {
_rounded_box([width + (wall_width * 2),
depth + (wall_width * 2),
height + (wall_width * 2)],
2022-12-07 15:40:32 +00:00
r=corner_radius);
translate([wall_width,wall_width,wall_width])
cube([width, depth, height + (wall_width * 2)]);
// lid slot
translate([wall_width / 2, wall_width, height + wall_width + 0.001]) {
lid_base([lid_width, lid_depth, lid_height]);
2022-12-07 15:40:32 +00:00
}
}
// supports
translate([wall_width,wall_width,wall_width]) {
translate([0,0,0])
corner_post(h=below, r=support_radius);
translate([width,0,0])
rotate([0,0,90])
corner_post(h=below, r=support_radius);
translate([0,depth,0])
rotate([0,0,270])
corner_post(h=below, r=support_radius);
translate([width,depth,0])
rotate([0,0,180])
corner_post(h=below, r=support_radius);
}
// locking nubs
translate([wall_width,wall_width,wall_width]) {
nub_size = fit_tolerance * 2;
nub_width = box.y / 4;
2022-12-07 15:40:32 +00:00
nub_height = below + board_thickness + (nub_size/2) + (fit_tolerance*2);
translate([0,box.y / 2 - nub_width / 2,nub_height])
2022-12-07 15:40:32 +00:00
rotate([270,0,0])
cylinder(h=nub_width, r=nub_size/2);
translate([width,box.y / 2 - nub_width / 2,nub_height])
2022-12-07 15:40:32 +00:00
rotate([270,0,0])
cylinder(h=nub_width, r=nub_size/2);
}
if (mode == "all") {
// lid
translate([wall_width / 2 + fit_tolerance,
wall_width + fit_tolerance,
height + wall_width + fit_tolerance]) {
lid([lid_width - (fit_tolerance * 2),
lid_depth - (fit_tolerance * 2),
lid_height - (fit_tolerance * 2)]);
2022-12-07 15:40:32 +00:00
}
}
2022-12-06 21:19:45 +00:00
}
2022-12-07 15:40:32 +00:00
// cutouts
translate([wall_width + fit_tolerance, wall_width + fit_tolerance, wall_width + below])
children();
2022-12-06 21:19:45 +00:00
}
2022-12-07 15:40:32 +00:00
} else if (mode == "lid") {
// Flip the lid and translate it into place for printing
translate([lid_width - (fit_tolerance * 2),0,lid_height - (fit_tolerance * 2)]) {
rotate([0, 180, 0]) {
difference() {
lid([lid_width - (fit_tolerance * 2),
lid_depth - (fit_tolerance * 2),
lid_height - (fit_tolerance * 2)]);
2022-12-07 15:40:32 +00:00
translate([wall_width + fit_tolerance, wall_width + fit_tolerance, -0.001])
children();
}
}
2022-12-06 21:19:45 +00:00
}
2022-12-07 15:40:32 +00:00
}
}
2022-12-06 15:58:59 +00:00
module cutout_front(box) {
2022-12-07 15:40:32 +00:00
rotate([90, 0, 0])
linear_extrude(height=box.y * 2)
2022-12-07 15:40:32 +00:00
children(0);
}
2022-12-06 21:19:45 +00:00
module cutout_back(box) {
translate([box.x,0,0])
2022-12-07 15:40:32 +00:00
rotate([90, 0, 180])
linear_extrude(height=box.y * 2)
2022-12-07 15:40:32 +00:00
children(0);
}
module cutout_right(box) {
2022-12-07 15:40:32 +00:00
rotate([90, 0, 90])
linear_extrude(height=box.x * 2)
2022-12-07 15:40:32 +00:00
children(0);
}
module cutout_left(box) {
translate([box.x, box.y, 0])
2022-12-07 15:40:32 +00:00
rotate([90, 0, 270])
linear_extrude(height=box.x * 2)
2022-12-07 15:40:32 +00:00
children(0);
}
module cutout_top(box) {
linear_extrude(height=box.y * 2)
2022-12-07 15:40:32 +00:00
children(0);
2022-12-06 15:58:59 +00:00
}
project_box([board_x, board_y, clearance_above],
2022-12-06 15:58:59 +00:00
below=clearance_below,
board_thickness=board_thickness,
fit_tolerance=fit_tolerance,
corner_radius=corner_radius,
support_radius=support_radius,
2022-12-06 21:19:45 +00:00
wall_width=wall_width,
mode=mode);