Skip to content

Instantly share code, notes, and snippets.

@ednisley
Created November 19, 2017 23:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ednisley/3bc51f11fef466efe2be129a2bc2c8b6 to your computer and use it in GitHub Desktop.
Save ednisley/3bc51f11fef466efe2be129a2bc2c8b6 to your computer and use it in GitHub Desktop.
OpenSCAD source code: Prototype board holder with mounting holes and selectable board sizes
// Test support frame for proto boards
// Ed Nisley KE4ZNU - Jan 2017
// June 2017 - Add side-mount bracket, inserts into bottom
// 2017-11 - Selectable board sizes, chassis mounting holes
/* [Options] */
PCBSelect = "ArdUno"; // ["20x80","40x60","30x70","50x70","70x90","80x120","ArdDuemil","ArdMega","ArdPro","ArdUno","ProtoneerCNC"]
Layout = "Frame"; // [Frame, Bracket]
ClampFlange = true; // external flange
Mounts = true; // frame to chassis screw holes
Channel = false; // wiring channel cutout
WasherRecess = false; // cutout around screw head
/* [Extrusion parameters] */
ThreadThick = 0.25; // [0.15, 0.20, 0.25]
ThreadWidth = 0.40;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
/* [Hidden] */
Protrusion = 0.1;
HoleWindage = 0.2;
inch = 25.4;
Tap4_40 = 0.089 * inch;
Clear4_40 = 0.110 * inch;
Head4_40 = 0.211 * inch;
Head4_40Thick = 0.065 * inch;
Nut4_40Dia = 0.228 * inch;
Nut4_40Thick = 0.086 * inch;
Washer4_40OD = 0.270 * inch;
Washer4_40ID = 0.123 * inch;
Tap6_32 = 0.106 * inch;
Clear6_32 = 0.166 * inch;
Head6_32 = 0.251 * inch;
Head6_32Thick = 0.097 * inch;
Nut6_32Dia = 0.312 * inch;
Nut6_32Thick = 0.109 * inch;
Washer6_32OD = 0.361 * inch;
Washer6_32ID = 0.156 * inch;
ID = 0;
OD = 1;
LENGTH = 2;
//- PCB sizes
// the list must contain all the selection names as above
//* [Hidden] */
PCB_NAME = 0;
PCB_DIMENSION = 1;
PCBSizes = [
["40x60",[40,60,1.6]],
["30x70",[30,70,1.6]],
["50x70",[50,70,1.6]],
["20x80",[20,80,1.6]],
["70x90",[70,90,1.6]],
["80x120",[80,120,1.6]],
["ArdDuemil",[69,84,1.6]],
["ArdMega",[102,53.5,1.6]],
["ArdPro",[53,53.5,1.6]],
["ArdUno",[69,53.1,1.6]],
["ProtoneerCNC",[69,53.1,1.6]],
];
PCBIndex = search([PCBSelect],PCBSizes)[0];
PCBSize = PCBSizes[PCBIndex][PCB_DIMENSION];
//echo(str("PCB Size Table: ",PCBSizes));
//echo(str("PCB Select: ",PCBSelect));
//echo(str("PCB Index: ",PCBIndex));
echo(str("PCB Size: ",PCBSize));
/* [Sizes] */
WallThick = 4.0; // basic frame structure
FrameHeight = 10.0;
/* [Hidden] */
Insert = [3.9,4.6,5.8];
PCBShelf = 1.0; // width of support rim under PCB
Clearance = 1*[ThreadWidth,ThreadWidth,0]; // around PCB on all sides
ScrewOffset = ThreadWidth + Insert[OD]/2; // beyond PCB edges
echo(str("Screw offset: ",ScrewOffset));
/* [Screw Selectors] */
// ij selectors for PCB clamp screw holes: -1/0/1 = left/center/right , bottom/center/top
ScrewSites = [
// [-1,1],[1,1],[1,-1],[-1,-1], // corners
// [-1,0],[1,0],[0,1],[0,-1] // middles
[-1,1],[-1,-1],[1,0] // Arduinos
];
// ij selectors for frame mounting holes
MountSites = [
[0,-1],[0,1],
// [-1,0],[1,0]
];
function ScrewAngle(ij) = (ij[0]*ij[1]) ? ij[0]*ij[1]*15 : ((!ij[1]) ? 30 : 0); // align screw sides
OAHeight = FrameHeight + Clearance[2] + PCBSize[2]; // total frame height
echo(str("OAH: ",OAHeight));
BossOD = 2*Washer4_40OD; // make bosses oversized for washers
FlangeExtension = 4.0 + Washer6_32OD/2 - WallThick; // beyond frame structure
FlangeThick = IntegerMultiple(2.0,ThreadThick); // plate under frame
Flange = PCBSize
+ 2*[ScrewOffset,ScrewOffset,0]
+ [BossOD,BossOD,0]
+ [2*FlangeExtension,2*FlangeExtension,(FlangeThick - PCBSize[2])]
;
FlangeRadius = BossOD/4;
echo(str("Flange: ",Flange));
NumSides = 4*5;
WireChannel = [Flange[0],15.0,3.0 + PCBSize[2]]; // ad-hoc wiring cutout
WireChannelOffset = [
Flange[0]/2,0,(FrameHeight + PCBSize[2] - WireChannel[2]/2)
];
//- Adjust hole diameter to make the size come out right
module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
FiiDia = Dia / cos(180/Sides);
cylinder(r=(FiiDia + HoleWindage)/2,h=Height,$fn=Sides);
}
//- Build things
if (Layout == "Frame")
difference() {
union() { // body block
translate([0,0,OAHeight/2])
cube(PCBSize + Clearance + [2*WallThick,2*WallThick,FrameHeight],center=true);
for (ij = ScrewSites) // screw bosses
if (ij[0] != 0 || ij[1] != 0)
translate([ij[0]*(PCBSize[0]/2 + ScrewOffset),
ij[1]*(PCBSize[1]/2 + ScrewOffset),
0])
cylinder(d=BossOD,h=OAHeight,$fn=NumSides);
if (ClampFlange) // flange for work holder & mounting screw holes
linear_extrude(height=Flange[2])
hull()
for (i=[-1,1], j=[-1,1]) {
translate([i*(Flange[0]/2 - FlangeRadius),j*(Flange[1]/2 - FlangeRadius)])
circle(r=FlangeRadius,$fn=NumSides); // convenient rounding size
}
}
for (ij = ScrewSites) { // screw position indeies
if (ij[0] != 0 || ij[1] != 0) {
translate([ij[0]*(PCBSize[0]/2 + ScrewOffset),
ij[1]*(PCBSize[1]/2 + ScrewOffset),
-Protrusion])
rotate(ScrewAngle(ij))
PolyCyl(Clear4_40,(OAHeight + 2*Protrusion),6); // screw clearance holes
translate([ij[0]*(PCBSize[0]/2 + ScrewOffset),
ij[1]*(PCBSize[1]/2 + ScrewOffset),
-Protrusion])
rotate(ScrewAngle(ij))
PolyCyl(Insert[OD],OAHeight - PCBSize[2] - 3*ThreadThick + Protrusion,6); // inserts
if (WasherRecess)
translate([ij[0]*(PCBSize[0]/2 + ScrewOffset),
ij[1]*(PCBSize[1]/2 + ScrewOffset),
OAHeight - PCBSize[2]])
PolyCyl(1.2*Washer4_40OD,(PCBSize[2] + Protrusion),NumSides); // optional washer recess
}
}
if (Mounts)
for (ij = MountSites)
translate([ij[0]*(Flange[0]/2 - Washer6_32OD/2),ij[1]*(Flange[1]/2 - Washer6_32OD/2),-Protrusion])
rotate(ScrewAngle(ij))
PolyCyl(Clear6_32,(Flange[2] + 2*Protrusion),6);
translate([0,0,OAHeight/2]) // through hole below PCB
cube(PCBSize - 2*[PCBShelf,PCBShelf,0] + [0,0,2*OAHeight],center=true);
translate([0,0,(OAHeight - (PCBSize[2] + Clearance[2])/2 + Protrusion/2)]) // PCB pocket on top
cube(PCBSize + Clearance + [0,0,Protrusion],center=true);
if (Channel)
translate(WireChannelOffset) // opening for wires from bottom side
cube(WireChannel + [0,0,Protrusion],center=true);
}
// Add-on bracket to hold smaller PCB upright at edge
PCB2Insert = [3.0,4.9,4.1];
PCB2OC = 45.0;
if (Layout == "Bracket")
difference() {
hull() // frame body block
for (i=[-1,1]) // bosses around screws
translate([i*(PCBSize[0]/2 + ScrewOffset),0,0])
cylinder(r=Washer4_40OD,h=OAHeight,$fn=NumSides);
for (i=[-1,1]) // frame screw holes
translate([i*(PCBSize[0]/2 + ScrewOffset),0,-Protrusion])
rotate(i*180/(2*6))
PolyCyl(Clear4_40,(OAHeight + 2*Protrusion),6);
for (i=[-1,1]) // PCB insert holes
translate([i*PCB2OC/2,(Washer4_40OD + Protrusion),OAHeight/2])
rotate([90,0,0])
cylinder(d=PCB2Insert[OD],h=2*(Washer4_40OD + Protrusion),$fn=6);
}
@ednisley
Copy link
Author

More details on my blog at https://wp.me/poZKh-7aC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment