The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Machine Shop

Mechanical widgetry

  • 2000 Toyota Sienna: Short Battery Adapter

    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
    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…

  • Microsoft Comfort Curve Keyboard Cleaning Redux

    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:

    Microsoft Comfort Curve Keyboard - crud buildup
    Microsoft Comfort Curve Keyboard – crud buildup

    Obviously, I got nasty habits

    Microsoft Comfort Curve Keyboard - crud detail
    Microsoft Comfort Curve Keyboard – crud detail

    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.

    Elite Keyboards

    I want one too.

    They look good to me, too, although I hope the weird Esc key is optional…

  • Water Heater Anode Rod – One Year Check

    A one-year-old magnesium rod looks pretty good, all things considered:

    Water Heater Anode Rod - one year
    Water Heater Anode Rod – one year

    The previous one was still working after seven years, although I had to wreck it to get it out…

  • Browning Hi-Power Magazine Capacity Reduction Block

    Based on tweaking the measurements from the nut trap block trial, this block attaches to the inner floor plate of the magazine and reduces the magazine’s capacity to 10 rounds:

    Browning Hi-Power Magazine Block - solid model - whole
    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
    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
    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
    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
    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
    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);
    }
    
  • Sherline Four-Jaw Chuck Speed Wrenches: 3D Printed Edition

    A Home Shop Machinist article (A Speed Key for Your Four-Jaw Chuck, p 67 Nov-Dec 2013, David Morrow) showed some lovely knurled steel knobs. These 3D printed knobs aren’t nearly as pretty, but they do much the same thing:

    Sherline Knobs - in 4 jaw chuck
    Sherline Knobs – in 4 jaw chuck

    The solid model resembles the illegitimate offspring of a wine bottle and a pineapple:

    Sherline Knob - solid model
    Sherline Knob – solid model

    The knurling comes from aubenc’s Knurled Surface Library v2. I ran off a prototype (on the left), then tweaked the dimensions to get the final version on the right:

    Sherline Knobs - knurl depth variation
    Sherline Knobs – knurl depth variation

    Being that type of guy, I define the knurl in terms of its diametral pitch, compute the diamond width & length to fit in the available space, then hand those measurements to the knurling library… which recomputes everything and decides on one less diamond than I do: NumSides has a Finagle Constant of -1 to make the answer come out right. We may be using a different diameter or something, but I haven’t deciphered the source code. It’s parametric out the wazoo, as usual, so you can spin up what you like, how you like it.

    Anyhow, a 24 DP knurl with 1.0 mm depth looks and feels pretty good; the XY resolution isn’t good enough for a 48 DP knurl around that knob diameter. The diamonds don’t come out as crisp and pointy as crushed steel knurls, but they’re OK for my fingers.

    Doing half a dozen doesn’t take much longer than doing a few, because there’s a 20 second minimum layer time in effect and those things don’t have much plastic, so now I have one for the hold-down clamps and another for Show-n-Tell sessions:

    Sherline Knobs - M2 platform
    Sherline Knobs – M2 platform

    I chopped a 5/32 inch hex key into five 15 mm lengths with a Dremel cutoff wheel, then filed both ends flat and broke the edges. The hex stubs were a press fit in the hex holes, so I finger-started them, grabbed the hex in the drill press, aligned the handle below, and rammed the stub about 5 mm deep. The final depth comes from jamming the wrench into the chuck and pressing firmly, so the stubs project exactly as far as possible:

    Sherline Knobs - hex key inserted
    Sherline Knobs – hex key inserted

    One might quibble about the infill on the end; one may go adjust one’s own printer as one prefers.

    There’s 0.1 mm more HoleWindage than usual, because these holes must fix a hex shaft, not a circular pin, and the corners need some clearance. They came out a firm press fit: exactly what’s needed.

    They’re no good for final tightening of those chuck jaws, but that’s not their purpose…

    The OpenSCAD source code:

    // Knurled handles for Sherline hex keys
    // Ed Nisley - KE4ZNU - November 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.3;			// extra clearance to improve hex socket fit
    
    Protrusion = 0.1;			// make holes end cleanly
    
    PI = 3.14159265358979;
    inch = 25.4;
    
    //----------------------
    // Dimensions
    
    ShaftDia = 10.5;				// un-knurled section diameter
    ShaftLength = 15.0;				//  ... length
    
    SocketDia = (5/32) * inch;		// hex key size
    SocketDepth = 10.0;
    
    KnurlLen = 20.0;				// length of knurled section
    KnurlDia = 15.0;				//   ... diameter
    KnurlDPNom = 24;				// Nominal diametral pitch = (# diamonds) / (OD inches)
    
    DiamondDepth = 1.0;				//   ... 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);
    }
    

    This might be a good stocking stuffer for that guy who has everything, but you’d need his shop to make it, so what’s the point in that?

  • Browning Hi-Power Magazine: Nut Trap Block Trial

    The general idea is to reduce the capacity of a 13 round Browning Hi-Power magazine to 10 rounds, in compliance with the NY Safe Act, using a number of possibly invalid assumptions. The new Firearms tag will produce earlier posts.

    This early prototype tried out the sizes, shapes, and angles, using an M3x0.5 socket head cap screw:

    Browning Hi-Power Magazine Block - solid model - nut trap prototype
    Browning Hi-Power Magazine Block – solid model – nut trap prototype

    The bottom nut trap locates the block on the inner floor plate by capturing the nut. It might need a bit more clearance or a chamfer to allow for brazing material around the nut flats; cleaning up the brazed nut with a file might also help.

    The central trap holds a nut that anchors the block; the trap must be about 50% longer than the nut to allow for thread alignment, because the central hole is a loose tap fit.

    That central nut probably isn’t needed, because you’d fill the central shaft with metal-loaded epoxy, which would form a perfectly serviceable, exactly form-fitting, and utterly non-removable “nut”. The vent from the end of the screw shaft releases air trapped behind the epoxy by the screw; if you don’t have a vent, then air pressure will force the epoxy out of the cavity.

    If the epoxy “nut” is workable, then you can build it in a single piece printed vertically on the platform. Having a split version makes it easier to show off and, in truth, the cemented joint is about as strong as the rest of the object.

    Hot off the M2 3D printer, it looks like this:

    BHP magazine block - prototype nut trap - bare
    BHP magazine block – prototype nut trap – bare

    A few threads droop into the air vent, so that channel should be larger. The overall plastic block may be porous enough to release the air pressure even without a vent.

    With locating pins glued in place and a nut in the central trap:

    BHP magazine block - prototype nut trap
    BHP magazine block – prototype nut trap

    Pretty much as I expected, it doesn’t quite fit in the magazine, because it doesn’t have clearance for the little tab on the inner floor plate that captures the spring.

    One might argue that a plastic block isn’t “permanent”, but it’s definitely not “readily” removed:

    • PLA doesn’t dissolve in common solvents
    • It doesn’t actually melt and flow away at high temperatures
    • It’s protected by the spring and inner floor plate
    • It’s certainly strong enough to resist simple mechanical attacks

    This is a start…

    The OpenSCAD source code, replete with inadequacies:

    // Browning Hi-Power Magazine Plug
    // Ed Nisley KE4ZNU November 2013
    
    Layout = "Show";			// Show Whole Pin Build
    
    CrossSection = 1;			// -1, 0, 1 to select section side or none
    
    Section = (Layout == "Build") ? 1 : CrossSection;		// for cross-section for 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
    
    Angle = 12.5;				// from vertical
    
    EndDia = 10.3;				// an 11/32 inch drill fits
    EndRadius = EndDia / 2;
    
    Length = 24.0;				// front-to-back perpendicular to magazine shaft
    Height = 14.0;				// bottom-to-top, parallel to magazine shaft
    							//  14 = 10 round capacity
    							//  28 = 7 round
    
    RectLength = Length - EndDia;	// block length between end radii
    
    ScrewOD = 3.0 - 0.5;		// bottom screw tapping diameter
    ScrewLength = 11.0;
    ScrewOffset = 0;			//   ... from centerline
    
    NutOD = 5.5;				// hex nut dia across flats
    NutThick = 2.4;				//  ... then add 50% for thread engagement & epoxy
    NutOffset = 6.0;			//  ... base height from floor
    
    VentWidth = 2*ThreadWidth;	// air vent from back of screw recess
    VentDepth = 4*ThreadThick;
    
    NumSides = 8*4;				// default cylinder sides
    
    PinOD = 1.72;				// alignment pins
    PinLength = 6.0;
    PinInset = 0.9*EndRadius;	// from outside edges
    echo(str("Alignment pin length: ",PinLength));
    
    Offset = 5.0/2;				// from centerline for build layout
    
    //----------------------
    // Useful routines
    
    // 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);
    
    }
    
    //----------------------
    // Components
    
    module Block(SectionSelect = 0) {
    
    Delta = tan(Angle)*(Length/2);				// incremental length due to angle
    
    CropHeight = Height*cos(Angle);				// block height perpendicular to base
    
    echo(str("Perpendicular height: ",CropHeight));
    
    	difference() {
    		intersection() {
    			rotate([Angle,0,0])
    				difference() {
    					translate([0,0,-Height/2])
    						linear_extrude(height=2*Height,convexity=2) {
    							for (i=[-1,1])
    								translate([0,(i*RectLength/2),0])
    									rotate(180/NumSides)
    										circle(r=EndRadius/cos(180/NumSides),
    												$fn=NumSides);
    							square([EndDia,RectLength],center=true);
    						}
    					for (i=[-1,1])
    						translate([0,
    									(i*(Length/2 - PinInset)),
    									(CropHeight/2 + i*(CropHeight/2 - PinInset))])
    							rotate([0,90,0]) rotate(45-Angle)
    								LocatingPin(PinOD,PinLength);
    				}
    			translate([0,0,CropHeight/2])
    				cube([2*EndDia,3*Length,CropHeight],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([0,-(ScrewOffset + NutOD),(ScrewLength - Protrusion)/2])	// air vent
    			cube([VentDepth/2,VentWidth,(ScrewLength + Protrusion)],center=true);
    		translate([0,(ScrewOffset - NutOD/2),(ScrewLength - VentWidth/2)])
    			cube([VentDepth/2,NutOD,VentWidth],center=true);
    
    		if (SectionSelect == 1)
    			translate([EndDia,0,Height/2-Protrusion])
    				cube([2*EndDia,3*Length,Height+2*Protrusion],center=true);
    		else if (SectionSelect == -1)
    			translate([-EndDia,0,Height/2-Protrusion])
    				cube([2*EndDia,3*Length,Height+2*Protrusion],center=true);
    	}
    
    }
    
    //-------------------
    // Build it...
    
    ShowPegGrid();
    
    if (Layout == "Pin")
    	LocatingPin(PinOD,PinLength);
    
    if (Layout == "Show")
    	Block(CrossSection);
    
    if (Layout == "Whole")
    	Block(0);
    
    if (Layout ==  "Build") {
    	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);
    }
    
  • Samsung Quiet Jet Vacuum: Improved Floor Brush Strips

    Those simple floor brush strips for the Samsung vacuum cleaner worked moderately well, but the urethane adhesive didn’t have enough grip on the plastic strips. Having just run out of that batch, I made up another set with slightly undercut holes:

    Bushing Solid Model - better holes - bottom
    Bushing Solid Model – better holes – bottom

    That’s half a thread width on each side, just enough to give the adhesive something to grab. Such is the plan, anyway.

    I taped the strips to a pair of credit cards (actually, flat cards without embossed characters), slathered a thin layer of urethane atop them, and laid on squares of the same wool fabric I used the last time:

    Samsung vacuum floor strips - gluing
    Samsung vacuum floor strips – gluing

    Then I piled a steel block atop an aluminum slab on both arrays, fast forwarded a day, peeled and flexed and cut the strips apart:

    Samsung floor brushes - glued
    Samsung floor brushes – glued

    The urethane foamed through the holes as I hoped and (seems to have) locked the fabric in place, at least well enough to withstand some experimental bending on the workbench.

    Now, to see how they stand up to actual use…

    The OpenSCAD source code:

    // Samsung Vacuum cleaner nozzle floor strips
    // Ed Nisley KE4ZNU January 2013
    //  November 2013 - adapt to M2, enlarge holes
    
    Layout = "Build";			// Show, Build
    
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 0.4;
    
    HoleWindage = 0.75;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;           // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    Body = [6.0,59.0,3*ThreadThick];	// width, length, thick
    
    Tab1 = [4.5,5.0,0.0];				// width, length, offset from centerline
    Tab2 = [3.5,5.0,0.5];
    
    HoleOC = 8.0;						// adhesive anchoring holes
    HoleDia = 2.0;
    HoleSides = 4;
    HoleMax = floor(Body[1]/(2*HoleOC));
    
    echo("HoleMax: ",HoleMax);
    
    //----------------------
    // 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);
    
    }
    
    module BackingStrip() {
    
    	difference() {
    		union() {
    			translate([0,0,Body[2]/2])
    			cube(Body,center=true);
    			translate([Tab1[2],-1*Body[1]/2,Body[2]/2])
    			cube([Tab1[0],2*Tab1[1],Body[2]],center=true);
    			translate([Tab2[2],+1*Body[1]/2,Body[2]/2])
    			cube([Tab2[0],2*Tab2[1],Body[2]],center=true);
    		}
    		for (i = [-HoleMax:HoleMax])
    			translate([0,i*HoleOC,-Protrusion])
    			rotate(45) {
    				PolyCyl(HoleDia,(Body[2] + 2*Protrusion),HoleSides);
    				PolyCyl((HoleDia + ThreadWidth),(ThreadThick + Protrusion),HoleSides);
    			}
    	}
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Show")
    	BackingStrip();
    
    if (Layout == "Build")
    	rotate(90) BackingStrip();