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.

Tag: Improvements

Making the world a better place, one piece at a time

  • Even More Garish Kickstand Plate

    Fluorescent Red Kickstand Pad
    Fluorescent Red Kickstand Pad

    Having managed to mislay my dingy yellow kickstand plate, I made two more and this time hit ’em with fluorescent red paint. Ought to be unforgettable for another few years…

    In theory, you’re supposed to apply a white undercoat. I hosed ’em down with many drippy, runny coats of red and it’s all good. This ain’t art and they get thrown on the ground, so what’s the point of being fancy?

  • Lenovo Mini Wireless Keyboard: Readable Power Switch

    The backside of the Lenovo N5901 Mini Wireless Keyboard (which arrived with the aforementioned Q150) has a black-on-black power switch with ON and OFF legends (yes, I think they’re backwards, too) embossed in the matte black case: under anything less intense than enhanced interrogation lighting, you (well, I) can’t determine the switch position.

    Of course, the myriad certifications / ratings / labels required for compliance with all the regulations are perfectly legible:

    Lenovo Mini Keyboard - enhanced labels
    Lenovo Mini Keyboard – enhanced labels

    Working a dab of white correction fluid into the letters makes them blindingly obvious; the smudges around the letters will wear off in short order.

    I should probably add a bit of white to the switch background as well.

  • Drilling a Drainage Hole in a Plant Pot

    We divided an ancient Snake (a.k.a. Mother-In-Law’s Tongue) Plant and discovered the pot had no drainage hole, which is not to be tolerated.

    It turns out that an ordinary carbide glass drill works just fine on glazed clay pots. Use a low RPM and very slow feed, flood the scene with water, and drill from the other side after the point breaks through.

    Glass drill for plant pot hole
    Glass drill for plant pot hole

    The glaze inside the pot already had a flaw that let the water into the clay, from whence it seeped out through the unglazed lower rim. I suppose saturating the clay can’t possibly be good, but I’ve done this to many glazed pots over the years and none of them have ever complained, so it’s all good.

  • Helmet Mirror: Smaller Mirror Shaft

    This is the slightly smaller mount corresponding to the OpenSCAD code there for the two-section inspection mirror shaft, hot from the printer:

    Helmet mirror mount on build platform - smaller mirror shaft
    Helmet mirror mount on build platform – smaller mirror shaft

    It’s about the same as the previous version, despite trimming a few millimeters from the diameters and spacings:

    Helmet mirror mount size comparison
    Helmet mirror mount size comparison

    I’ll print the next one in a darker color. At least it’s not pink…

    The OpenSCAD source:

    // Helmet mirror mount
    // Ed Nisley KE4ZNU June 2011
    
    include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
    include </home/ed/Thing-O-Matic/lib/MCAD/boxes.scad>
    include </home/ed/Thing-O-Matic/lib/visibone_colors.scad>
    
    //-- Layout Control
    
    Layout = "Build";					// Build Fit Show None
    
    Examine = "None";				// AzMount ElMount ElBody ElPlate HelmetPlate None
    
    //-- Extrusion parameters
    
    ThreadThick = 0.33;
    ThreadWT = 2.0;
    ThreadWidth = ThreadThick * ThreadWT;
    
    HoleWindage = 0;			// enlarge hole dia by this amount
    
    //-- Useful sizes
    
    Tap2_56 = 0.070 * inch;
    Clear2_56 = 0.082 * inch;
    Head2_56 = 0.156 * inch;
    Head2_56Thick = 0.055 * inch;
    Nut2_56Dia = 0.204 * inch;
    Nut2_56Thick = 0.065 * inch;
    
    Tap3_48 = 0.079 * inch;
    Clear3_48 = 0.096 * inch;
    Head3_48 = 0.184 * inch;
    Head3_48Thick = 0.058 * inch;
    Nut3_48Dia = 0.201 * inch;
    Nut3_48Thick = 0.073 * inch;
    
    Tap4_40 = 0.089 * inch;
    Clear4_40 = 0.110 * inch;
    Head4_40 = 0.211 * inch;
    Head4_40Thick = 0.065 * inch;
    Nut4_40Dia = 0.228 * inch;
    Nut4_40Thick = 0.086 * inch;
    
    //-- Azimuth Mount
    
    AzMountDia = 12.0;
    AzMountLength = 14.0;
    
    AzFacets = 30;
    
    echo(str("Azmuth mount dia: ",AzMountDia," length: ",AzMountLength));
    
    //-- Mirror sizes
    
    MirrorShaftDia = 3.60;
    MirrorShaftOffset = -1.5;				// vertical offset from center of AzMountBody
    MirrorShoulderLen = 3*MirrorShaftDia;
    MirrorShoulderDia = min(AzMountDia,MirrorShaftDia + 6*ThreadWidth);
    
    MirrorStudDia = Tap3_48;
    MirrorStudLen = 2.0;
    
    //-- Elevation Mount / Body / Plate
    
    ElMountDia = AzMountDia;
    ElMountLength = 2.0 + ElMountDia;
    
    ElMountBase = 2.0;
    
    ElMountRounding = 2.0;
    
    ElMountFacets = AzFacets;
    
    ElBodyWidth = ElMountDia;
    ElBodyBlockLength = ElMountLength + AzMountLength/2 - MirrorShaftOffset;
    ElBodyThick = 8.0;
    
    echo(str("Elevation body overall: ",(ElBodyBlockLength + ElBodyWidth/2)," width: ",ElBodyWidth));
    
    ElPlateTall = ElBodyBlockLength + 0.70*ElBodyWidth;
    ElPlateWidth = 1.25 * ElPlateTall;
    ElPlateThick = Nut3_48Thick + 3*ThreadThick;
    
    ElPlatePlusX = ElPlateThick + (ElMountDia/2 + ElMountBase) + ElBodyThick;
    
    echo(str("Elevation plate tall: ",ElPlateTall," width: ",ElPlateWidth));
    
    ElArcRadius = (3/4) * ElBodyBlockLength;
    ElArcThick = 4*ThreadWidth;
    ElArcHeight = (1/2) * ElBodyThick;
    ElArcAngle = 35;
    ElArcFacets = 32;
    
    ElPlateFacets = 52;
    
    //-- Helmet Interface Plate
    
    HelmetCX = 60.0;
    HelmetMX = 4.0;
    HelmetRX = (pow(HelmetMX,2) + pow(HelmetCX,2)/4)/(2*HelmetMX);
    
    HelmetPlateC = max(ElPlateTall,ElPlateWidth);
    HelmetPlateTheta = atan(HelmetPlateC/HelmetRX);
    HelmetPlateM = 2*HelmetRX*pow(sin(HelmetPlateTheta/4),2);
    
    HelmetPlateThick = ThreadThick*(ceil(HelmetPlateM/ThreadThick) + 1);
    
    //-- Bearing Interfaces
    
    BearingWidth = 3*ThreadWidth;
    
    BearingOverlap = 3*ThreadThick;
    BearingClearance = 1*ThreadThick;
    
    BearingStudDia = min(AzMountDia,ElBodyWidth) - 2*BearingWidth;
    
    //-- Convenience values
    
    Protrusion = 0.1;		// make holes look good
    
    //----------------------
    // Useful routines
    
    module PolyCyl(Dia,Height) {			// based on nophead's polyholes
    
      Sides = ceil(Dia) + 2;
      FixDia = Dia / cos(180/Sides);
    
      cylinder(r=(FixDia + HoleWindage)/2,
               h=Height,
    	   $fn=Sides);
    }
    
    PegSize = 1.0;
    
    module ShowPegGrid(Size) {
    	for (x=[-5:5])
    	  for (y=[-5:5])
    		translate([x*10,y*10,Size/2])
    		  cube(Size,center=true);
    
    }
    
    //----------------------
    // Azimuth Mount
    
    module AzMount() {
    
      difference() {
    	union() {
    	  cylinder(r=AzMountDia/2,h=AzMountLength,$fn=AzFacets);		// body
    	  translate([0,0,AzMountLength/2 + MirrorShaftOffset])
    		rotate([-90,0,0])
    		  cylinder(r=MirrorShoulderDia/2,
    				   h=MirrorShoulderLen,$fn=AzFacets);				// mirror shaft shoulder
    
    	  if (Layout != "Fit")
    		for (y=[0:1])												// shoulder support
    		  translate([-AzMountDia/2,(4*y + AzMountDia/2 + ThreadWidth),0])
    			difference() {
    			  cube([AzMountDia,2*ThreadWidth,AzMountLength/6]);
    			  translate([AzMountDia/2,-Protrusion,AzMountLength/2 + MirrorShaftOffset])
    				rotate([-90,0,0])
    				  cylinder(r=MirrorShoulderDia/2,h=ThreadWidth + 2*Protrusion);
    			}
    	}
    
        translate([0,-Head3_48/2,AzMountLength/2 + MirrorShaftOffset])
          rotate([-90,0,0])
    		PolyCyl(MirrorShaftDia,(AzMountDia + MirrorShoulderLen));	// mirror shaft
    
        translate([0,-(Head3_48/2 - Protrusion),AzMountLength/2 + MirrorShaftOffset])
    	  rotate([90,0,0])
    		PolyCyl(MirrorStudDia,MirrorStudLen+Protrusion);			// mirror stud
    
        translate([0,0,
    	       Head3_48Thick - (AzMountLength - MirrorShaftDia)/2 + MirrorShaftOffset - Protrusion])
          PolyCyl(Head3_48,AzMountLength + Protrusion);					// mounting screw head
    
        translate([0,0,-Protrusion])
          cylinder(r=(Clear3_48 + HoleWindage)/2,
    	  h=(AzMountLength + 2*Protrusion),
    	  $fn=ceil(Clear3_48)+2);										// mounting screw clearance
    
    	translate([0,0,AzMountLength/2 + Head3_48Thick + MirrorShaftDia/2 + MirrorShaftOffset - Protrusion])
    	  cylinder(r1=(Head3_48/cos(180/7) + HoleWindage)/2,
    			   r2=Clear3_48/2,
    			   h=(3*ThreadThick + Protrusion),
    			   $fn=7);												// overhang support
    
        translate([0,0,AzMountLength/2 + MirrorShaftOffset])
          rotate([0,90,0])
    		PolyCyl(Tap2_56,AzMountDia/2 + Protrusion);					// setscrew hole
    
        translate([0,0,AzMountLength - (BearingOverlap + BearingClearance)])
    	  PolyCyl(BearingStudDia,
    			  BearingOverlap + BearingClearance + Protrusion);		// bearing surface
    
      }
    
    }
    
    //----------------------
    // Elevation Mount
    
    module ElMount() {
    
      difference() {
    
    	union() {
    
    	  translate([(ElMountDia/4 + ElMountBase/2),0,(ElMountLength/2 + BearingOverlap)])
    		rotate([0,90,0])
    		  cube([ElMountLength,ElMountDia,(ElMountDia/2 + ElMountBase)],
    			  center=true);											// mounting block
    
    	  translate([0,0,BearingOverlap]) {
    //		color([0.4,0.3,0.3,0.7])
    		cylinder(r=ElMountDia/2,
    				 h=ElMountLength - ElMountDia/2,
    				 $fn=ElMountFacets);								// cylinder to Az
    
    //		color([0.3,0.4,0.3,0.7])
    		translate([0,0,ElMountLength - ElMountDia/2]) {				// curved interface
    		  intersection() {
    			cylinder(r=ElMountDia/2,h=ElMountDia/2,$fn=ElMountFacets);
    			translate([0,ElMountDia/2,0])
    			  rotate([90,0,0])
    				cylinder(r=ElMountDia/2,h=ElMountDia,$fn=ElMountFacets);
    		  }
    		}
    
    	  }
    
    	  cylinder(r=(BearingStudDia - HoleWindage)/2,h=BearingOverlap);	// bearing stud
    	}
    
    	translate([0,0,-Protrusion])
    	  PolyCyl(Tap3_48,(3/4)*ElMountLength + BearingOverlap + Protrusion);	// AzMount screw
      }
    }
    
    //----------------------
    // Elevation Body
    
    module ElBody() {
    
      difference() {
    	union() {
    	  translate([-ElBodyBlockLength,-ElBodyWidth/2,0])
    		cube([ElBodyBlockLength,ElBodyWidth,ElBodyThick]);
    	  translate([0,0,ElBodyThick])
    		cylinder(r=(ElBodyWidth - 2*BearingWidth)/2,h=BearingOverlap);
    	  cylinder(r=ElBodyWidth/2,h=ElBodyThick,$fn=ElMountFacets);
    	}
    
    	PolyCyl(Clear3_48,ElBodyThick + BearingOverlap + Protrusion);
    
    	translate([0,0,-Protrusion])
    	  PolyCyl(Head3_48,Head3_48Thick);
    
    	translate([-ElArcRadius,0,ElBodyThick - ElArcHeight/2])
    	  rotate([0,-90,0])
    		PolyCyl(Tap2_56,ElBodyBlockLength - ElArcRadius + Protrusion);
    
    	translate([0,0,ElBodyThick - (ElArcHeight + BearingClearance)])
    	  difference() {
    		cylinder(r=ElArcRadius + (ElArcThick/2 + BearingClearance),
    				 h=ElArcHeight + BearingClearance + Protrusion,
    				 $fn=ElArcFacets);
    		cylinder(r=ElArcRadius - (ElArcThick/2 + BearingClearance),
    				 h=ElArcHeight + BearingClearance + Protrusion,
    				 $fn=ElArcFacets);
    	  }
    
      }
    
    }
    
    //----------------------
    // Elevation Plate
    
    module ElPlate() {
    
      union() {
    	difference() {
    	  translate([ElBodyWidth/2 - ElPlateTall/2,0,0])
    		scale([ElPlateTall,ElPlateWidth,1.0])
    		  cylinder(r=0.5,h=ElPlateThick,$fn=ElPlateFacets);
    	  translate([0,0,-Protrusion])
    		PolyCyl(Tap3_48,ElPlateThick + 2*Protrusion);
    	  translate([0,0,ElPlateThick - (BearingOverlap + BearingClearance)])
    		PolyCyl(BearingStudDia,(BearingOverlap + BearingClearance) + Protrusion);
    	  translate([0,0,-Protrusion])
    		cylinder(r=Nut3_48Dia/2,h=(1.1*Nut3_48Thick + Protrusion),$fn=6);
    	}
    
    	translate([0,0,ElPlateThick])
    	difference() {
    	  cylinder(r=ElArcRadius + ElArcThick/2,
    			   h=ElArcHeight,
    			   $fn=ElArcFacets);
    	  cylinder(r=ElArcRadius - ElArcThick/2,
    			   h=ElArcHeight + Protrusion,
    			   $fn=ElArcFacets);
    	  rotate([0,0,90 - ElArcAngle])
    	    translate([ElArcRadius + ElArcThick,0,ElArcHeight/2])
    		  cube([2*ElArcRadius + ElArcThick,
    				2*ElArcRadius + ElArcThick,
    				ElArcHeight + Protrusion],
    				center=true);
    	  rotate([0,0,-(90 - ElArcAngle)])
    	    translate([ElArcRadius + ElArcThick,0,ElArcHeight/2])
    		  cube([2*ElArcRadius + ElArcThick,
    				2*ElArcRadius + ElArcThick,
    				ElArcHeight + Protrusion],
    				center=true);
    	}
      }
    }
    
    //----------------------
    // Helmet Interface Plate
    
    module HelmetPlate() {
    
      difference() {
    	scale([ElPlateTall,ElPlateWidth,1.0])
    	  cylinder(r=0.5,h=HelmetPlateThick,$fn=ElPlateFacets);
    
    	translate([0,0,HelmetRX + HelmetPlateThick - HelmetPlateM])
    	  sphere(r=HelmetRX,$fn=256,$fs=0.1);
    
      }
    }
    
    //----------------------
    // Lash it together
    
    if (Examine == "AzMount")
      AzMount();
    
    if (Examine == "ElMount")
      ElMount();
    
    if (Examine == "ElBody")
      ElBody();
    
    if (Examine == "ElPlate")
      ElPlate();
    
    if (Examine == "HelmetPlate")
      HelmetPlate();
    
    if ((Layout == "Build" || Layout == "Show") && Examine == "None") {
      translate([-10,-20,0])
    	rotate([0,0,90])					// mis-align top fill from ElMount
    	  AzMount();
    
      translate([-10,20,ElMountLength + BearingOverlap])
    	rotate([0,180,-90])
    	  ElMount();
    
      translate([0,0,0])
    	rotate([0,0,0])
    	  ElBody();
    
      translate([10,15,0])
    	rotate([0,0,215])					// mis-align top fill from ElBody
    	  ElPlate();
    
      translate([20,-20,0])
    	rotate([0,0,-45])
    	  HelmetPlate();
    
      if (Layout == "Show")
    	ShowPegGrid(PegSize);
    
    }
    
    if ((Layout == "Fit") && Examine == "None") {
      translate([0,0,-(AzMountLength/2 + MirrorShaftOffset)])
    	color(MFG) AzMount();
    
      translate([0,0,AzMountLength/2 - MirrorShaftOffset - BearingOverlap])
    	color(DHC) ElMount();
    //	color([  0/255, 204/255, 204/255,0.5]) ElMount();
    
    	translate([ElMountDia/2 + ElMountBase,0,0])
    	  rotate([0,90,0])
    		color(DFC) ElBody();
    
    	translate([ElPlatePlusX,0,0])
    	  rotate([180,90,0])
    		color(LHC) ElPlate();
    
    	translate([ElPlatePlusX,0,ElPlateTall/2 - ElBodyWidth/2])
    	  rotate([0,90,0])
    		color(LWM) HelmetPlate();
    }
    
  • Lawn Mower Drive Control Lever Assist

    Our Craftsman lawn mower has both a deadman grip for the motor (the Operator Presence Control Bar) and a Drive Control Lever that engages the rear wheel drive. The latter requires a death grip to keep the belt engaged, which means you (well, I) spend about two hours clenching the grip.

    Lawn mower - compound leverage handle
    Lawn mower – compound leverage handle

    I’ve long since flipped the control to the left side and added thick foam padding, but there’s no adjustment that reduces the death-grip requirement: you can change the engagement distance, not the spring constant.

    Evidently the Sears engineers have much stronger hands than anyone in our family.

    The doodad hose-clamped to the upright part of the mower handle is a basically a hinge that applies force to the tip of the red handle. The hinge axis lies far enough from the handle’s pivot so that holding the hinge against the handle requires very little force; at least it’s no longer a death grip.

    Lawn mower - compound leverage handle engaged
    Lawn mower – compound leverage handle engaged

    It’s not an ideal solution, but it engages and (more importantly) disengages easily. I still don’t like mowing the lawn, but at least I don’t return with a crippled-up hand.

    The hinge is actually a lock hasp, so it has a slot that slides neatly over the Drive Control Lever’s tab. I beat both sides into a more-or-less cylindrical form over a piece of pipe, while miraculously not bending the hinge pin.

    Evidently the Sears engineers never actually used the damn mower for two hours at a time.

  • Thing-O-Matic: Fairing Clamp Plates

    Although those pink clamp plates worked well enough, they did not provide, shall we say, a completely satisfactory user experience. I reprinted new sets in red while varying the extruder speed by 0.1 rev/min, with small tweaks to the overlap between the infill and the loop threads.

    First, the big pictures with details scrawled on the back of the lower plate…

    At 3.2 rpm, which is only slightly too fast:

    Fairing Plate - 3.2 rpm
    Fairing Plate – 3.2 rpm

    At 3.3 rpm, a bit overstuffed:

    Fairing Plate - 3.3 rpm
    Fairing Plate – 3.3 rpm

    At 3.4 rpm, there’s obviously too much plastic:

    Fairing Plate - 3.4 rpm
    Fairing Plate – 3.4 rpm

    Some closeups, in the same order…

    At 3.2 rpm with 0.20 overlap, it looks OK:

    Fairing Plate - 3.2 rpm detail
    Fairing Plate – 3.2 rpm detail

    At 3.3 rpm with 0.25 overlap, which pretty much devours the inner loop thread:

    Fairing Plate - 3.3 rpm detail
    Fairing Plate – 3.3 rpm detail

    At 3.4 rpm with 0.25 overlap there’s serious overfill:

    Fairing Plate - 3.4 rpm detail
    Fairing Plate – 3.4 rpm detail

    In all cases, the extruder left a track while exiting upward from near the middle of the images. Even at 3. 2 rpm there’s slightly too much plastic.

    My ladies don’t care about the fine details. They prefer red to pink and the clamps hold the fairings firmly in place…

  • Thing-O-Matic: LED Lighting Upgrade

    Another one of those LED ring lights wound up in the Thing-O-Matic, affixed to the underside of the Z stage with double-sticky foam tape. You can see the whole ring reflected in that picture, but the front third of the ring obscured what the nozzle was doing.

    So I sawed out one of the three-LED strings to open a gap:

    LED ring light with gap
    LED ring light with gap

    Unfortunately, the designers arranged things so that the ballast resistor for each string sits directly above the last LED of the adjacent string. The white wire you can barely see connects the ballast resistor that drove the now-missing string on the left to the via feeding the first string on the right.

    It now fits around the extruder with the gap exactly matching the opening in front of the Thermal Core.

    LED ring light installed
    LED ring light installed

    Power comes from a screw terminal connector I hacked into the 4-pin block that used to be part of the 20+4-pin ATX power block at the Motherboard. There’s a length of overly stout 4-wire cable leading to a kludged not-a-connector made of square pins and heatshrink tubing jammed into the block.

    TOM auxiliary power connector
    TOM auxiliary power connector

    It provides +12, +5, +3.3 V, and ground for the fan and LED lighting.

    Most of the light in that last picture comes from LED strips on either side of the front opening. My Shop Assistant won a meter of warm-white LEDs at the 3rd Ward Make-a-Thon [Update: dead link. Try their pix from the event.] and graciously allowed me to chop off two 6-LED  strips for a good cause.