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.

Month: January 2014

  • FC1002 Frequency Counter Faceplate Repair

    The plastic faceplate over the display cracked quite a while ago:

    FC1002 Frequency Counter - cracked plastic
    FC1002 Frequency Counter – cracked plastic

    I don’t recall dropping the poor thing. Given the interesting pattern, it could be inherent stress that finally let loose as the plastic aged.

    While I have it apart to rebuild the battery pack (more on that later), I’ve been easing acetone/MEK into those cracks by capillary attraction in the hopes of dissolving just enough plastic to rejoin them, without slobbering solvent all over the faceplate and scarring it.

    If all else fails, I suppose I can mill out a replacement from thin acrylic sheet, but those nicely rounded cast / molded edges lie well beyond my abilities…

  • MHV LUG Lightning Talk: Intro to NSA Hardware Implants

    Meme - Nixon - I see what you did there - 5x38k
    Meme – Nixon – I see what you did there – 5x38k

    I did five minutes of standup comedy at yesterday’s MHV Lug meeting, pointing out some of the more interesting ways to compromise a PC when you have an infinite budget for development and consumables.

    You don’t get my patter with the PDF (unless you had access to the room’s bugging hardware), but the links may come in handy in the unlikely event you haven’t been following the story closely.

    If you have a security clearance or are in line for one, you probably shouldn’t click on the link, because it contains copies of pages from the leaked NSA catalog:

    I See What You Did There – NSA Hardware Guide

  • Water Cooled Stepper Motors: Flow Calculation

    A discussion on the Makergear Google Group about a heated enclosure prompted me to run the numbers for cooling stepper motors with water, rather than fans and finned heatsinks.

    The general idea comes from my measurements of the air-cooled heatsink stuck to a stepper’s end cap. The metal-to-metal conductivity works surprisingly well and reduces the case temperature to slightly over ambient with decent airflow through the heatsink; epoxying a cold plate to the end cap should work just as well. A NEMA 17 stepper case is 42.3 mm square, so a standard 40 mm square CPU cooling plate will fit almost exactly.

    The question then becomes: how much water flow do you need to keep the motors cool?

    Some numbers:

    • Water’s heat capacity is 4.2 J/g·K
    • 1 J = 1 W·s, 1 W = 1 J/s
    • NEMA 17 motors dissipate about 5 W (13 W if you’re abusing them)
    • We’ll cool all four motors in parallel, for a total of 20 W
    • Allow a 5 K = 5 °C temperature rise in each cold plate

    Rub them all together:

    (20 J/s) / (5 K * (4.2 J/g·K)) = 0.95 g/s

    For water, 1 g = 1 cc, so the total flow is 1 cc/s = 3600 cc/h = 3.6 liter/h, which, here in the US, works out to a scant 1 gallon/hour. It’s tough getting a pump that small and cheap flowmeters run around 0.5 liter/m…

    If you don’t want a pump. put an aquarium up on a (sturdy) shelf and drain it through the cold plates. A cubic foot of water, all eight gallons and sixty-some-odd pounds of it, will last 8 hours, which should be enough for most printing projects.

    If you want reliability, drain the coolers into a sump with a float switch (high = on), put another float switch (high = off) on the aquarium, and have the pump top up the aquarium. If the pump fails, your steppers stay cool for the next 8 hours. Heating the water about 5 °C during 8 hours won’t require active cooling.

    Now, managing the hoses leading to the X axis stepper may be challenging, but a cable drag chain would control the rest of the wiring, too.

  • Santa Ride: Crash Report

    While walking from the Metropolitan Museum of Art to Grand Central on a frigid post-Christmas December evening, we encountered this storefront display:

    Santa Ride - car
    Santa Ride – car

    A closer look at the monitor in the background:

    Santa Ride - crash report
    Santa Ride – crash report

    Hmmm. Bit of a surprise: not a Windows box.

    After walking two miles along Madison Avenue, I didn’t see one single item in the store windows that I’d buy, even in the after-Christmas discount season. Mary wasn’t enthralled by a pair of diamond-encrusted emerald earrings the size of my thumbs, either, which is likely a Good Thing.

    We stopped in the Ugg Boot Store, both to warm up and  so I’d know what all the spammers have been hawking…

  • Browning Hi-Power Magazine Capacity Reduction Block: Steel Version

    The Shapeways stainless steel process produces nice results:

    Browning HP Mag Blocks - stainless and plastic - side
    Browning HP Mag Blocks – stainless and plastic – side

    It’s actually bronze-infused stainless steel powder, so it’s not exactly solid steel. The parts spend a day rattling around in a vibratory polisher that slightly rounds off their edges and smooths the surface, but (as with all 3D printed objects) you must learn to love the results; it’s certainly more photogenic than the black plastic version from my M2.

    The bottom view shows the hole I added to reduce the metallic volume; they charge a bit under $0.01/mm3, which encourages airy design:

    Browning HP Mag Blocks - stainless and plastic - bottom
    Browning HP Mag Blocks – stainless and plastic – bottom

    A cross-section view of the solid model shows the interior structure:

    Browning Hi-Power Magazine Block - steel - solid model - section
    Browning Hi-Power Magazine Block – steel – solid model – section

    The vent pipes are somewhat larger than in the plastic version and, obviously, I didn’t include the yellow support structures in the model I sent to Shapeways.

    Their specs give a minimum wall thickness of 3.0 mm, which I’m definitely pushing on some of the internal features. The pipes came out perfectly, as nearly as I can tell, although some polishing media did get wedged in the smaller hole. Air passes freely across the top, which is the important part.

    Although the specs list a ±2 mm (!) tolerance, a comment in a Shapeways forum said that applies to larger objects, with 0.2 mm being typical for smaller objects. The steel and plastic parts match within 0.2 mm of the nominal model dimensions, so that lower tolerance seems about right; I have no idea how consistent it is.

    Another comment recommended carbide tools for secondary operations and that’s definitely true; I wrecked a perfectly good HSS tap trying to thread the central hole. Fortunately, I made the block slightly smaller outside and slightly larger inside, specifically to avoid having a deep thread; I intend to ram a standard M3x0.5 SHCS into that hole and epoxy it in place without worrying about thread damage.

    A trial fit shows it captures the spring tab just like the plastic version did:

    Browning Hi-Power magazine - steel block trial fit
    Browning Hi-Power magazine – steel block trial fit

    I must contact my legislators again, as I’m pretty sure they’re not going to contact me.

    The OpenSCAD source code:

    // Browning Hi-Power Magazine Plug
    // Ed Nisley KE4ZNU December 2013
    
    Layout = "Show";			// 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 = true && (Layout != "Split");				// no support for split, optional otherwise
    
    //- 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 = 23.0;				// front-to-back perpendicular to magazine shaft
    Height = 18.0;				// bottom-to-top, parallel to magazine shaft
    							//  18 = 10 round max 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*
    
    ScrewOD = 3.0 - 0.25;		// screw hole dia - minimal thread engagement
    ScrewLength = 13.0;
    ScrewOffset = -1.5;			//   ... from centerline
    							//  OEM = 0.0
    							//  generic A = -1.5
    
    NutOD = 5.6;				// hex nut dia across flats
    NutThick = 2.4;				//  ... generous allowance for nut
    NutTrapLength = 1.5*NutThick;		// allow for epoxy buildup
    NutOffset = 6.0;			//  ... base height from floor
    
    TrimHeight = 2.5;			// vertical clearance for spring clip on base plate
    							//   OEM = 2.5
    							//   generic A = 2.5
    
    TrimOffset = -9.5 + ScrewOffset;	// ... horizontal from centerline
    							//	 OEM = 0.0
    							//   generic A = 1.5
    
    SupportLength = 4.0;		// length of support struts under Trim
    SupportWidth = SpringID;	// ... width
    
    VentDia = 2.5;				// air vent from back of screw recess
    VentOffset = ScrewOffset - 6.0;
    
    RecessDia = 5.0;			// recess to reduce weight
    RecessLength = 0.66*Length;	//  ... internal length
    RecessOffset = 8.5;	//  ... offset from centerline
    
    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,NutTrapLength,6);
    
    		translate([0,ScrewOffset,-Protrusion])		// nut clearance at base
    			rotate(180/6)
    				PolyCyl(NutOD,(1.1*NutThick + Protrusion),6);
    
    		translate([SpringID/2,TrimOffset,-Protrusion])
    			rotate(180)
    				cube([SpringID,Length,(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 + 1.25*NutOD),ScrewLength])	// air vent
    			rotate([90,0,0]) rotate(180/8)
    				PolyCyl(VentDia,3*NutOD,8);
    		translate([0,VentOffset,-(VentDia/2)*tan(Angle)])
    			rotate([Angle,0,0]) rotate(180/8)
    				PolyCyl(VentDia,(RecessLength + (VentDia/2)*tan(Angle)),8);
    
    		translate([0,(RecessOffset + ScrewOffset),0])			// weight reduction recess
    			rotate([Angle,0,0]) rotate(180/8)
    				translate([0,0,-((RecessDia/2)*tan(Angle))])
    				PolyCyl(RecessDia,(RecessLength + (RecessDia/2)*tan(Angle)),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);
    	}
    
    SupportBars = floor((SupportWidth/2) / (4*ThreadWidth));
    
    	if (Support) {									// add support structures
    		for (i = [-SupportBars:SupportBars])
    			translate([i*4*ThreadWidth,
    					   (TrimOffset - SupportLength/2 - ThreadWidth),
    					   (TrimHeight - ThreadThick)/2])
    				color("Yellow")
    				cube([(2*ThreadWidth),SupportLength,(TrimHeight - ThreadThick)],center=true);
    
    		translate([0,(TrimOffset - SupportLength - ThreadWidth),(TrimHeight - ThreadThick)/2])
    			color("Yellow")
    			cube([SupportWidth,(2*ThreadWidth),(TrimHeight - ThreadThick)],center=true);
    
    		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);
    }
    
  • Sandisk 32 GB Flash Drive: Now With String!

    So I drill two holes in the dust caps of those teensy Sandisk drives and added a cheerful red string:

    Sandisk 32 GB Flash Drive - cap string
    Sandisk 32 GB Flash Drive – cap string

    That this should not be necessary goes without saying…

  • Kenmore Dishwasher Sound Deadening Sheets: Slip Sliding Away, Redux

    The springs balancing the dishwasher door started twanging again, which I now know is the diagnostic sign that an asphalt sound deadening sheet has slipped off the tub. A sheet on the right side almost perpetrated a clean escape, but the flap drooping over the spring gave it away:

    Dishwasher sound deadener - slipped away
    Dishwasher sound deadener – slipped away

    Another sheet on the left side was inching away, but hadn’t quite gotten over the fence:

    Dishwasher sound deadener - slipping away
    Dishwasher sound deadener – slipping away

    They’re pretty much a rigid solid at room temperature:

    Dishwasher sound deadener - wrinkled asphalt sheet
    Dishwasher sound deadener – wrinkled asphalt sheet

    It puts one in mind of the pitch drop experiments now running in various labs. In this case, we now know it takes about four years for an asphalt sheet to slide completely off the tub; those two sheets were definitely in place when I buttoned it up after the previous one broke free.

    I applied a heat gun to soften the sheets, then smoothed them around the tub again. This time I applied long strips of Gorilla Tape from one side to the other, rather than short strips of ordinary duct tape along the edges, and maybe this fix will outlast either the dishwasher or our tenure here, whichever comes first…