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: Home Ec

Things around the home & hearth

  • Engineering Book Costs

    Clearing off the shelves produced a book I haven’t opened in a loooong time:

    Vector Mechanics for Engineers - cover
    Vector Mechanics for Engineers – cover

    The price sticker shows that textbooks have always been expensive:

    Vector Mechanics for Engineers - price tag
    Vector Mechanics for Engineers – price tag

    The first line looks like a date and, indeed, I took “Principles of Mechanics” in Spring 1974, so that book would cost $88.08 in 2015 dollars, based on the official CPI calculator.

    It’s harder to figure college costs, but the old rule of thumb says it’s a factor of two higher than the CPI. A bit of successive approximation with a compound interest calculator suggests an annual inflation of 3.9% and 7.8% says the book would cost $403 today.

    Which, it turns out, isn’t all that much higher than what our Larval Engineer has been paying for the fatter textbooks in her engineering courses.

    Even using today’s worthless dollars, that’s still a chunk o’ change…

    Memo to Self: As the bumper sticker puts it, “If you think education is expensive, try ignorance.”

  • Silhouette Eyeglasses: Second Temple Repair

    As we expected, the remaining temple of Mary’s Silhouette glasses broke, a bit over a year from the previous repair, and this repair proceeded along the same lines as the previous fix.

    Cross-drill a brass tube for the teeny screws:

    Silhouette temple repair - cross-drilling brass tube
    Silhouette temple repair – cross-drilling brass tube

    I don’t recall having to do quite this much filing to make the screws fit, but they don’t call ’em “needle files” for nothin’:

    Silhouette temple repair - filing screw holes
    Silhouette temple repair – filing screw holes

    Trim the tube to the proper length by chucking it in the Sherline, rotating the spindle by hand, and filing a notch just below the jaws:

    Silhouette temple repair - trimming tube
    Silhouette temple repair – trimming tube

    Then file the end flat, countersink it just a bit, and ream out the hole to fit the broken end of the earpiece. This one didn’t quite fit the tubing, but we’re talking a few mils of tolerance on a bent piece of titanium. Rough up the end of the earpiece, degrease everything, and a few dabs of epoxy suffice for another Steampunk repair:

    Silhouette temple repair - finished
    Silhouette temple repair – finished

    The original fix continues to hold, but … this can’t go on.

     

  • Tour Easy Rear Fender Bracket

    I’d originally secured the rear fender to the steel strap connecting the chainstays on Mary’s Tour Easy with a cable tie: small, simple, light weight, reliable. Unfortunately, that put the end of the fender just slightly lower than the strap and, I fear, sprayed water all over the strap, where it worked its way through a paint flaw and rusted the steel under the paint. A simple metal clip would chew its way through the pain[t] on the strap, so, seeing as how we’re living in the future…

    The C-shaped block on the top grips the steel cross-strap, the trough fits the fender’s curve, the little spider supports the inside of the nut recess, and a pair of alignment pin holes (one visible) help during gluing:

    Tour Easy Rear Fender Bracket - solid model - show
    Tour Easy Rear Fender Bracket – solid model – show

    Although it’s tempting to 3D print both parts as a single unit, laying them out like this aligns the threads for best strength in each piece:

    Tour Easy Rear Fender Bracket - solid model - build
    Tour Easy Rear Fender Bracket – solid model – build

    Pressing the bracket on the glass slab (flat side up, nubblies on the bottom) with the clamps in place finished the job. The slightly crushed support spider from the nut recess sits in the foreground:

    Tour Easy rear fender bracket - gluing
    Tour Easy rear fender bracket – gluing

    Magenta PETG matches the red Tour Easy paint surprisingly well:

    Tour Easy - rear fender bracket - installed - top
    Tour Easy – rear fender bracket – installed – top

    From below, you can see why the top block can’t extend all the way to the bottom of the fender mount:

    Tour Easy rear fender bracket - installed
    Tour Easy rear fender bracket – installed

    That rubber boot needs replacing in the worst possible way, but I didn’t have anything suitable on hand and wouldn’t dismount that cable even if I had; cables never go back on properly.

    Alas, because the brakes weren’t mounted when I did the measurements, I had to build one to find out why a long block wouldn’t work:

    Tour Easy rear fender bracket - long back
    Tour Easy rear fender bracket – long back

    The screw atop the block (on the left in that picture) presses a small plastic slug against the steel strap, in the hopes it won’t chew through the paint quite as rapidly. The screws & nuts are stainless, so at least they’ll survive for a while.

    The curve in the trough comes from the chord equation applied to these crude measurements:

    Tour Easy Rear Fender Bracket - measurement doodle
    Tour Easy Rear Fender Bracket – measurement doodle

    Fortunately, it’s tucked into a spot where nobody ever looks…

    The OpenSCAD source code:

    // Tour Easy rear fender bracket
    // Ed Nisley KE4ZNU March 2015
    
    Layout = "Build";		// Build Show TabHolder Block
    
    //- 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
    
    PlateWidth = 45;		// Tour Easy frame plate
    PlateDepth = 17;
    PlateThick = 3.3;		//  ... allow for a bit of crud
    
    TabWidth = 32;			// fender tab
    TabLength = 40;
    TabThick = 1.5;
    TabDepth = 8;
    
    ChordM = TabDepth - TabThick;	// find fender tab's radius of curvature
    ChordC = TabWidth;
    
    TabRadius = ((ChordM * ChordM) + (ChordC * ChordC)/4) / (2 * ChordM);
    echo(str("Fender radius: ", TabRadius));
    
    FenderOffset = -25.0;		// from bottom of frame plate
    
    ScrewClear = 5.0;			// close enough to 10-32
    ScrewTap = ScrewClear - 1.0;
    
    NutThick = 3.1;				// 10-32 nut
    NutOD = 9.5;				//  ... across flats
    
    Chamfer = 5.0;					// edge chamfer
    
    BlockSlab = 10.0;
    BlockWidth = TabWidth;
    BlockDepth = PlateDepth + BlockSlab;
    BlockHeight = TabLength + PlateThick + BlockSlab;
    
    BlockOutline = [
    	[TabDepth/2,0],
    	[TabDepth/2,TabLength],
    	[PlateDepth,TabLength],
    	[PlateDepth,TabLength + PlateThick],
    	[0,TabLength + PlateThick],
    	[0,BlockHeight - Chamfer],
    	[Chamfer,BlockHeight],
    	[BlockDepth - Chamfer,BlockHeight],
    	[BlockDepth,BlockHeight - Chamfer],
    	[BlockDepth,TabLength - BlockSlab + Chamfer],
    	[BlockDepth - Chamfer,TabLength - BlockSlab],
    	[BlockSlab + Chamfer,TabLength - BlockSlab],
    	[BlockSlab,TabLength - BlockSlab - Chamfer],
    //	[BlockSlab,Chamfer],								// full-length tab (TrimBlock = false)
    //	[BlockSlab - Chamfer,0],							//   ""
    	[TabDepth/2,TabLength - BlockSlab - Chamfer]		// trim lower tab (TrimBlock = true)
    	];
    
    TrimBlock = true;
    
    BuildGap = 5.0;
    
    //----------------------
    // 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);
    }
    
    //- Locating pin hole with glue recess
    //  Default length is two pin diameters on each side of the split
    
    PinOD = 1.75;
    PinOC = TabLength / 2;
    
    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 LocatingPins(Length) {
    	for (i=[-1,1])
    	translate([i*PinOC/2,0,0])
    		rotate(180/4)
    		LocatingPin(Len=Length);
    }
    
    //----------------------
    // Pieces
    
    module TabHolder() {
    
    	difference() {
    		translate([-TabWidth/2,-TabLength,0])
    			cube([TabWidth,TabLength,2*TabDepth],center=false);
    
    		translate([0,-TabLength/4,0])
    			LocatingPins(5.0);
    
    if (!TrimBlock)
    		translate([0,-3*TabLength/4,0])
    			LocatingPins(5.0);
    
    		translate([0,FenderOffset,-Protrusion])
    			rotate(180/6)
    				PolyCyl(ScrewClear,3*TabDepth,6);
    
    if (TrimBlock)
    		translate([0,FenderOffset,-Protrusion])
    			rotate(180/6)
    				PolyCyl(NutOD,NutThick + Protrusion,6);
    
    		translate([0,TabLength,TabRadius + TabDepth/2])
    			rotate([90,0,0])
    				rotate(180/(6*4))
    					cylinder(r=TabRadius,h=3*TabLength,$fn=6*4);
    	}
    
    if (TrimBlock)
    	color("Yellow")
    	translate([0,FenderOffset,0])
    		for (Seg=[0:5]) {
    			rotate(30 + 360*Seg/6)
    			cube([NutOD/2,
    				2*ThreadWidth,
    				(NutThick - ThreadThick)],center=false);
    		}
    
    }
    
    module Block() {
    
    	difference() {
    		linear_extrude(height=BlockWidth,convexity=3)
    			polygon(points=BlockOutline);
    
    if (!TrimBlock)
    		translate([TabDepth/2,TabLength/4,BlockWidth/2])
    			rotate([0,90,0])
    				LocatingPins(5.0);
    
    		translate([TabDepth/2,3*TabLength/4,BlockWidth/2])
    			rotate([0,90,0])
    				LocatingPins(5.0);
    
    		translate([-BlockDepth,TabLength + FenderOffset,BlockWidth/2])
    			rotate([0,90,0])
    				rotate(180/6)
    					PolyCyl(ScrewClear,3*BlockDepth,6);
    
    		translate([PlateDepth/2,BlockHeight - BlockSlab - Protrusion,BlockWidth/2])
    			rotate([-90,0,0])
    					PolyCyl(ScrewTap,2*BlockSlab,6);
    
    if (!TrimBlock)
    		translate([(BlockSlab - NutThick),(TabLength + FenderOffset),BlockWidth/2])
    			rotate([0,90,0])
    				rotate(180/6)
    					PolyCyl(NutOD,NutThick + Protrusion,6);
    
    	}
    
    }
    
    //----------------------
    // Build it
    
    if (Layout == "TabHolder")
    	TabHolder();
    
    if (Layout == "Block")
    	Block();
    
    if (Layout == "Show") {
    	translate([0,BlockWidth/2,0])
    		rotate([90,0,0]) {
    			color("Magenta")
    				Block();
    			color("Orange")
    				translate([0,TabLength,TabWidth/2])
    					rotate([0,-90,0])
    						TabHolder();
    		}
    }
    
    if (Layout == "Build") {
    
    	translate([-BuildGap,0,0])
    		rotate(-90)
    			TabHolder();
    
    	translate([BuildGap,TrimBlock ? -BlockHeight/1.5 : -BlockHeight/3,0])
    		Block();
    }
    
  • Whirlpool Refrigerator Drawer Strut Re-Re-Repair

    Well, another year, another deep-cleaning session, another break in the strut holding up the drawers in the Whirlpool refrigerator:

    Whirlpool refrigerator drawer strut - clamped
    Whirlpool refrigerator drawer strut – clamped

    This time, there’s a fixture positioning the tab in the proper orientation while the solvent evaporates. The two bottom clamps hold an aluminum plate against the top (far side) of the strut, with the top-center clamp holding the tab against a steel block shimmed with cardboard to get the correct angle. The other two clamps squash the tab against the joint, which is well-soaked with IPS 4 adhesive.

    I replaced the right-side guide plate, originally made from phosphor bronze strip, with some thicker steel strip. The bronze strip collapsed into the worn section of the plastic bump that appeared in the previous post:

    Refrigerator strut - worn retainers
    Refrigerator strut – worn retainers

    I’ve written bigger caution messages on the top of the strut in red letters, but we think it’s getting on time for a whole new refrigerator…

  • Sienna Hood Rod Pivot: PETG Edition

    Our Larval Engineer reports that the PLA pivot for the Sienna’s hood rod didn’t survive contact with the van’s NYS Inspection. I’m not surprised, as PLA tends to be brittle and the inspection happened on a typical February day in upstate New York. Seeing as how PETG claims to be stronger and more durable than PLA, I ran off some replacements:

    Toyota Sienna hood rod pivot - small - PETG
    Toyota Sienna hood rod pivot – small – PETG

    The square cap fit snugly over the bottom of the post; PETG tolerances seem pretty much the same as for PLA.

    A slightly larger loop may be more durable, so I changed one parameter in the OpenSCAD code to get this:

    Toyota Sienna Hood Rod Pivot - up-armored - solid model
    Toyota Sienna Hood Rod Pivot – up-armored – solid model

    Which printed just like you’d expect:

    Toyota Sienna hood rod pivot - large - PETG hairs
    Toyota Sienna hood rod pivot – large – PETG hairs

    Despite the hairs stretching between each part, the nozzle didn’t deposit any boogers during the print. The top and bottom use Hilbert Curve infill, which looks pretty and keeps the nozzle from zipping back and forth quite so much; perhaps that’s a step in the right direction.

    Tapping the holes for 6-32 stainless machines screws went easily enough:

    Toyota Sienna hood rod pivot - PETG - assembled
    Toyota Sienna hood rod pivot – PETG – assembled

    She gets one of each and I keep the others for show-n-tell sessions.

    The OpenSCAD source code, which differs from the original by a constant or two:

    // Sienna Hood Rod Pivot
    // Ed Nisley KE4ZNU November 2013
    
    //- 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
    
    inch = 25.4;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //----------------------
    // Dimensions
    
    ShellOD = 20.0;
    ShellID = 8.75;
    ShellLength = 10.0;
    
    TaperLength = 1.5;
    TaperID = 11.4;
    
    BaseWidth = 20.0;
    BaseThick = 3.0;
    
    PegSide = 9.5;					// mounting peg through sheet metal
    PegLength = 7.0;
    PegCornerTrim = 0.75;
    PegHoleOD = 0.107*inch;			//  6-32 tap hole
    
    PegTrimSide = sqrt(2)*PegSide - PegCornerTrim;
    
    ClampWall = 3.0;				// clamping cap under sheet metal
    ClampHoleOD = 0.150*inch;		//  6-32 clearance hole
    ClampCap = 3.0;					// solid end thickness
    
    PanelThick = 2.0;				// sheet metal under hood
    
    NumSides = 6*4;
    
    //----------------------
    // 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();
    
    // pivot
    
    translate([-ShellOD,0,0])
    	difference() {
    		union() {
    			cylinder(r=ShellOD/2,h=ShellLength,$fn=NumSides);		// housing
    			translate([-ShellOD/2,0,0])								// filler
    				cube([ShellOD,(ShellOD/2 + BaseThick),ShellLength],center=false);
    			translate([0,(ShellOD/2 + BaseThick/2),ShellLength/2])	// foot
    				cube([BaseWidth,BaseThick,ShellLength],center=true);
    
    			translate([0,											// peg
    						(ShellOD/2 + PegLength/2 + BaseThick - Protrusion),
    						PegSide/2])
    				intersection() {
    					cube([PegSide,(PegLength + Protrusion),PegSide],center=true);
    					rotate([0,45,0])
    						cube([PegTrimSide,2*PegLength,PegTrimSide],center=true);
    				}
    		}
    
    		PolyCyl(ShellID,ShellLength,NumSides);		// central hole
    
    		translate([0,0,-Protrusion])				// end bevels
    			cylinder(r1=TaperID/2,r2=ShellID/2,h=(TaperLength + Protrusion),$fn=NumSides);
    		translate([0,0,(ShellLength + Protrusion)])
    			rotate([180,0,0])
    				cylinder(r1=TaperID/2,r2=ShellID/2,h=(TaperLength + Protrusion),$fn=NumSides);
    
    		translate([0,0,PegSide/2])					// screw tap hole
    			rotate([-90,0,0])
    				PolyCyl(PegHoleOD,(ShellOD + BaseThick + PegLength),6);
    
    	}
    
    // anchor cap
    
    translate([2*PegSide,0,0])
    	difference() {
    		translate([0,0,(PegLength + ClampCap)/2])					// overall shape
    			cube([(PegSide + ClampWall),(PegSide + ClampWall),(PegLength + ClampCap)],center=true);
    		translate([0,0,(PegLength/2 + ClampCap + Protrusion)])		// peg cutout
    			cube([(PegSide + ThreadWidth),(PegSide + ThreadWidth),(PegLength + Protrusion)],center=true);
    		translate([0,0,-Protrusion])								// screw clearance
    				PolyCyl(ClampHoleOD,2*PegLength,6);
    	}
    
  • Detergent Cap Holder

    Although chain mail provides a good test of the M2’s setup and slicing parameters, it doesn’t offer much in the way of infill. To test that, I designed a holder for the cap of the bulk laundry detergent container:

    Detergent Cap Holder - in place
    Detergent Cap Holder – in place

    The container must rest on its side, but if you snap the cap back in place, detergent will ooze out between the cap and the container and drip on whatever’s below. The never-sufficiently-to-be-damned Whirlpool high-efficiency front loading washer vibrates like crazy during the spin cycle, shaking anything from its top to the floor. The cap must sit in a cup to catch the inevitable ooze down its side, the wire shelf already has a bunch of other crap on it, and I needed a bulky test object, soooo ….

    We regard that detergent container and its cap as a botched design.

    Anyhow.

    The holder has pair of holes in its back surface for the copper (!) hangers:

    Detergent Cap Holder - solid model - rear
    Detergent Cap Holder – solid model – rear

    I stripped a length of 10 AWG wire, straightened & annealed it, bent up a pair of hooks, then hammered them just flat enough to work-harden the copper, and they were all good.

    Printing that massive block with 20% infill showed that the nozzle collected enough PETG during the first few layers to leave a substantial booger behind:

    Detergent cup holder - oxidized PETG
    Detergent cup holder – oxidized PETG

    Fortunately, that was the only one and it ended up on the inside, tucked out of sight.

    The PETG deposit on the outside of the nozzle gradually darkens from the original magenta to brown, which I’m pretty sure means that it’s oxidizing / decomposing / going bad. There’s no obvious way to remove the booger during the print; I’ve taken to wiping the nozzle after each object, while it’s still hot and the PETG remains flexible.

    Because the nozzle didn’t accumulate any more PETG during the rest of the print, it’s not a constant problem, but I have seen boogers several times so far.

    Perhaps continued refinement of the slicing parameters will help? One can always hope…

    The OpenSCAD source code:

    // Detergent Cap Holder
    // Ed Nisley KE4ZNU - March 2015
    
    Layout = "Show";			// Show Build
    
    //-------
    //- Extrusion parameters must match reality!
    
    ThreadThick = 0.20;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.2;
    
    Protrusion = 0.1; 				// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Dimensions
    
    RecessX = 45.0;								// cap recess
    RecessDia = 55.0;
    RecessDepth = 10.0;
    RecessSides = 16*4;
    
    BaseThick = 5.0;							// block thickness below cap
    
    PinDia = 2.5;
    PinLength = 20.0;
    PinOC = 65.0;
    PinInset = 7.0;
    PinZ = BaseThick;
    
    Block = [RecessX,PinOC + 2*PinInset,30.0];	// overall block size (X to cap center)
    
    FairingRadius = Block[2] - RecessDepth - BaseThick;
    
    //-------
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      RangeX = floor(95 / Space);
      RangeY = floor(125 / Space);
    
    	for (x=[-RangeX:RangeX])
    	  for (y=[-RangeY:RangeY])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    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 Holder() {
    	difference() {
    		union() {									// main shape
    			translate([-Block[0]/2,0,Block[2]/2])
    			cube(Block,center=true);
    			cylinder(d=Block[1],h=Block[2],$fn=RecessSides);
    		}
    		for (j=[-1,1])								// mounting pin holes
    			translate([-(Block[0] + Protrusion),j*PinOC/2,PinZ])
    				rotate([0,90,0]) rotate(180/6)
    					PolyCyl(PinDia,PinLength + Protrusion,6);
    		translate([0,0,Block[2]])					// fairing arc
    			rotate([90,0,0])
    				cylinder(r=FairingRadius,h=2*Block[1],center=true);
    		translate([Block[0]/2,0,Block[2]/2 + RecessDepth + BaseThick])	// flat top
    			scale([1,2,1])
    				cube(Block,center=true);
    		translate([0,0,BaseThick])
    			cylinder(d1=RecessDia,d2=1.1*RecessDia,h=Block[2]);
    	}
    }
    
    //-------
    // Build it!
    
    //ShowPegGrid();
    
    if (Layout == "Show") {
    	Holder();
    }
    
    if (Layout == "Build") {
    	translate([0,0,0])
    	rotate([0,0,0])
    	Holder();
    }
    
  • LED Bulb in High-Vibration Environment

    The garage door opener just ate another rough-duty bulb, so let’s see how a $7 LED bulb fares:

    Walmart 60 W LED Bulb - garage door opener
    Walmart 60 W LED Bulb – garage door opener

    It has no external heatsink fins and the color temperature looks just like the old-school incandescent bulb it’s replacing, so they’re getting a clue about what’s acceptable to ordinary folks.

    That’s equivalent to a 60 W incandescent bulb, too, at least according to the package:

    Walmart 60 W LED Bulb - package data
    Walmart 60 W LED Bulb – package data

    I love the “Return the package and reciept for replacement or money back” part…