added sbccb_accessory_tool.scad for user access to the accessory library, fixed rack tab hole spacing, added library parts rack_rail and rack_stand for 1u-4u cases

This commit is contained in:
Edward Kisiel
2025-05-29 16:50:35 -04:00
parent 12c99bee77
commit 054dbb9edc
7 changed files with 245 additions and 16 deletions

View File

@@ -90,7 +90,7 @@ Both standard motherboard adapters and cases can be generated with SBC Case Buil
### Rack Mount Case Adjustments Tab
Both 1U and 2U, 10" and 19", rack cases are configured in this tab. The first entry *rack width* selects if 10" or 19" rack cases are being created. The *rack size* sets wether 1U or 2U. The remaining tab is divided into six groups of settings each representing a virtual bay. Each bay group specifies the SBC thru the pickbox *Rack Bay1* respectively. With *rack bay1 xyz loc* and *rack bay1 rotation determining the position and z-axis rotation. The type of bay is set in the *rack bay1 face* pickbox followed by two checkboxes for the internal dividing wall, rear fan and a bay conduit selection pickbox.
Both 1U and 2U, 10" and 19", rack cases are configured in this tab. The first entry *rack width* selects if 10" or 19" rack cases are being created. The *rack size* sets wether 1U or 2U. There is a 2mm wall in front of every removable bay. *removable bay height* allows the tray height to be reduced to form an opening which allows for tray removal and venting when installed with other rack cases above. The remaining tab is divided into six groups of settings each representing a virtual bay. Each bay group specifies the SBC thru the pickbox *Rack Bay1* respectively. With *rack bay1 xyz loc* and *rack bay1 rotation determining the position and z-axis rotation. The type of bay is set in the *rack bay1 face* pickbox followed by two checkboxes for the internal dividing wall, rear fan and a bay conduit selection pickbox.
### 3D Case Adjustments Tab
@@ -796,7 +796,7 @@ DESCRIPTION: creates nut holder of various styles.
size[0] = top diameter or x size in mm
size[1] = bottom diameter or y size in mm
size[2] = holder height in mm
data[0] = "m2", "m2.5", "m3", "m4"
data[0] = "m2", "m2.5", "m3", "m4", "m3-insert"
data[1] = "default", "sloped", "trap"
mask[0] = true
mask[1] = length

View File

