Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
Turns out that it’s 0.1340 inches, determined by bracketing the sliver above that 0.1300 block with feeler gauges. I don’t believe that last zero, either, as the Basement Shop was about 10 °F below the block’s 68 °F calibration temperature. [grin]
The actual size of that gap makes absolutely no difference whatsoever, but fooling around with the gauge blocks gave me an excuse to renew my acquaintance with them and, en passant, massage some oil over their long-neglected bodies:
Gauge block set
I used La Perle Clock Oil, which isn’t Official Gauge Block Oil, but doesn’t go bad on the shelf. Verily, this bottle may be the last of its kind, as it’s no longer available from any of the usual sources; it appears I bought it back in 2000.
The blocks are in good shape, probably because they don’t often see the light. FWIW, I have experimentally determined that my body oil doesn’t etch fingerprints into steel.
The block set, which is similar to a current box o’ blocks from Enco, claims “Workshop Grade”, but the ±0.00050 inch = 1.27 μm tolerance shown in the top row of the labels is much worse than even grade B’s sub-micron tolerance. That newer box claims “Economy” accuracy with the same spec, so I suppose somebody kvetched about mis-using the terms.
Ah, well, they’re far better than any measurements I’ve needed in a while and entirely suitable for verifying my other instruments.
Turns out that I managed to crunch it, exactly as I expected: I’d added a block to the Z-axis stage that poked the home switch just slightly before the anti-backlash nut unscrewed from the top of the leadscrew, but the stage could continue moving another few millimeters.
You can see the gap just above the brass anti-backlash nut:
Sherline Z-axis leadscrew nut – top end
At that point, the nut has barely a single micro-smidgen of thread engaged; that last 0.1340 inch of travel (yeah, I measured it) isn’t usable.
Rather than put a collar around the end of the leadscrew, I opted for a brute-force block atop the Z-axis saddle nut that will slam into the bottom of the stepper motor mount just before the anti-backlash nut disengages:
Sherline Z-axis Overrun Block – rear view
A strip of tapeless sticky (double-sided tape, minus the tape) holds the block in place on the saddle nut. It’s not subject to any particular stress: as long as it doesn’t fall off, it’s all good.
I ran the stage upward until it stalled, then epoxied a new switch (with the old fluorescent tape) in place. This shows the result after backing the stage down a few millimeters:
Sherline Z-axis Overrun Block – side view
The solid model shows off the bevel that provides a bit more room for anti-backlash nut adjustment, not that I ever adjust it that much:
Sherline Z-Axis Overrun Prevention Block – solid model
Obviously, it doesn’t print in that position, but it’s easier to design it in the natural orientation and flip it around for printing.
The OpenSCAD source code:
// Sherline Z-axis Overrun Prevention Block
// Ed Nisley KE4ZNU December 2013
Layout = "Show"; // Show Build
//- Extrusion parameters must match reality!
// Print with 2 shells and 3 solid layers
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
//----------------------
// Dimensions
BlockZ = 30.0; // overall height
ZLimit = 17.0; // Z travel limit
TongueX = 9.0; // beside Z axis dovetail
TongueY = 10.0;
StubX = 6.0; // behind Z axis pillar
StubY = 3.0;
BlockX = TongueX + StubX; // overall X
TabY = 3.0; // behind brass bracket
TabX = BlockX - sqrt(2)*TabY;
TabZ = BlockZ - ZLimit;
BlockY = TongueY + StubY + TabY; // overall Y
//----------------------
// Useful routines
module ShowPegGrid(Space = 10.0,Size = 1.0) {
Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}
//- The Block
module Block() {
difference() {
cube([BlockX,BlockY,BlockZ]);
translate([-Protrusion,-Protrusion,-Protrusion]) // remove column
cube([(StubX + Protrusion),(TongueY + Protrusion),2*BlockZ]);
translate([-BlockX/2,-Protrusion,-Protrusion]) // form tab
cube([2*BlockX,(TongueY + StubY),(TabZ + Protrusion)]);
translate([0,BlockY,(BlockZ/2 - 0*Protrusion)])
rotate(45)
cube([3*StubY,2*StubY,(BlockZ + 2*Protrusion)],center=true);
translate([0,0,-Protrusion])
cube([sqrt(2)*TabY,2*BlockY,(TabZ + Protrusion)]);
}
}
//-------------------
// Build it...
ShowPegGrid();
if (Layout == "Show")
Block();
if (Layout == "Build")
translate([-BlockZ/2,-BlockY/2,BlockX])
rotate([0,90,0])
Block();
While putting the speed wrenches in the box with the Sherline four-jaw chuck, it occurred to me that I had all the makings of a handle for Sherline’s steel tommy bars:
Sherline Tommy Bar Handle – solid model
Because these are intended for pushing, rather than twisting, I dialed the knurl back to 32 DP, reduced the depth to 0.5 mm, and ran the bar almost all the way through the handle for strength:
Sherline Tommy Bar Handles
A dab of urethane adhesive inside the handle holds the bar in place. They started out a snug slip fit, so we’ll see how well that holds the bars in place.
A tommy bar holds the spindle against the torque from the collet pusher:
Sherline CNC mill – tommy bar and collet pusher
A pair will come in handy with the three-jaw chuck the next time that one appears.
The white slab is a very early 3D printed tool from my Thing-O-Matic, made to hold the pin at exactly the proper distance from the pulley so it fits squarely into the pusher and locks it to the spindle:
Locking pin holder – spindle end view
Other folks make much nicer tommy bar handles than mine, but I’d say my 3D printed handles beat a common nail any day!
The OpenSCAD source code:
// Knurled handles for Sherline tommy bars
// Ed Nisley - KE4ZNU - December 2013
use <knurledFinishLib_v2.scad>
//- Extrusion parameters must match reality!
// Print with 2 shells and 3 solid layers
ThreadThick = 0.20;
ThreadWidth = 0.40;
HoleWindage = 0.2; // extra clearance
Protrusion = 0.1; // make holes end cleanly
PI = 3.14159265358979;
inch = 25.4;
//----------------------
// Dimensions
ShaftDia = 10.0; // un-knurled section diameter
ShaftLength = 10.0; // ... length
SocketDia = 4.0; // tommy bar diameter
SocketDepth = 40.0;
KnurlLen = 35.0; // length of knurled section
KnurlDia = 15.0; // ... diameter
KnurlDPNom = 32; // Nominal diametral pitch = (# diamonds) / (OD inches)
DiamondDepth = 0.5; // ... depth of diamonds
DiamondAspect = 2; // length to width ratio
NumDiamonds = floor(KnurlDPNom * KnurlDia / inch);
echo(str("Num diamonds: ",NumDiamonds));
NumSides = 4*(NumDiamonds - 1); // 4 facets per diamond. Library computes diamonds separately!
KnurlDP = NumDiamonds / (KnurlDia / inch); // actual DP
echo(str("DP Nom: ",KnurlDPNom," actual: ",KnurlDP));
DiamondWidth = (KnurlDia * PI) / NumDiamonds;
DiamondLenNom = DiamondAspect * DiamondWidth; // nominal diamond length
DiamondLength = KnurlLen / round(KnurlLen/DiamondLenNom); // ... actual
TaperLength = 0.75*DiamondLength;
//----------------------
// 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);
}
module ShowPegGrid(Space = 10.0,Size = 1.0) {
Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}
//- Build it
ShowPegGrid();
difference() {
union() {
render(convexity=10)
translate([0,0,TaperLength])
knurl(k_cyl_hg=KnurlLen,
k_cyl_od=KnurlDia,
knurl_wd=DiamondWidth,
knurl_hg=DiamondLength,
knurl_dp=DiamondDepth,
e_smooth=DiamondLength/2);
color("Orange")
cylinder(r1=ShaftDia/2,
r2=(KnurlDia - DiamondDepth)/2,
h=(TaperLength + Protrusion),
$fn=NumSides);
color("Orange")
translate([0,0,(TaperLength + KnurlLen - Protrusion)])
cylinder(r2=ShaftDia/2,
r1=(KnurlDia - DiamondDepth)/2,
h=(TaperLength + Protrusion),
$fn=NumSides);
color("Moccasin")
translate([0,0,(2*TaperLength + KnurlLen - Protrusion)])
cylinder(r=ShaftDia/2,h=(ShaftLength + Protrusion),$fn=NumSides);
}
translate([0,0,(2*TaperLength + KnurlLen + ShaftLength - SocketDepth + Protrusion)])
PolyCyl(SocketDia,(SocketDepth + Protrusion),6);
}
Although automobile batteries have “standard” sizes designated by BCI Group numbers, this Group 34R Sears Diehard battery was about an inch shorter than the previous one:
Toyota Sienna – short Group 34 battery
It arrived with a plastic grid embossed with the helpful notation “Use this height adapter under battery if necessary”, but I figured lower was better. A little bending, two snippets of mouse pad (remember mouse pads?), and a section of white plastic rod faced off / drilled on the lathe anchored it flat on the platform with no wiggle room at all.
With any luck, that’s the last battery the van will ever need…
Part of the routine cleaning around here involves running the vacuum cleaner nozzle over the keyboard to suck up random debris, but that doesn’t extract crud from under the keycaps. Almost exactly three years after the previous cleaning, I finally decided the keys had lost enough of their normal feel to justify the hassle of taking the thing apart.
Bolstered by that experience, however, I just yanked the keycaps off with a removal tool from my old bag of tricks, revealing the horror that lies beneath the surface:
The keycaps took a swim in a dishpan full of hot soapy water, endured some scrubbing, and emerged looking like new. Thwacking them on a towel ejected the remaining water from the posts.
With the electronics still in place, I vacuumed the larger chunks out of the tray, scrubbed the aforementioned hot soapy water around the bushings with an acid brush, then cleaned up the residue with cotton swabs. There’s a paper towel under the drain gutters to catch the runoff, which worked surprisingly well.
The keycap legends have been eroding, as they’re basically a decal stuck on the surface. Eventually I’ll have a crappy non-clicky Das Keyboard Model S Ultimate.
[Update: a spammer’s script has been attempting to create hundreds of junk comments per day, so I’ve temporarily disabled comments for this post. Drop me a direct note using the About / Copyright / Contact link on the right if it’s critical. I expect this to pass in a few days, but I may be underestimating the stupidity out there. ]
A note from regular commenter Frans:
Don’t get a Das Keyboard if you want a keyboard without a keypad. Look into e.g. a Leopold Tenkeyless Otaku. The one to which I include a link comes with the same Cherry MX Brown switches as the Das Keyboard Silent.
Browning Hi-Power Magazine Block – solid model – whole
The horn fits between the follower’s pegs, so that chopping the pegs off won’t increase the magazine’s capacity. Chopping the horn off without modifying the follower won’t make any difference, either. As nearly as I can tell, chopping the pegs off the follower will destabilize it enough that it’ll roll over atop the spring, but I admit to not actually trying that.
The yellow comb supports the overhang that captures the tab around the magazine spring and there’s a tiny support spider inside the lower nut clearance that holds the ceiling in place:
Browning Hi-Power Magazine Block – solid model – section
The inner nut trap probably droops a bit without any support, but there’s no way to tell when it’s printed as one solid piece. That trap will hold the blob of steel-filled epoxy that secures the screw and helps prevent the block from turning, so it’s not really a nut trap and doesn’t require a precision fit. The vent tube from the top of the screw shaft gives the air and any excess epoxy an exit path.
Here’s a bottom view of two blocks, showing the support structures and the results:
Browning Hi-Power magazine – block support detail
I poked the tips of a snap ring pliers into the spider and twisted it out. The comb snaps off with fingernail pressure.
You could also print it without support by laying it flat, then glue the halves together with alignment pins. This is a bottom view:
Browning Hi-Power Magazine Block – solid model – split bottom
The OpenSCAD program has a handful of configuration settings that determine which of those blocks it produces, which components appear, and how it’s oriented.
Installed in a Browning magazine, the block looks like this:
Browning Hi-Power magazine – block in place
A detail of the bottom shows the notch capturing the spring tab:
Browning Hi-Power magazine – block detail
I think the top surface would benefit from a small bevel to ease the spring around the block, but that’s in the nature of fine tuning.
Not having heard back from my legislators yet, I still don’t know whether this counts as a readily reversible modification. I have my doubts, what with it being plastic and all, but we shall see.
The OpenSCAD source code:
// Browning Hi-Power Magazine Block
// Ed Nisley KE4ZNU December 2013
Layout = "Whole"; // Show Whole Split
// Show = section view for demo, not for building
// Whole = upright for steel or plastic
// Split = laid flat for plastic show-n-tell assembly
AlignPins = (Layout == "Split"); // pins only for plastic show-n-tell
Support = (Layout != "Split"); // no support for split
//- Extrusion parameters must match reality!
// Print with 2 shells and 3 solid layers
ThreadThick = 0.15;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.1; // make holes end cleanly
//----------------------
// Dimensions
Angle = 12.5; // from vertical
SpringID = 10.3; // magazine spring curvature (measure with drill shank)
SpringRadius = SpringID / 2;
Length = 24.0; // front-to-back perpendicular to magazine shaft
Height = 18.0; // bottom-to-top, parallel to magazine shaft
// 18 = 10 round capacity
RectLength = Length - SpringID; // block length between end radii
HornBaseOD = 8.0; // fits between follower pegs to prevent shortening
HornTipOD = 5.0;
HornAddTip = (HornTipOD/2)*tan(Angle);
HornAddBase = (HornBaseOD/2)*tan(Angle);
HornAddLength = HornAddTip + HornAddBase + 2*Protrusion;
HornLength = 12.0; // should recompute ODs, but *eh*
TrimHeight = 2.5; // vertical clearance for spring clip on base plate
// OEM = 2.5
// generic A = 2.5
TrimInset = 1.5; // ... horizontal
// OEM = 0.0
// generic A = 1.5
ScrewOD = 3.0 - 0.25; // screw hole dia - minimal thread engagement
ScrewLength = 11.0;
ScrewOffset = -1.5; // ... from centerline
// OEM = 0.0
// generic A = -1.5
NutOD = 5.6; // hex nut dia across flats
NutThick = 2.4; // ... then add 50% to trap for thread engagement & epoxy
NutOffset = 6.0; // ... base height from floor
VentDia = 2.0; // air vent from back of screw recess
PinOD = 1.72; // alignment pins
PinLength = 6.0;
PinInset = 0.6*SpringRadius; // from outside edges
echo(str("Alignment pin length: ",PinLength));
NumSides = 8*4; // default cylinder sides
Offset = 5.0/2; // from centerline for build layout
//----------------------
// Useful routines
function Delta(a,l) = l*tan(a); // incremental length due to angle
// Locating pin hole with glue recess
// Default length is two pin diameters on each side of the split
module LocatingPin(Dia=PinOD,Len=0.0) {
PinLen = (Len != 0.0) ? Len : (4*Dia);
translate([0,0,-ThreadThick])
PolyCyl((Dia + 2*ThreadWidth),2*ThreadThick,4);
translate([0,0,-2*ThreadThick])
PolyCyl((Dia + 1*ThreadWidth),4*ThreadThick,4);
translate([0,0,-(Len/2 + ThreadThick)])
PolyCyl(Dia,(Len + 2*ThreadThick),4);
}
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);
}
module ShowPegGrid(Space = 10.0,Size = 1.0) {
Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}
//----------------------
// The magazine block
module Block(SectionSelect = 0) {
CropHeight = Height*cos(Angle); // block height perpendicular to base
echo(str("Perpendicular height: ",CropHeight));
difference() {
union() {
intersection() {
rotate([Angle,0,0])
hull() {
for (i=[-1,1])
translate([0,i*RectLength/2,-((Length/2)*sin(Angle) + Protrusion)]) cylinder(r=SpringRadius,
h=(Height + 2*(Length/2)*sin(Angle) + 2*Protrusion),
$fn=NumSides);
}
translate([0,0,CropHeight/2])
cube([2*SpringID,3*Length,CropHeight],center=true);
}
translate([0,-Height*sin(Angle),Height*cos(Angle)])
resize([SpringID,0,0])
intersection() {
rotate([Angle,0,0])
translate([0,0,-(HornAddBase + Protrusion)])
cylinder(r1=HornBaseOD/2,
r2=HornTipOD/2,
h=(HornLength + HornAddLength + Protrusion),
$fn=NumSides);
cube([2*SpringID,Length,2*(HornLength*cos(Angle) + Protrusion)],center=true);
}
}
translate([0,ScrewOffset,-Protrusion]) // screw
rotate(180/6)
PolyCyl(ScrewOD,(ScrewLength + Protrusion),6);
translate([0,ScrewOffset,NutOffset]) // nut trap in center
rotate(180/6)
PolyCyl(NutOD,1.5*NutThick,6);
translate([0,ScrewOffset,-Protrusion]) // nut clearance at base
rotate(180/6)
PolyCyl(NutOD,(1.1*NutThick + Protrusion),6);
translate([SpringID/2,-((Length/2)/cos(Angle) - TrimInset),-Protrusion])
rotate(180)
cube([SpringID,2*TrimInset,(TrimHeight + Protrusion)],center=false);
if (AlignPins) // alignment pins
for (i=[-1,1])
rotate([Angle,0,0])
translate([0,
(i*((Length/2)*cos(Angle) - PinInset)),
(CropHeight/2 - i*2*PinInset)])
rotate([0,90,0]) rotate(45 - Angle)
LocatingPin(PinOD,PinLength);
translate([0,(ScrewOffset - NutOD),-Protrusion]) // air vent
rotate(180/8)
PolyCyl(VentDia,(ScrewLength + Protrusion),8);
translate([0,(ScrewOffset + VentDia/2),ScrewLength])
rotate([90,0,0]) rotate(180/8)
PolyCyl(VentDia,(NutOD + VentDia),8);
if (SectionSelect == 1)
translate([0*SpringID,-2*Length,-Protrusion])
cube([2*SpringID,4*Length,(Height + HornLength + 2*Protrusion)],center=false);
else if (SectionSelect == -1)
translate([-2*SpringID,-2*Length,-Protrusion])
cube([2*SpringID,4*Length,(Height + HornLength + 2*Protrusion)],center=false);
}
NumBars = floor((SpringID/2)/(5*ThreadWidth));
if (Support) { // add support structures
for (i = [-NumBars:NumBars])
translate([i*5*ThreadWidth,
-((Length/2)/cos(Angle) + TrimInset/2 + ThreadWidth),
(TrimHeight - ThreadThick)/2])
color("Yellow")
cube([(2*ThreadWidth),(3*TrimInset),(TrimHeight - ThreadThick)],center=true);
translate([-SpringID/2,-((Length/2)/cos(Angle) + 2*TrimInset + ThreadWidth),0])
color("Yellow")
cube([SpringID,(2*ThreadWidth),(TrimHeight - ThreadThick)],center=false);
translate([0,ScrewOffset,0])
for (j=[0:5]) {
rotate(30 + 360*j/6)
translate([(NutOD/2 - ThreadWidth)/2,0,(1.1*NutThick - ThreadThick)/2])
color("Yellow")
cube([(NutOD/2 - ThreadWidth),
(2*ThreadWidth),
(1.1*NutThick - ThreadThick)],
center=true);
}
}
}
//-------------------
// Build it...
ShowPegGrid();
if (Layout == "Show")
Block(1);
if (Layout == "Whole")
Block(0);
if (Layout == "Split") {
translate([(Offset + Length/2),Height/2,0])
rotate(90) rotate([0,-90,-Angle])
Block(-1);
translate([-(Offset + Length/2),Height/2,0])
rotate(-90) rotate([0,90,Angle])
Block(1);
}