Skip to content

Instantly share code, notes, and snippets.

@thehans
Last active August 28, 2021 18:41
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 thehans/acd2caca71b1e4cdf8be3c71d4689bb9 to your computer and use it in GitHub Desktop.
Save thehans/acd2caca71b1e4cdf8be3c71d4689bb9 to your computer and use it in GitHub Desktop.
Endstop mount
//use <../Libraries/drawPath.scad>
// Width of base
wBase = 20;
// Length of base
lBase = 25;
// Thickness of base
thBase = 5;
// Fillet radius
rFillet = 1;
// Thickness under bolt head
thBoltBase = 3;
// Length of switch body
lSwitch = 20;
// Width of switch body
wSwitch = 10;
// Thickness of switch body
thSwitch = 6;
// Distance between centers of holes on switch
boltSpacing = 9.57;
// Diameter of bolt holes on switch
dSwitchBolt = 2.5;
// Switch holding arms are offset from edge of the base to give better clearance from potential bolt heads on carriage
clearanceOffset = 2;
// Diameter of counterbore for bolt head
dBoltHead = 10;
// Diameter of bolt hole
dBolt = 5.3;
// Thickness of cable tie channel
thCableTie = 1.5;
// Width of cable tie channel
wCableTie = 5;
// Angle in degreess between bump edge and surface, around the edge of the bump
bumpAngle = 45;
// Width across flats of nut
//wSwitchNut = 4;
/* [Hidden] */
$fa=2;
$fs=0.2;
err = 0.002;
// calculated
h0 = 10-thSwitch/2;
y0 = wSwitch+rFillet*2;
// distance from bolt counterbore to edge
wBoltPadding = (lBase-wSwitch-dBoltHead)/2;
// width of "pad" profile that is extruded to form the switch-holding arms
wPad = (wBase-thSwitch)/2-clearanceOffset;
// diameter of sphere used to make bump for the given bumpAngle
dSphere = dSwitchBolt/cos(bumpAngle);
// distance to set sphere into the arms for the given bumpAngle
sphereInset = dSphere*sin(bumpAngle)/2;
// Max width across points of nut
//dSwitchNut = 2*(wSwitchNut)/sqrt(3); // M2
endstopMount();
// display switch body mockup
//translate([(wBase+thSwitch-err)/2,0,thBase]) rotate([0,-90,0]) microswitch();
module endstopMount() {
difference() {
union() {
linear_extrude(thBase, convexity=2) {
baseProfile();
}
// right brace
translate([wBase-wPad-clearanceOffset,0,thBase-err]) {
linear_extrude(lSwitch-wPad+thCableTie, convexity=2) padProfile();
translate([0,wSwitch,lSwitch-wPad+thCableTie]) rotate([90,0]) rotate_extrude2(angle=90, convexity=2)
padProfile();
}
// left brace
translate([clearanceOffset,0,thBase-err]) {
linear_extrude(lSwitch-wPad+thCableTie, convexity=2) mirror([1,0]) translate([-wPad,0]) padProfile();
translate([wPad,wSwitch,lSwitch-wPad+thCableTie]) rotate([90,0]) rotate(180) rotate_extrude2(angle=-90) padProfile();
}
// nubs for lining up holes
for (i=[-1,1], j=[-1,1])
translate([wBase/2+j*(thSwitch/2+sphereInset),wSwitch-(1.25+dSwitchBolt/2),thBase+lSwitch/2+i*boltSpacing/2])
sphere(d=dSphere);
}
translate([wBase/2,lBase-wBoltPadding-dBoltHead/2])
mountBolt();
// radius'd cable tie channel
r1 = wPad-thCableTie;
translate([wPad+clearanceOffset+err,wCableTie/2+wSwitch/2,r1+thBase])rotate([90,0])
rotate(180) rotate_extrude2(angle=90, convexity=2) translate([r1,0]) square([thCableTie,wCableTie]);
// straight through cable tie channel
translate([wBase-wPad-clearanceOffset,wCableTie/2+wSwitch/2,thBase])
rotate([0,90,0]) translate([0,-wCableTie,-err]) linear_extrude(wPad+2*err, convexity=2)
square([thCableTie,wCableTie]);
}
}
module baseProfile() {
path = concat(
arcPath(r=rFillet,angle=90,c=[wBase-rFillet,lBase-rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=90,c=[rFillet,lBase-rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=180,c=[rFillet,wSwitch+rFillet]),
arcPath(r=rFillet,angle=-90,offsetAngle=90,c=[clearanceOffset-rFillet,wSwitch-rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=180,c=[clearanceOffset+rFillet,rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=270,c=[clearanceOffset+wPad-rFillet,rFillet]),
arcPath(r=rFillet,angle=-90,offsetAngle=180,c=[clearanceOffset+wPad+rFillet,wSwitch-rFillet]),
arcPath(r=rFillet,angle=-90,offsetAngle=90,c=[wBase-wPad-clearanceOffset-rFillet,wSwitch-rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=180,c=[wBase-wPad-clearanceOffset+rFillet,rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=270,c=[wBase-clearanceOffset-rFillet,rFillet]),
arcPath(r=rFillet,angle=-90,offsetAngle=180,c=[wBase-clearanceOffset+rFillet,wSwitch-rFillet]),
arcPath(r=rFillet,angle=90,offsetAngle=270,c=[wBase-rFillet,wSwitch+rFillet])
);
polygon(path);
}
module padProfile() {
path = square([wPad,wSwitch],r=rFillet);
difference() {
polygon(path);
translate([wPad-thCableTie,wSwitch/2-wCableTie/2]) square([thCableTie+err,wCableTie]);
}
}
module microswitch() {
color([0.3,0.3,0.3,0.5+err]) linear_extrude(thSwitch-2*err) difference() {
square([lSwitch,wSwitch]);
bolts2d();
}
}
module mountBolt() {
translate([0,0,thBase-thBoltBase])
cylinder(d=dBoltHead,h=thBase);
translate([0,0,-1])
cylinder(d=dBolt,h=thBase);
}
module bolts2d() {
for (i = [-1,1]) {
translate([lSwitch/2+i*boltSpacing/2,wSwitch-(1.25+dSwitchBolt/2)])
circle(d=dSwitchBolt);
}
}
module nuts2d() {
for (i = [0,1]) {
translate([5.15+i*boltSpacing,wSwitch-(1.25+dSwitchBolt/2)])
rotate(0) circle(d=dSwitchNut,$fn=6);
}
}
// use <../Libraries/rotate_extrude.scad>;
// older versions of OpenSCAD do not support "angle" parameter for rotate_extrude
// this module provides that capability even when using older versions (such as thingiverse customizer)
module rotate_extrude2(angle=360, convexity=2, size=max(wBase+2,lBase+2)/2) {
module angle_cut(angle=90,size=1000) {
x = size*cos(angle/2);
y = size*sin(angle/2);
translate([0,0,-size])
linear_extrude(2*size) polygon([[0,0],[x,y],[x,size],[-size,size],[-size,-size],[x,-size],[x,-y]]);
}
// support for angle parameter in rotate_extrude was added after release 2015.03
// Thingiverse customizer is still on 2015.03
angleSupport = (version_num() > 20150399) ? true : false; // Next openscad releases after 2015.03.xx will have support angle parameter
// Using angle parameter when possible provides huge speed boost, avoids a difference operation
if (angleSupport) {
rotate_extrude(angle=angle,convexity=convexity)
children();
} else {
rotate([0,0,angle/2]) difference() {
rotate_extrude(convexity=convexity) children();
angle_cut(angle, size);
}
}
}
// use <../Libraries/drawPath.scad>
// based on get_fragments_from_r documented on wiki
// https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language
function fragments(r=1) = ($fn > 0) ?
($fn >= 3 ? $fn : 3) :
ceil(max(min(360.0 / $fa, r*2*PI / $fs), 5));
// Draw a circular arc with center c, radius r, etc.
// "center" parameter centers the sweep of the arc about the offsetAngle (half to each side of it)
// "internal" parameter does enables polyhole radius correction
function arcPath(r=1, angle=360, offsetAngle=0, c=[0,0], center=false, internal=false) =
let (
fragments = ceil((abs(angle) / 360) * fragments(r)),
step = angle / fragments,
a = offsetAngle-(center ? angle/2 : 0),
R = internal ? r / cos (180 / fragments) : r,
last = (angle == 360 ? 1 : 0)
)
[ for (i = [0:fragments-last] ) let(a2=i*step+a) c+R*[cos(a2), sin(a2)] ];
function circle(r=1, c=[0,0], internal=false, d) =
let(r1 = d==undef ? r : d/2)
arcPath(r=r1,c=c,angle=-360,internal=internal);
function square(size=1, center=false,r=0) =
let(
x = len(size) ? size.x : size,
y = len(size) ? size.y : size,
o = center ? [-x/2,-y/2] : [0,0],
d = r*2
)
//assert(d <= x && d <= y)
translate(o,
(r > 0 ?
concat(
arcPath(r=r, angle=-90, offsetAngle=0, c=[x-r, r]),
arcPath(r=r, angle=-90, offsetAngle=270, c=[ r, r]),
arcPath(r=r, angle=-90, offsetAngle=180, c=[ r,y-r]),
arcPath(r=r, angle=-90, offsetAngle=90, c=[x-r,y-r])
) :
[[0,0],[0,y],[x,y],[x,0]]
)
);
function translate(v, points) = [for (p = points) p+v];
function scale(v=1, points) = let(s = len(v) ? v : [v,v,v])
len(points) && len(points[0]) == 3 ?
[for (p = points) [s.x*p.x,s.y*p.y,s.z*p.z]] :
[for (p = points) [s.x*p.x,s.y*p.y]];
// rotate a list of 3d points by angle vector v
// vector v = [pitch,roll,yaw] in degrees
function rotate(v, points) =
let(
lv = len(v),
V = (lv == undef ? [0,0,v] :
(lv > 2 ? v :
(lv > 1 ? [v.x,v.y,0] :
(lv > 0 ? [v.x,0,0] : [0,0,0])
)
)
),
cosa = cos(V.z), sina = sin(V.z),
cosb = cos(V.y), sinb = sin(V.y),
cosc = cos(V.x), sinc = sin(V.x),
Axx = cosa*cosb,
Axy = cosa*sinb*sinc - sina*cosc,
Axz = cosa*sinb*cosc + sina*sinc,
Ayx = sina*cosb,
Ayy = sina*sinb*sinc + cosa*cosc,
Ayz = sina*sinb*cosc - cosa*sinc,
Azx = -sinb,
Azy = cosb*sinc,
Azz = cosb*cosc
)
[for (p = points)
let( pz = (p.z == undef) ? 0 : p.z )
[Axx*p.x + Axy*p.y + Axz*pz,
Ayx*p.x + Ayy*p.y + Ayz*pz,
Azx*p.x + Azy*p.y + Azz*pz]
];
// rotate about z axis without adding 3rd dimension to points
function rotate2d(a=0, points) =
let(
cosa = cos(a),
sina = sin(a)
)
[for (p = points) [p.x * cosa - p.y * sina,p.x * sina + p.y * cosa]];
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment