|
// MPCNC USB Camera Mount |
|
// Ed Nisley KE4ZNU – 2018-02-22 |
|
|
|
Layout = "Build"; // Build, Show |
|
|
|
/* [Extrusion] */ |
|
|
|
ThreadThick = 0.25; // [0.20, 0.25] |
|
ThreadWidth = 0.40; // [0.40] |
|
|
|
/* [Hidden] */ |
|
|
|
Protrusion = 0.1; // [0.01, 0.1] |
|
|
|
HoleWindage = 0.2; |
|
|
|
inch = 25.4; |
|
|
|
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); |
|
|
|
ID = 0; |
|
OD = 1; |
|
LENGTH = 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); |
|
FixDia = Dia / cos(180/Sides); |
|
cylinder(r=(FixDia + HoleWindage)/2,h=Height,$fn=Sides); |
|
} |
|
|
|
//- Dimensions |
|
|
|
WallThick = 3.0; // minimum thickness / width |
|
|
|
CameraStalk = [6.0 + 1.0,10.0 + HoleWindage,4.0]; // stalk OD, ball OD, stalk length |
|
CameraAngle = -5; // stalk tilt, negative = downward |
|
|
|
Screw = [3.0,7.0,25.0]; // holding it all together, OD = washer |
|
|
|
Insert = [3.0,4.4,4.5]; // brass insert |
|
Pusher = Insert[LENGTH] / 2; // plastic locking snippet |
|
|
|
UpperThick = IntegerMultiple(CameraStalk[OD]/2 + Insert[LENGTH] + Pusher + WallThick,ThreadThick); |
|
LowerThick = Screw[LENGTH] – UpperThick; |
|
|
|
MountBlock = [24.0,20.0,LowerThick + UpperThick]; |
|
|
|
echo(str("Block: ",MountBlock)); |
|
|
|
NumSides = 6*4; |
|
|
|
//—– |
|
// Define shapes |
|
|
|
// Camera mount, enlongated for E-Z differencing |
|
// Origin at center of ball, stalk along +X |
|
|
|
module Camera() { |
|
|
|
union() { |
|
sphere(d=CameraStalk[OD],$fn=NumSides); |
|
rotate([0,90 – CameraAngle,0]) |
|
PolyCyl(CameraStalk[ID],3*CameraStalk[LENGTH],NumSides); |
|
} |
|
} |
|
|
|
// Mount block with all the cutouts |
|
// Ball centerline on XY plane = block split line |
|
|
|
module Mount(Half="All") { |
|
|
|
Rounding = 2.0; // corner radius |
|
|
|
ZShift = // block shift to remove unwanted half |
|
(Half == "Upper") ? -MountBlock.z/2 – 0*UpperThick : |
|
(Half == "Lower") ? MountBlock.z/2 + 0*LowerThick : |
|
2*MountBlock.z; // … want both halves, remove none |
|
|
|
difference() { |
|
hull() |
|
for (i=[-1,1], j=[-1,1]) { |
|
translate([i*(MountBlock.x/2 – Rounding),j*(MountBlock.y/2 – Rounding),(UpperThick – Rounding)]) |
|
sphere(r=Rounding,$fn=3*4); |
|
translate([i*(MountBlock.x/2 – Rounding),j*(MountBlock.y/2 – Rounding),-(LowerThick – Rounding)]) |
|
sphere(r=Rounding,$fn=3*4); |
|
} |
|
|
|
for (j=[-1,1]) |
|
translate([-MountBlock.x/4,j*MountBlock.y/4,-(LowerThick + Protrusion)]) { |
|
PolyCyl(Insert[OD],Insert[LENGTH] + Protrusion,6); |
|
PolyCyl(Insert[ID],2*MountBlock.z,6); |
|
} |
|
|
|
translate([MountBlock.x/2 – (CameraStalk[OD]/2 + CameraStalk[LENGTH]),0,0]) { |
|
Camera(); |
|
translate([0,0,UpperThick – (Insert[LENGTH] + WallThick)]) |
|
PolyCyl(Insert[OD],Insert[LENGTH] + WallThick,6); |
|
PolyCyl(Insert[ID],2*UpperThick,6); |
|
} |
|
|
|
translate([0,0,ZShift]) |
|
cube([2*MountBlock.x,2*MountBlock.y,MountBlock.z],center=true); |
|
} |
|
|
|
} |
|
|
|
//—– |
|
// Build it |
|
|
|
if (Layout == "Show") |
|
Mount("All"); |
|
|
|
if (Layout == "Build") { |
|
translate([0,0.75*MountBlock.y,UpperThick]) |
|
rotate([180,0,0]) |
|
Mount("Upper"); |
|
translate([0,-0.75*MountBlock.y,LowerThick]) |
|
rotate([0,0,0]) |
|
Mount("Lower");} |