====== Prototype Enclosures with FreeCAD & OpenSCAD ======
Introduction to 3D Modelling in FreeCAD and OpenSCAD for designing 3D printed mountings for prototype electronics.
* [[https://odysee.com/@OpenTechLab:f/otl-008-enclosures:7|odysee]]
* [[https://www.youtube.com/watch?v=38Z7E8OcVd8|YouTube]]
* [[https://peertube.social/videos/watch/08201efd-5f9b-4b0b-b5cc-80cb3b783023|peertube.social]]
* [[http://archive.is/qBhHs|Aluminium Enclosure]] @ $5.88
===== FreeCAD =====
* [[https://www.freecadweb.org/|FreeCAD Site]]
* [[https://www.openhub.net/p/freecad|FreeCAD on Open Hub]]
===== OpenSCAD =====
* [[http://www.openscad.org/|OpenSCAD Website]]
* [[https://www.openhub.net/p/openscad|OpenSCAD on Open Hub]]
* [[http://www.openscad.org/cheatsheet/|OpenSCAD Cheat Sheet]]
* [[https://github.com/sirtaj/vim-openscad|vim OpenSCAD Syntax Highlighting Plugin]]
==== Examples ====
=== 5-sided Widget ===
''example.scad''
width = 120;
height = 60;
thickness = 40;
hole_dia = 24;
difference() {
linear_extrude(thickness) difference() {
polygon([
[-width/2, -height/2],
[-width/2, height/2],
[width/2 - height/2, height/2],
[width/2, 0],
[width/2, -height/2]
]);
translate([-width/4, 0]) circle(d=hole_dia);
translate([width/4, 0]) circle(d=hole_dia);
}
translate([0, -height/2, thickness/2]) rotate([90, 0, -45])
cylinder(h=1000, d=hole_dia, center=true);
}
=== PCB Frame ===
''frame.scad''
holeSpacingH = 90.40;
holeSpacingV = 95;
dioHoleOffsetH = 35;
frameEdgePaddingV = 15.0;
frameEdgePaddingR = 16.0;
frameSize = [holeSpacingH + dioHoleOffsetH + frameEdgePaddingR, holeSpacingV + frameEdgePaddingV*2];
frameWidth = 8;
frameThickness = 2;
frameReinforcementHeight = 4;
frameReinforcementThickness = 1.5;
mountLength = 18;
mountDia = 7;
mountHoleDia = 3.5;
mountColumns = [0, holeSpacingH, holeSpacingH + dioHoleOffsetH];
pcbThickness = 1.6;
footHeight = mountLength * 2 + pcbThickness;
footThickness = frameReinforcementThickness;
footBaseWidth = 10;
footEndWidth = 5;
hddMountSpacingH = 3 * 25.4;
hddMountSpacingV = (2 + 7/16) * 25.4;
hddMountHoleDia = 3;
hddCountersinkDia = 5.5;
hddMountColumns = [holeSpacingH - hddMountSpacingH, holeSpacingH];
union() {
mounts();
frame();
feet();
}
module mountOutline(d) {
circle(d/2, $fn=32);
}
module mountOutlines(d) {
translate([-frameSize[0] / 2, 0]) union() {
for (a=mountColumns) {
translate([a, -holeSpacingV/2]) mountOutline(d);
translate([a, holeSpacingV/2]) mountOutline(d);
}
}
}
module hddMountOutlines(d) {
translate([-frameSize[0] / 2, 0]) union() {
for (a=hddMountColumns) {
translate([a, -hddMountSpacingV/2]) mountOutline(d);
translate([a, hddMountSpacingV/2]) mountOutline(d);
}
}
}
module mountFlange() {
translate([-footThickness/2, 0]) rotate([90, 0, 90])
linear_extrude(footThickness) polygon(points=[
[mountHoleDia/2, 0],
[frameEdgePaddingV, 0],
[frameEdgePaddingV, frameReinforcementHeight],
[mountHoleDia/2, mountLength]]);
}
module mountFlangeRow() {
for (a=mountColumns)
translate([a - frameSize[0] / 2, holeSpacingV/2]) mountFlange();
}
module mounts() {
union() {
linear_extrude(mountLength) difference() {
mountOutlines(mountDia);
mountOutlines(mountHoleDia);
}
mountFlangeRow();
mirror([0, 1, 0]) mountFlangeRow();
}
}
module frameFlangeRow(length, columns) {
for (a=columns)
translate([a - frameSize[0]/2 - frameWidth/2, frameSize[1]/2 - length]) square(size=[frameWidth, length]);
}
module frameFlanges(length, columns) {
frameFlangeRow(length, columns);
mirror([0, 1, 0]) frameFlangeRow(length, columns);
}
module frameRim(width) {
difference() {
offset(r=width/2) square(size=frameSize, center=true);
offset(r=-width/2) square(size=frameSize, center=true);
}
}
module frameHddEndFlange() {
translate([-frameSize[0] / 2, (hddMountSpacingV - frameWidth) / 2]) square(size=[hddMountColumns[0], frameWidth]);
}
module frameOutline() {
difference() {
union() {
frameRim(frameWidth);
mountOutlines(frameWidth);
hddMountOutlines(frameWidth);
frameFlanges(frameEdgePaddingV, mountColumns);
frameFlanges((frameSize[1] - hddMountSpacingV) / 2, [hddMountColumns[1]]);
frameHddEndFlange();
mirror([0, 1, 0]) frameHddEndFlange();
}
mountOutlines(mountHoleDia);
hddMountOutlines(hddMountHoleDia);
}
}
module frameReinforcementOutline() {
difference() {
frameRim(frameReinforcementThickness);
mountOutlines(mountHoleDia);
}
}
module hddCountersink() {
translate([0, 0, frameThickness]) mirror([0, 0, 1]) cylinder(hddCountersinkDia/2, hddCountersinkDia/2, 0, $fn=32);
}
module hddCountersinks() {
translate([-frameSize[0] / 2, 0]) union() {
for (a=hddMountColumns) {
translate([a, -hddMountSpacingV/2]) hddCountersink();
translate([a, hddMountSpacingV/2]) hddCountersink();
}
}
}
module frame() {
difference() {
union() {
linear_extrude(frameThickness) frameOutline();
linear_extrude(frameReinforcementHeight) frameReinforcementOutline();
}
hddCountersinks();
}
}
module halfFoot() {
linear_extrude(footThickness) polygon(points=[
[-footThickness/2, 0],
[-footThickness/2, footHeight],
[footEndWidth, footHeight],
[footBaseWidth, 0]]);
}
module foot() {
union() {
translate([0, footThickness/2]) rotate(a=[90, 0, 0]) halfFoot();
translate([-footThickness/2, 0]) rotate(a=[90, 0, 90]) halfFoot();
}
}
module feet() {
union() {
translate([-frameSize[0] / 2, -frameSize[1] / 2]) rotate(a=[0,0,0]) foot();
translate([frameSize[0] / 2, -frameSize[1] / 2]) rotate(a=[0,0,90]) foot();
translate([frameSize[0] / 2, frameSize[1] / 2]) rotate(a=[0,0,180]) foot();
translate([-frameSize[0] / 2, frameSize[1] / 2]) rotate(a=[0,0,270]) foot();
}
}