Skip to content

Instantly share code, notes, and snippets.

@ednisley
Created January 10, 2016 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ednisley/d5d676c9a9402f48c3cd to your computer and use it in GitHub Desktop.
Save ednisley/d5d676c9a9402f48c3cd to your computer and use it in GitHub Desktop.
OpenSCAD Source Code: Microscope Stage Positioner
// Microscope Stage Positioner
// Ed Nisley KE4ZNU January 2016
Layout = "Build"; // Show Build
// Base ZStand YMount XMount
Gap = 0.0;
//- Extrusion parameters must match reality!
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
inch = 25.4;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
//----------------------
// Dimensions
SlipFit = 0.1;
ZDrive = [26.0,19.6,75.0]; // stationary part of Z drive
ZDriveOffset =[0,0,22.0]; // left front corner of stationary Z base
ZWall = 4.0; // thickness of edge wrapped around Z columns
YStageBlock = [25.0,61.0,17.0]; // Y stage mount + slide
YStageOffset = [-6.0,4.0,0.0]; // offset to inner corner of Y stage holder
YArm = [10.0,93.0,17.0]; // mount to stationary part of Y stage
ZStage = [24.0,9.7,85.0]; // moving part of Z drive
ZYArm = [(2*ZWall + ZStage[0]),10.0,YArm[2]]; // attaches to ZStage, same thickness as YArm
XStageBlock = [25.0,20.0,12.0]; // X stage mount + slide
XStageOffset = [-95.0,-15.0,-26]; // offset to rear left bottom corner of X stage slide
XTray = [25,25,5]; // X tray attached to bottom of X mount
//----------------------
// Useful routines
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);
}
//-- Z Stand
module ZStand() {
Holes = [12.0,41.5,68.0];
HoleOD = 3.5;
HolesOC = 15.0;
echo(str("Z Stand holes OC: ",HolesOC));
ZPlate = 6.0; // thickness of Z plate = max screw grab distance
ZStandWrap = 2.0; // length of edge wrapped around Z column
MaxY = 9.0;
MinY = -14.0;
difference() {
union() {
linear_extrude(height=ZDriveOffset[2])
polygon(points=[
[-ZWall,MaxY], // limited by Z slide rack
[ZDrive[0] + ZWall,MaxY],
[ZDrive[0] + ZWall,MinY], // limited by X slide rack
[-ZWall,MinY]
]);
linear_extrude(height=(ZDrive[2] + ZDriveOffset[2]),convexity=4)
polygon(points=[
[-SlipFit,0],
[ZDrive[0] + SlipFit,0.0],
[ZDrive[0] + SlipFit,ZStandWrap],
[ZDrive[0] + ZWall,ZStandWrap],
[ZDrive[0] + ZWall,-ZPlate],
[-ZWall,-ZPlate],
[-ZWall,ZStandWrap],
[-SlipFit,ZStandWrap]
]);
}
for (i = [0:len(Holes) - 1]) // holes along Z stand
translate([ZDrive[0]/2,ZDrive[1]/2,(Holes[i] + ZDriveOffset[2])])
rotate([90,0,0])
PolyCyl(HoleOD,ZDrive[1]);
for (i = [-1,1]) // mounting screw holes
translate([i*HolesOC/2 + ZDrive[0]/2, // center the holes from side to side
(MaxY + MinY)/2, // moby hack to put holes on midline
-Protrusion])
PolyCyl(3.5,0.75*ZDriveOffset[2],6);
}
}
//-- Y Mounting arm
// Polygon origin at inner corner nearest the Z stand column
module YMount() {
YHoles = [12.0,48.0,84.0]; // mounting holes along Y stage arm, from outside in
YScrewLength = 4.0; // screw head to Y stage mount
ZStageBase = [(ZDrive[0] - ZStage[0])/2,(ZDrive[1] + ZStage[1]),0.0] - YStageOffset; // local coordinates of Z slide left rear corner
ZHoles = [26.5,55.0,71.0];
ZStageWrap = 8.0; // length of edge wrapped around Z stage
Trim = ZStageBase[1] - ZStageWrap;
union() {
difference() {
linear_extrude(height=YArm[2],convexity=5)
polygon(points=[
[-Trim,0.0],
[-YStageBlock[0],0.0],
[-YStageBlock[0],-(YArm[1] + SlipFit)],
[-(YStageBlock[0] + YArm[0]),-(YArm[1] + SlipFit)],
[-(YStageBlock[0] + YArm[0]),Trim],
[-Trim,(ZStageBase[1] + ZYArm[1])],
[(ZStageBase[0] + ZStage[0]/2),(ZStageBase[1] + ZYArm[1])],
[(ZStageBase[0] + ZStage[0] + ZWall),(ZStageBase[1] + 0*ZYArm[1])],
[(ZStageBase[0] + ZStage[0] + ZWall),(ZStageBase[1] - ZStageWrap)],
[(ZStageBase[0] + ZStage[0] + SlipFit),(ZStageBase[1] - ZStageWrap)],
[(ZStageBase[0] + ZStage[0] + SlipFit),ZStageBase[1]],
[(ZStageBase[0] - SlipFit),ZStageBase[1]],
[(ZStageBase[0] - SlipFit),(ZStageBase[1] - ZStageWrap)],
[0.0,(ZStageBase[1] - ZStageWrap)],
[0.0,Trim]
]);
for (j=[0:len(YHoles) - 1]) { // Y stage mounting screws
translate([-(YStageBlock[0] + YScrewLength),
(-YArm[1] + YHoles[j] - 2*SlipFit),
YArm[2]/2])
rotate([0,-90,0]) rotate(180/6)
PolyCyl(5.5,YArm[0],6);
translate([-(YStageBlock[0] - Protrusion),
(-YArm[1] + YHoles[j] - 2*SlipFit),
YArm[2]/2])
rotate([0,-90,0]) rotate(180/6)
PolyCyl(2.5,2*YArm[0],6);
}
}
if (true)
difference() {
linear_extrude(height=ZStage[2],convexity=5)
polygon(points=[
[(ZStageBase[0] - ZWall),(ZStageBase[1] + 5.0)],
[(ZStageBase[0] + ZStage[0] + ZWall),(ZStageBase[1] + 5.0)],
[(ZStageBase[0] + ZStage[0] + ZWall),(ZStageBase[1] - ZStageWrap)],
[(ZStageBase[0] + ZStage[0] + SlipFit),(ZStageBase[1] - ZStageWrap)],
[(ZStageBase[0] + ZStage[0] + SlipFit),ZStageBase[1]],
[(ZStageBase[0] - SlipFit),ZStageBase[1]],
[(ZStageBase[0] - SlipFit),(ZStageBase[1] - ZStageWrap)],
[(ZStageBase[0] - ZWall),(ZStageBase[1] - ZStageWrap)],
]);
for (k=[0:len(ZHoles) - 1])
translate([(ZStageBase[0] + ZStage[0]/2),0.0,ZHoles[k]])
rotate([-90,0,0])
PolyCyl(3.5,2*ZStageBase[1],6);
}
}
}
//-- X Slide attachment
// Origin at left rear bottom of mount
module XMount() {
XHoles = [6.0,18.0]; // from end of X slide
XHolesOffset = 7.0; // from bottom of X slide
TrayHolesOC = 10.0;
echo(str("Tray holes OC: ",TrayHolesOC));
BlockOAH = XStageBlock[2] - XStageOffset[2] - XTray[2]; // overall height of mount
difference() {
translate([XStageBlock[0],0,BlockOAH])
rotate([0,90,180])
linear_extrude(height=XStageBlock[0],convexity=2)
polygon(points=[
[0,0],
[0.0,7.0],
[(XStageBlock[2] + SlipFit),7.0],
[(XStageBlock[2] + SlipFit),XStageBlock[1]],
[BlockOAH,XStageBlock[1]],
[BlockOAH,0.0],
]);
for (i=[0:len(XHoles) - 1]) // holes for X stage screws
translate([XHoles[i],Protrusion,BlockOAH - XStageBlock[2] + XHolesOffset])
rotate([90,0,0])
PolyCyl(3.5,2*7.0,6);
for (i=[-1,1]) // holes for tray mount
translate([i*TrayHolesOC/2 + XStageBlock[0]/2,-XStageBlock[1]/2,-Protrusion])
PolyCyl(2.5,0.75*(BlockOAH - XStageBlock[2]),6);
}
}
//----------------------
// Build it
if (Layout == "ZStand")
ZStand();
if (Layout == "YMount")
YMount();
if (Layout == "XMount")
XMount();
if (Layout == "Show") {
color("lightgreen")
ZStand();
color("orange")
translate(YStageOffset)
YMount();
color("lightblue")
translate(XStageOffset + [0,0,-XStageOffset[2]])
XMount();
}
if (Layout == "Build") {
translate([20,0,0])
ZStand();
translate([YStageBlock[0]/2,0,0])
YMount();
translate([20,-30,0])
XMount();
}
@ednisley
Copy link
Author

More details on my blog at http://wp.me/poZKh-5y9

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