@@ -29,7 +29,7 @@
USAGE: nut_holder(nut, style, dia_x, dia_y, height, mask)
nut = "m2", "m2.5", "m3", "m4"
nut = "m2", "m2.5", "m3", "m4", "m3-insert"
style = "default", "sloped", "trap"
dia_x = top diameter or x size in mm
dia_y = bottom diameter or y size in mm
@@ -87,6 +87,10 @@ module nut_holder(nut, style, dia_x, dia_y, height, mask) {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height, $fn=6);
}
if(nut == "m3-insert") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 0]) cylinder(d=4.2, h=5.1);
}
if(nut == "m4") {
translate([0, 0, -1]) cylinder(d=nuts[3][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[3][1]*2/sqrt(3), h=height, $fn=6);
@@ -106,7 +110,11 @@ module nut_holder(nut, style, dia_x, dia_y, height, mask) {
}
if(nut == "m3") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 2]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height, $fn=6);
translate([0, 0, 0]) cylinder(d=nuts[2][1]*2/sqrt(3), h=height+5, $fn=6);
}
if(nut == "m3-insert") {
translate([0, 0, -1]) cylinder(d=nuts[2][0]+.5, h=height+2);
translate([0, 0, 0]) cylinder(d=4.2, h=5.1);
}
if(nut == "m4") {
translate([0, 0, -1]) cylinder(d=nuts[3][0]+.5, h=height+2);

View File

@@ -16,6 +16,8 @@
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
rack_end_bracket(side, size, thick)
rack_rail(style, rack_1u, hole_dia, thick)
rack_stand(rack_1u)
*/
@@ -36,7 +38,9 @@
module rack_end_bracket(side, size, thick) {
u1 = 44.45;
depth = size == "1u" ? 44.45 : size == "1u+" ? 59.26 : size == "1u++" ? 74.07 : size == "2u" ? 2*44.45 : size == "3u" ? 3*44.45 : 4*44.45;
mask = size == "1u" ? 44.45 : size == "1u+" ? 88.9 : size == "1u++" ? 88.9 : size == "2u" ? 2*44.45 : size == "3u" ? 3*44.45 : 4*44.45;
c_fillet = 2;
hole = 3.2;
rack_hole = 6;
@@ -50,7 +54,7 @@ module rack_end_bracket(side, size, thick) {
$fn=90;
if(side == "left") {
translate([thick,-thick,depth]) rotate([270,0,0])
translate([thick,0,0]) rotate([90,0,0])
difference() {
union() {
translate([(-tab_width/2),(depth/2),thick/2])
@@ -60,8 +64,11 @@ module rack_end_bracket(side, size, thick) {
cube_fillet_inside([b_width,b_depth,b_height],
vertical=[0,0,0,0],top=[c_fillet,0,c_fillet,0],bottom=[0,0,0,0], $fn=90);
}
for (c=[7.5:15:depth]) {
translate([(3-thick)-9-(15.875-9)/2,c,-adjust]) slot(rack_hole,3,thick+(adjust*2));
for(i=[0:u1:mask-u1]) {
for(c=[6.35:15.875:44.45]) {
translate([(3-thick)-9-(15.875-9)/2,c+i,-adjust])
slot(rack_hole,3,thick+(adjust*2));
}
}
}
}
@@ -76,9 +83,123 @@ module rack_end_bracket(side, size, thick) {
cube_fillet_inside([b_width,b_depth,b_height],
vertical=[0,0,0,0],top=[c_fillet,0,c_fillet,0],bottom=[0,0,0,0], $fn=90);
}
for (c=[7.5:15:depth]) {
translate([(3-thick)-9-(15.875-9)/2,c,-adjust]) slot(rack_hole,3,thick+(adjust*2));
for(i=[0:u1:mask-u1]) {
for(c=[6.35:15.875:44.45]) {
translate([(3-thick)-9-(15.875-9)/2,c+i,-adjust]) slot(rack_hole,3,thick+(adjust*2));
}
}
}
}
}
/*
NAME: rack_rail
DESCRIPTION: creates rack rail lengths
TODO: none
USAGE: rack_rail(style, rack_1u, hole_dia, thick)
style = "none", "nut", "insert"
rack_1u = number of 1u
hole_dia = hole size to create
thick = thickness of bracket
*/
module rack_rail(style, rack_1u, hole_dia, thick) {
1u = 44.45;
mount_rail = 15.875;
1u_hole_offset = 6.35;
1u_hole_spacing = 15.875;
height = rack_1u * 1u;
difference() {
union() {
cube([mount_rail, thick, height]);
if(style == "nut" || style == "insert") {
fastner = style == "insert" ? "m3-insert" : "m3";
for(i=[0:rack_1u-1]) {
translate([mount_rail/2, adj, i*1u]) {
translate([0,0,1u_hole_offset]) rotate([90,0,0])
nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
translate([0,0,1u_hole_offset+1u_hole_spacing])
rotate([90,0,0]) nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
translate([0,0,1u_hole_offset+2*1u_hole_spacing])
rotate([90,0,0]) nut_holder(fastner, "sloped", 7, mount_rail-1, 3, [false,10,2,"default"]);
}
}
}
}
for(i=[0:rack_1u-1]) {
translate([mount_rail/2, -1, i*1u]) {
translate([0,thick+2,1u_hole_offset]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
translate([0,thick+2,1u_hole_offset+1u_hole_spacing]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
translate([0,thick+2,1u_hole_offset+2*1u_hole_spacing]) rotate([90,0,0]) cylinder(d = hole_dia, h=thick+2);
}
}
translate([-1,-1,height]) cube([mount_rail+2,thick+2,10]);
}
}
/*
NAME: rack_stand
DESCRIPTION: creates rack stand of 1u hieght
TODO: none
USAGE: rack_stand(rack_1u)
rack_1u = number of 1u
*/
module rack_stand(rack_1u) {
1u = 44.45;
mount_rail = 15.875;
thick = 5;
height = rack_1u * 1u;
height_offset = 25.4/2;
hole_dia = 3.2;
c_fillet = 9;
rail_offset = 87.5;
foot_length = 175;
foot_thick = thick;
$fn=180;
// vertical rack rails
translate([0, 0, height_offset-adj]) rack_rail(rack_fasteners, rack_1u, hole_dia, thick);
// bottom feet
translate([mount_rail/2, -rail_offset/2, foot_thick-2]) cube_fillet_inside([mount_rail, foot_length, foot_thick],
vertical=[0,0,0,0], top=[c_fillet,0,c_fillet,0], bottom=[0,0,0,0], $fn=90);
// bottom connection piece
translate([0, 0, 0]) cube([mount_rail, thick, height_offset]);
// top extension piece
ext_len = rack_1u == 4 ? thick : rack_1u == 3 ? thick : thick;
translate([0, 0, height+height_offset-adj]) cube([mount_rail, thick, ext_len]);
// support arc
if(rack_1u > 0) {
ext_adj = rack_1u == 4 ? 4.5*thick : rack_1u == 3 ? 3.5*thick : 2.5*thick;
difference() {
translate([0,(height/2)-5*thick,ext_adj]) rotate([0,90,0]) {
difference() {
translate([0,0,0]) cylinder(d=(2*height)+(3*thick), h=mount_rail);
translate([0,0,-adj]) cylinder(d=(2*height)+thick, h=mount_rail+(2*adj));
}
}
// top trim
translate([-1, thick, height+height_offset-5]) cube([mount_rail+2, 300, 40]);
// front trim
translate([-1, 42.75, -175]) cube([mount_rail+2, 300, 400]);
translate([-1, thick, foot_thick]) cube([mount_rail+2, 300, 400]);
// bottom trim
translate([-1, -150, -174.5]) cube([mount_rail+2, 300, 175]);
}
}
}

View File

@@ -1004,7 +1004,7 @@ module bay_tray(depth, bay) {
union() {
slab([reminsert-wallthick-gap-2,depth-.5,1],.5);
translate([0, 1.5, 0]) rotate([90,0,0])
slab([reminsert-wallthick-gap-2,bay_height-3,1.5],.5);
slab([reminsert-wallthick-gap-2,bay_height-3+removable_bay_height,1.5],.5);
}
// case floor panel clamp holes
translate([baysize-2.5,(depth/2)-gap-wallthick+3,-adj])

View File

@@ -7479,7 +7479,7 @@
"bottom_standoff_insert_height": "5.1",
"bottom_standoff_pillar": "hex",
"bottom_standoff_reverse": "false",
"bottom_standoff_size": "m3",
"bottom_standoff_size": "m3_tap",
"bottom_standoff_support_height": "4",
"bottom_standoff_support_size": "10",
"bottom_standoff_type": "countersunk",
@@ -12760,7 +12760,7 @@
"ext_top_standoffs": "false",
"fan_size": "0",
"flat_blank_section": "false",
"floorthick": "2",
"floorthick": "3",
"front_cover_pattern": "solid",
"gap": "1",
"gpio_opening": "none",

View File

@@ -78,14 +78,15 @@ rear_io_shield = false;
rack_width = 19; //[10,19]
// size of rack mount cases 1U or 2U //
rack_size = "1u"; //["1u","1u+","1u++","2u"]
// enable rack io plate opening for sbc
removable_bay_height = 0; // [-4 : .5 : 0]
// bay sbc device
Rack_Bay1 = "none"; // ["none", "c1+", "c2", "c4", "hc4", "c5", "xu4", "xu4q", "mc1", "hc1", "n1", "n2", "n2+", "n2l", "n2lq", "m1", "m1s", "m2", "h2", "h2+", "h3", "h3+", "h4", "h4+", "h4_ultra", "show2", "rpipico", "rpipicow", "rpicm4+ioboard", "rpicm1", "rpicm3", "rpicm3l", "rpicm3+", "rpicm4s", "rpicm4", "rpicm4l", "rpizero", "rpizerow", "rpizero2w", "rpi1a+", "rpi1b+", "rpi2b", "rpi3a+", "rpi3b", "rpi3b+", "rpi4b", "rpi5", "a64", "a64lts", "rock64", "rockpro64", "quartz64a", "quartz64b", "h64b", "star64", "soedge_a-baseboard", "soedge_rk1808", "rock4a", "rock4b", "rock4a+", "rock4b+", "rock4c", "rock4c+", "rock5b-v1.3", "rock5b", "rock5bq", "rock5b+", "nio12l", "vim1", "vim2", "vim3", "vim3l", "vim4", "tinkerboard", "tinkerboard-s", "tinkerboard-2", "tinkerboard-2s", "tinkerboard-r2", "tinkerboard-r2s", "opizero", "opizero2", "opir1plus_lts", "opir1", "opi5", "opi5max", "jetsonnano", "lepotato", "sweetpotato", "tritium-h2+", "tritium-h3", "tritium-h5", "solitude", "alta", "atomicpi", "visionfive2", "visionfive2q", "bpif3", "milk-v_duos", "licheerv+dock", "rak19007", "cnano-avr128da48", "nodemcu-32s", "cs-solarmeter", "feather-m0_express", "feather-m0_wifi", "feather-m4_express"]
rack_bay1_xyz_loc = [0,0,0]; // [0:.5:450]
rack_bay1_rotation = 0; // [0:90:270]
rack_bay1_face = "fixed"; //["open","fixed","removable","vent"]
rack_bay1_face = "fixed"; // ["open","fixed","removable","vent"]
rack_bay1_wall = false; // [true,false]
rack_bay1_rear_fan = false; //[true,false]
rack_bay1_rear_conduit = "none"; //["none","conduit","grommet","grommets-vertical"]
rack_bay1_rear_fan = false; // [true,false]
rack_bay1_rear_conduit = "none"; // ["none","conduit","grommet","grommets-vertical"]
Rack_Bay2 = "none"; // ["none", "c1+", "c2", "c4", "hc4", "c5", "xu4", "xu4q", "mc1", "hc1", "n1", "n2", "n2+", "n2l", "n2lq", "m1", "m1s", "m2", "h2", "h2+", "h3", "h3+", "h4", "h4+", "h4_ultra", "show2", "rpipico", "rpipicow", "rpicm4+ioboard", "rpicm1", "rpicm3", "rpicm3l", "rpicm3+", "rpicm4s", "rpicm4", "rpicm4l", "rpizero", "rpizerow", "rpizero2w", "rpi1a+", "rpi1b+", "rpi2b", "rpi3a+", "rpi3b", "rpi3b+", "rpi4b", "rpi5", "a64", "a64lts", "rock64", "rockpro64", "quartz64a", "quartz64b", "h64b", "star64", "soedge_a-baseboard", "soedge_rk1808", "rock4a", "rock4b", "rock4a+", "rock4b+", "rock4c", "rock4c+", "rock5b-v1.3", "rock5b", "rock5bq", "rock5b+", "nio12l", "vim1", "vim2", "vim3", "vim3l", "vim4", "tinkerboard", "tinkerboard-s", "tinkerboard-2", "tinkerboard-2s", "tinkerboard-r2", "tinkerboard-r2s", "opizero", "opizero2", "opir1plus_lts", "opir1", "opi5", "opi5max", "jetsonnano", "lepotato", "sweetpotato", "tritium-h2+", "tritium-h3", "tritium-h5", "solitude", "alta", "atomicpi", "visionfive2", "visionfive2q", "bpif3", "milk-v_duos", "licheerv+dock", "rak19007", "cnano-avr128da48", "nodemcu-32s", "cs-solarmeter", "feather-m0_express", "feather-m0_wifi", "feather-m4_express"]
rack_bay2_xyz_loc = [0,0,0]; // [0:.5:450]

99
sbccb_accessory_tool.scad Normal file
View File

@@ -0,0 +1,99 @@
/*
SBC Case Builder Accessory Tool Copyright 2025 Edward A. Kisiel hominoid@cablemi.com
This file is part of SBC Case Builder https://github.com/hominoids/SBC_Case_Builder
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Code released under GPLv3: http://www.gnu.org/licenses/gpl.html
see https://github.com/hominoids/SBC_Case_Builder
*/
include <./sbc_case_builder_library.scad>;
/* [View] */
// viewing mode "model", "platter"
view = "model"; // [model, platter]
individual_part = "bottom"; // [top, bottom, right, left, front, rear, io_shield, accessories]
// section individual parts for panel cases
section_part = false; // [true,false]
accessory = "grommet"; // ["fan cover", "grommet", "hd25 holder", "1u rack stand"]
/* [Fan Cover] */
fan_style = "fan_hex"; // ["fan_open", "fan_1", "fan_2", "fan_hex"]
fan_size = 40; // [25, 30, 40, 50, 60, 80, 92, 120]
fan_cover_thickness = 2; // [2 : .25 : 5]
/* [Grommet] */
grommet_style = "sleeve"; // ["sleeve"]
grommet_od = 10; // [6 : .25 : 20]
grommet_id = 6; // [2 : .25 : 20]
installation_wall_thickness = 2; // [2 : .25 : 5]
/* [2.5" HD Holder] */
holder_length = 110; // [110, 145]
holder_width = 101.6; // [101.6 : .1 : 150]
/* [1U Rack Stand] */
rack_width = 19; // [10, 19]
rack_1u = 4; // [1 : 4]
rack_depth = 150; // [25 : 200]
rack_fasteners = "nut"; // ["none", "nut", "insert"]
/* [Hidden] */
mask = [true, 10, 2, "default"];
nmask = [false, 10, 2, "default"];
adj = .01;
$fn = 90;
// model view
if (view == "model") {
if(accessory == "fan cover") {
fan_cover(fan_size, fan_cover_thickness, fan_style);
}
if(accessory == "grommet") {
grommet("front", grommet_style, grommet_od, grommet_id, installation_wall_thickness, true, nmask);
}
if(accessory == "hd25 holder") {
hd35_25holder(holder_length, holder_width);
}
if(accessory == "1u rack stand") {
rack_stand(rack_1u);
}
}
// platter view
if (view == "platter") {
if(accessory == "fan cover") {
fan_cover(fan_size, fan_cover_thickness, fan_style);
}
if(accessory == "grommet" && grommet_style == "sleeve") {
translate([0,0,0]) rotate([270,0,0]) difference() {
grommet("bottom", grommet_style, grommet_od, grommet_id, installation_wall_thickness, false, nmask);
translate([-grommet_od,-.125,-3]) cube([20,10,20]);
}
translate([0,20,0]) rotate([270,0,0]) difference() {
grommet("bottom", grommet_style, grommet_od, grommet_id, installation_wall_thickness, false, nmask);
translate([-grommet_od,-.125,-3]) cube([20,10,20]);
}
translate([0,-20,0])
grommet_clip(grommet_style, grommet_od, grommet_id, installation_wall_thickness);
}
if(accessory == "hd25 holder") {
hd35_25holder(holder_length, holder_width);
}
if(accessory == "1u rack stand") {
rotate([0,270,0]) rack_stand(rack_1u);
}
}