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: Thing-O-Matic

Using and tweaking a Makerbot Thing-O-Matic 3D printer

  • Printing Scale Model Concrete Blocks

    For reasons that undoubtedly make sense to him, my buddy Aitch is moving to coastal NC. Seeing as how we lived in Raleigh for half a decade, I figure he needs some hints on how to blend in…

    Toy cars up on blocks
    Toy cars up on blocks

    The solid model looks about the way you’d expect:

    Concrete block - solid model
    Concrete block – solid model

    The webs are slightly thinner than in real life, but it looks OK to me. The web came out slightly over 3 thread widths = 1.5 mm, to ensure they get a bit of fill rather than being two distinct threads. I originally tried making the web exactly 3 threads wide, which produced tiny dots of fill on the sides and corners. They printed with 0.20 infill; they’d print faster with 1.00 infill or all-solid layers.

    You’ll want to create a pile o’ blocks at once, of course, although this array took about two hours:

    Concrete blocks - build platform
    Concrete blocks – build platform

    The OpenSCAD source code:

    // Scale model concrete block
    // Ed Nisley KE4ZNU February 2013
    
    // Extrusion parameters must match reality!
    // Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;           // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    Scale = (1/25) * (3*ThreadWidth);
    
    BlockWidth = Scale * 190;
    BlockLength = Scale * 390;
    BlockHeight = BlockWidth;
    
    WebWidth = Scale * 30;
    
    CoreSize = [(BlockWidth - 2*WebWidth),(BlockLength - 4*WebWidth)/2,BlockHeight];
    
    CornerRadius = WebWidth/2;
    
    //----------------------
    // 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);
    
    }
    
    //-------------------
    // Component parts
    
    module Core(Size,Radius) {
        translate([0,0,(Size[2] - Protrusion)/2])
            minkowski() {
                cube([(Size[0] - 2*Radius),(Size[1] - 2*Radius),Size[2]],center=true);
                cylinder(r=Radius,h=Protrusion,$fn=8);
            }
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    difference() {
        translate([0,0,BlockHeight/2])
            cube([BlockWidth,BlockLength,BlockHeight],center=true);
        for (i = [-1,1])
            translate([0,i*(CoreSize[1] + WebWidth)/2,0])
               Core(CoreSize,CornerRadius);
        for (i = [-1,1])
            translate([0,i*3*(CoreSize[1] + WebWidth)/2,0])
               Core(CoreSize,CornerRadius);
    }
    
  • Dishwasher Rack Protectors: Into The Maw

    Three rack protectors have gone missing over the last few months, presumably being digested by the dishwasher’s grinder, so I ran off another batch:

    Dishwasher Rack Protectors - on platform
    Dishwasher Rack Protectors – on platform

    I used the original solid model, shown here with the support structure outside for visibility:

    Dishwasher rack protector - support model
    Dishwasher rack protector – support model

    I re-sliced the model to pick up whatever printer config tweakage happened since then. Those ribbed doodads snapped out easily and, in fact, some remained bonded to the platform:

    Dishwasher Rack Protectors - support structures
    Dishwasher Rack Protectors – support structures

    No finishing required: just slide them over the pins atop a blob of acrylic caulk. Despite the few missing protectors, it does a good job of bonding them to the rack and sealing gaps in the worn vinyl coating.

    I picked up a jar of ReRack glop on closeout duing my last pass through the Big Box Home Repair Store. It seemed a bit stiff, so I’ve added generous dollops of xylene, acetone, and MEK to thin it out; that’ll take a while to stabilize.

  • Samsung VAC-9048 Vaccuum Cleaner: Floor Brush Strips

    After beating the Samsung’s nozzle handle and hose into submission, I made a set of floor brush strips for the hard-floor attachment:

    Floor brush strips - replacements in place
    Floor brush strips – replacements in place

    The original brushes had non-woven felt glued to a cleverly molded strip of white plastic, which lasted not very long at all. I’d replaced them (*) with wool fabric glued to hand-hewn strips of polypropylene cut from the usual blister pack material, but that was so labor-intensive as to make no sense at all; it did show that replacement brushes would work, though, which was the whole point. This view looks through a finished strip to the urethane glue and wool fabric:

    Floor brush strip - manual version
    Floor brush strip – manual version

    Fortunately, there’s an easier way to make the strips:

    Floor brush strip - solid model
    Floor brush strip – solid model

    Note that the smaller tab (the one in the front) is not centered on the midline. The openings for the larger tab in the floor brush housing seem to have a small offset, but it’s not worth worrying about. The printed ones are 4 layers thick, but I think 3 layers will work as well; that’s what the OpenSCAD source will produce.

    This is one of the few situation where the hand-knitted top surface of a 3D-printed object is an advantage: that, plus the holes, provides enough griptitude for urethane glue to hold the fabric strips firmly in place.

    Obviously, you print them in multiples:

    Floor brush strips - on platform
    Floor brush strips – on platform

    A trial fit:

    Floor brush strip - trial fit
    Floor brush strip – trial fit

    They really are bowed slightly outward in the middle, which ensures there’s more pressure on the middle of the strip against the floor. I think the weird indented pattern in the brush housing under the strips was for a complex spring assembly that never made it into production; the OEM strips looked just like the ones I’m making, minus the perforations.

    I glued two strips individually to make sure everything lined up, then glued these two in one operation and separated them with a razor knife:

    Floor brush strips - gluing fabric
    Floor brush strips – gluing fabric

    (*) It goes without saying that OEM replacement brushes weren’t available and, in fact, they have never been available at any time when we’ve owned the vacuum cleaner. Maybe I’m not looking in the right place, but so it goes.

    The OpenSCAD source code, which you’ll want to print with Multiply set to maybe 8:

    // Samsung Vacuum cleaner nozzle floor strips
    // Ed Nisley KE4ZNU January 2013
    
    Layout = "Build";			// Show, Build
    
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    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 = 1.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);
    	}
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Show")
    	BackingStrip();
    
    if (Layout == "Build")
    	rotate(90) BackingStrip();
    
    
  • Samsung VAC-9048R Vacuum Cleaner: Nozzle Handle Hose Bushing

    The hose going into the handle of the neversufficently-to-be-damned Samsung VAC-9048R suck dog has been collapsing for quite some time, but I couldn’t figure out how to take the handle apart. Recently, the lock ring that I would have sworn was glued in place came loose, revealing the secret:

    Samsung vacuum cleaner - handle lock ring
    Samsung vacuum cleaner – handle lock ring

    You slide four lugs on the lock ring into the open slots, then turn the ring clockwise to force the lugs over barriers into recesses that capture them and hold the lock ring against the handle. The handle under the lock ring isn’t quite circular, nor is the lock ring, and I think (based on later events) that they expect the ring to deform as it turns in order to let the lugs spring over the barriers.

    Anyhow, with the lock ring loose, removing four screws released the two halves of the handle:

    Samsung vacuum cleaner - handle interior
    Samsung vacuum cleaner – handle interior

    The handle includes a switch for the powered floor brush, which we rarely use, and a suction control lever that’s basically a binary leak: on or off. With the handle opened in front of you, remove the innards, unwrap the decorative duct tape, unwind enough of the two power conductor / spring wire ribs to allow for rebuilding the electrical connections, and cut off the damaged part of the hose.

    Now, obviously, what that hose needs is a little bit of strain relief, along the lines of the hideous snout I’d affixed to its other end a while ago. The general idea is to replace the lock ring with a little attachment that will hold the heatshrink tubing in place. Something like this:

    Bushing Solid Model - top
    Bushing Solid Model – top

    The bottom view, looking up through the layer of 1 mm cubes defining the Z=0 plane, shows the lugs:

    Bushing Solid Model - bottom
    Bushing Solid Model – bottom

    I thought the slit would provide enough springiness to let the lugs bump over the ridges, but it wasn’t quite enough: the relatively stiff ABS isn’t nearly as springy as the original black plastic for about the same thickness. For the next version, I’ll try four slits, all of which must end at different levels to avoid concentrating the stress on a single layer.

    In any event, it came out about like you’d expect:

    Handle Bushing - on platform
    Handle Bushing – on platform

    As with many projects, though, I had to make a pair of simpler prototypes to get the measurements correct. The lugs, for example, are not 90° apart, spaced neatly around the handle’s midline seam, as I assumed for Prototype 1 on the right:

    Handle bushings - prototypes 2 and 1
    Handle bushings – prototypes 2 and 1

    Prototype 2, on the left, has a support structure holding up a horizontal step that butted against the handle, which turned out to be unnecessary. The OpenSCAD version substitutes a pair of conical transitions that worked much better; they’re at different levels with a thicker wall section between them.

    With the ring and somewhat preshrunk heatshrink tubing slipped along the hose, rewiring proceeds in reverse order. Next time, I’ll add a QD fitting in the hose-to-socket wire so I can take the whole thing apart again without cutting that wire:

    Samsung Vacuum Handle - wiring detail
    Samsung Vacuum Handle – wiring detail

    Assemble the handle, snap the glaring white strain relief fitting in place, shrink the tubing, add a cable tie mostly for show:

    Samsung Vacuum Handle - heatshrink over bushing
    Samsung Vacuum Handle – heatshrink over bushing

    I cut a few slits in the tubing’s end to improve its bendiness, but it’s already Much Better than it was.

    A few things I’d do differently:

    • Add a recess for the cable tie, with a flat spot for its latch
    • Four slits, not just one
    • Ribs on the snout to help anchor the tubing
    • Longer snout?

    The OpenSCAD source code for the final version, with a module for the support ring that you won’t need:

    // Samsung Vacuum cleaner hose bushing
    // Ed Nisley KE4ZNU January 2013
    
    // Layout options
    
    Layout = "Build";
                        // Overall layout: Show Build
                        // Parts: Ring Sleeve
    
    //- Extrusion parameters must match reality!
    //  Print with +1 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.75;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;           // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    HoseOD = 47.0;					// spiral tube diameter
    TubeWall = 1.4;					// heatshrink tubing wall thickness
    HandleRingLong = 8.5;			// length of ring stub on handle
    
    RingID = 51.0;					// lock ring over handle end
    RingOD = 58.0;
    RingLong = 12.0;
    
    Locks = 4;						// bumps inside lock ring
    LockLength = 4.0;
    LockWide = 4.0;
    LockThick = 0.75;
    
    LockAngleOffset = 52.0;			// offset of lock bump from handle top dead center
    LockAngleIncluded = 102.4;		// between first and second lock bump (also 3 & 4)
    LockAngles = [-LockAngleOffset,
    				-(LockAngleOffset+LockAngleIncluded),
    				-(LockAngleOffset+180),
    				-(LockAngleOffset+LockAngleIncluded+180)];
    
    BushID = HoseOD + 1.0;			// over spiral hose
    BushOD = RingOD - 2*TubeWall;	// allow flush heatshrink fit
    BushLength = 15.0;
    
    SlitWidth = 2*ThreadWidth;		// allow expansion of lock ring, sorta kinda
    SlitHeight = 20.0;
    SlitAngle = 0;
    SlitLength = max(RingOD,BushOD);
    
    RingSides = 4*8;
    RingAlign = 360/(2*RingSides);
    $fn = RingSides;
    
    //----------------------
    // 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);
    
    }
    
    //-------------------
    // Component parts
    
    module Ring() {
    	union() {
    		difference() {
    			union() {
    				cylinder(r=RingOD/2,h=(RingLong + Protrusion));
    				translate([0,0,RingLong])
    					cylinder(r1=(RingOD/2),r2=(BushOD - Protrusion)/2,h=(RingOD - BushOD));
    			}
    			translate([0,0,-Protrusion]) {
    				PolyCyl(RingID,(HandleRingLong + Protrusion),RingSides);
    				cylinder(r=BushID/2,h=(2*RingLong));
    			}
    			translate([0,0,(HandleRingLong - Protrusion)])
    				cylinder(r1=((RingID/2) / cos(180/RingSides) + HoleWindage),
    						 r2=BushID/2,
    						 h=(RingID - BushID)/2);
    		}
    		for (i=[0:Locks-1])
    			rotate(LockAngles[i] + RingAlign)
    				translate([(RingID/2),0,LockWide/2])
    					cube([2*LockThick,LockLength,LockWide],center=true);
    	}
    }
    
    module Sleeve() {
    	difference() {
    		cylinder(r=BushOD/2,h=(BushLength + Protrusion));
    		translate([0,0,-Protrusion])
    			cylinder(r=BushID/2,h=BushLength + 3*Protrusion);
    	}
    }
    
    module Bushing() {
    	difference() {
    		union() {
    			Ring();
    			translate([0,0,RingLong])
    				Sleeve();
    		}
    		rotate(SlitAngle)
    			translate([SlitLength/2,0,(SlitHeight - Protrusion)/2])
    				cube([SlitLength,SlitWidth,(SlitHeight + Protrusion)],center=true);
    	}
    }
    
    // This turned out to be unnecessary after tapering the transitions
    module Support() {
    
    SuppHeight = RingLong - ThreadThick;
    
    	color("Yellow")
    	union() {
    		difference() {
    			cylinder(r=(RingID/2 - LockThick - ThreadWidth/2),h=SuppHeight);
    			translate([0,0,-Protrusion])
    				cylinder(r=(BushID/2 - ThreadWidth),h=2*RingLong);
    			for (i=[0:RingSides-1])
    				rotate(i*2*RingAlign)
    					translate([RingID/4,0,SuppHeight - ThreadThick/2 + Protrusion/2])
    						cube([RingID/2,(LockLength - 3*ThreadWidth),(ThreadThick + Protrusion)],center=true);
    		}
    	}
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Build")
    	union() {
    		Bushing();
    //		Support();
    	}
    
    if (Layout == "Show")
    	Bushing();
    
    if (Layout == "Ring")
    	Ring();
    
    if (Layout == "Sleeve")
    	Sleeve();
    
    if (Layout == "Support")
    	Support();
    
    
  • Hall Effect Current Sensor: Winding and Armoring the Toroid

    Winding a slit ferrite toroid poses no challenge, so putting 25 turns of 26 AWG wire on it didn’t take long at all:

    F50-61 toroid - 25 turns 26 AWG
    F50-61 toroid – 25 turns 26 AWG

    However, a ferrite toroid doesn’t take kindly to being dropped and I figured that a slit toroid would crack under a stern look, so I decided to wrap some armor around it. A small squeeze bottle offered a cap just slightly larger than the winding, so I used that slitting saw to cut off a suitable ring.  The first step was to grab it in the 3 jaw chuck and align its axis parallel to the spindle:

    Aligning bottle cap in 3-jaw chuck
    Aligning bottle cap in 3-jaw chuck

    I wanted to cut off a slightly taller ring, but the clamping screw on the saw arbor just barely cleared the chuck for a 5 mm ring. I jogged around the chuck jaws to cut two slits in the cap that eventually joined near the back:

    Slicing ring from bottle cap
    Slicing ring from bottle cap

    That was about 1000 rpm, no coolant, and slow feed, but also a totally non-critical cut in plastic.

    I put a snippet of foam rubber in the slot, put the ring on a Kapton-covered build platform from the Thing-O-Matic, filled it with hot-melt glue, gooshed the toroid in place, and waited for cooling. Trimming and cleaning out the slit produced a hideously ugly, but (I hope) much more durable assembly:

    Slit ferrite toroid - with armor
    Slit ferrite toroid – with armor

    I’m reasonably sure I didn’t crack the ferrite while cleaning out the slit; that hot-melt glue is tenaciously gummy stuff!

    Now, to find out whether it actually works…

  • Improved OXO Can Opener Knob

    We recently replaced a defunct can opener with an OXO opener that removes can lids without creating razor-sharp edges. Unfortunately, the knob doesn’t agree well with Mary’s hand, so I laid out a prototype doorknob-shaped cap (and also removed all the can lids that confronted her):

    OXO Can Opener Knob
    OXO Can Opener Knob

    It prints in four parts: the flat cover and three pillars, with two filament snippets aligning each pillar. The internal openings of this model do not fit the OXO knob’s lobes correctly; a Dremel sanding drum worked wonderfully well to make it fit. The next version should have much smaller pillar bases with a bit more clearance at the top: measurements from the as-adapted pillars will be in order.

    Gluing everything together once again justifies having Too Many Clamps:

    OXO Can Opener - gluing knob cover
    OXO Can Opener – gluing knob cover

    I intended to secure cap to knob with 2-56 screws in those recessed holes and even went so far as to flatten the top of the knob’s lobes in preparation for drilling:

    OXO Can Opener - knob flats
    OXO Can Opener – knob flats

    However, Dragorn of Kismet gave me a few packets of only slightly outdated Sugru (a great idea that’s far too spendy and short-lived for my shop) that solved the problem:

    OXO Can Opener - knob cover with silicone tape
    OXO Can Opener – knob cover with silicone tape

    The silicone tape wrap greatly improves the griptitude.

    Early returns indicate this works reasonably well, but the top should be more rounded and tapered. It goes without saying that black filament would be much less ugly…

    The OpenSCAD source code, with the caveat that the as-printed knob won’t fit without considerable abrasive adjustment:

    // OXO Softworks Can Opener
    //  Enlarged & rounded knob
    // Ed Nisley KE4ZNU December 2012
    
    include </mnt/bulkdata/Project Files/Thing-O-Matic/MCAD/units.scad>
    include </mnt/bulkdata/Project Files/Thing-O-Matic/Useful Sizes.scad>
    
    // Layout options
    
    Layout = "Cap";
                        // Overall layout: Build1 Build2
                        // Parts: Cap Knob
    
    //- Extrusion parameters must match reality!
    //  Print with +1 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.2;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;           // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    TriLobeRad = 37.5;					// radius: center to end of lobe
    TriLobeOD = 2*TriLobeRad;
    TriLobePeakRad = 23.0;				// radius: center to peak height
    TriLobeHeight = 22.5;
    
    WingArcRad2 = 48;					// Arc between knob lobes, top
    WingArcRad1 = WingArcRad2 - 5;		//
    WingArcOffset = 14.0;				// Knob center to arc2 radius
    
    KnobOD1 = 70;						// maximum dia without chamfer
    KnobOD2 = 65;						// top dia
    
    KnobSides = 3*4;					// maintain 3-side symmetry
    
    DomeHeight = 8;						// dome shape above lobes
    
    KnobHeight = DomeHeight + TriLobeHeight;
    
    DomeOD = KnobOD2 + (KnobOD1 - KnobOD2)*(DomeHeight/KnobHeight);
    
    DomeArcRad = (pow(KnobHeight,2) + pow(DomeOD,2)/4) / (2*DomeHeight);
    
    ScrewDia = Tap2_56;
    ScrewHeadDia = Head2_56;
    ScrewBase = 0.6*DomeHeight - Head2_56Thick;
    
    AlignPinDia = 3.0;
    AlignPinCircleRad = 0.55*(WingArcOffset + KnobOD2/2);
    AlignPinDepth = 3.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);
    }
    
    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);
    
    }
    
    //-------------------
    // Component parts
    
    module TriKnob() {
    	intersection() {
    		difference(convexity=3) {
    			translate([0,0,-Protrusion])
    				cylinder(r=TriLobeRad,h=(TriLobeHeight + 2*Protrusion));
    			for (i=[-1:1])
    				rotate(i*120)
    					translate([(WingArcOffset + WingArcRad2),0,-TriLobeHeight/2])
    						cylinder(r1=WingArcRad1,r2=WingArcRad2,h=2*TriLobeHeight);
    		}
    		translate([0,0,TriLobeHeight/2])
    		cube([2*KnobOD1,2*KnobOD2,TriLobeHeight],center=true);
    	}
    }
    
    module KnobCap() {
    	difference() {
    		intersection() {
    			translate([0,0,(KnobHeight-DomeArcRad)])
    				rotate(180/KnobSides)
    					sphere(r=DomeArcRad,$fa=180/KnobSides);
    			difference(convexity=4) {
    				rotate(180/KnobSides)
    					cylinder(r1=KnobOD1/2,r2=KnobOD2/2,h=KnobHeight,$fn=KnobSides);
    				TriKnob();
    			}
    			rotate(180/KnobSides)
    				cylinder(r1=KnobOD2/2,r2=KnobOD1/2,h=KnobHeight,$fn=KnobSides);
    		}
    		for (i=[-1:1])
    			rotate(i*120) {
    				translate([-TriLobePeakRad,0,0]) {
    					PolyCyl(ScrewDia,KnobHeight);
    					translate([0,0,TriLobeHeight + ScrewBase])
    						PolyCyl(ScrewHeadDia,KnobHeight);
    				}
    			}
    		for (i=[-1:1]) for (j=[-1,1])
    			rotate(i*120 + j*(270/KnobSides))
    				translate([AlignPinCircleRad,0,(TriLobeHeight - AlignPinDepth - Protrusion)])
    					PolyCyl(AlignPinDia,2*(AlignPinDepth + Protrusion));
    	}
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Cap")
    	difference() {
    		KnobCap();
    		cylinder(r=KnobOD1,h=Protrusion/2,center=true);
    	}
    
    if (Layout == "Knob")
    	TriKnob();
    
    if (Layout == "Build1")
    	translate([0,0,-TriLobeHeight])
    		difference() {
    			KnobCap();
    			translate([0,0,(TriLobeHeight - Protrusion)/2])
    				cube([2*KnobOD1,2*KnobOD2,TriLobeHeight+Protrusion],center=true);
    		}
    
    if (Layout == "Build2")
    	translate([0,0,TriLobeHeight])
    		rotate([180,0,0])
    			difference() {
    				KnobCap();
    				translate([0,0,(TriLobeHeight + TriLobeHeight/2)])
    					cube([2*KnobOD1,2*KnobOD2,TriLobeHeight],center=true);
    			}
    
  • Logic Probe Tip Covers

    Our Larval Engineer received a logic probe / pulser set for Christmas:

    RSR Logic Probe Pulser Set - with formed covers
    RSR Logic Probe Pulser Set – with formed covers

    They’re the low-cost RSR-611 and -620 from the usual eBay vendor, not my ancient HP10525/10526 set, but they should suffice. Perhaps nobody uses logic probes these days, what with most of the parts being too small for even a needle tip, but …

    Anyhow, they didn’t have caps over the sharp probe tips, so I rummaged around until I found the stash of cigar tubes (some of which went into that air flow straightener) that were about the right size. I thought about 3D printing an adapter between tubes and probes:

    RSR Probe Cap Adapter - solid model
    RSR Probe Cap Adapter – solid model

    It’s actually a subtractive kind of thing, with a model of the probe tip subtracted from a suitable cylindrical object:

    RSR Logic Probe - solid model
    RSR Logic Probe – solid model

    But then I realized the tubes were thermoplastic, held each one over a stove burner until the open end went transparent and droopy, rammed it down over the probe tip, and trimmed off the ragged edge. Worked fine, fits securely, and even looks pretty good:

    RSR Covers - detail
    RSR Covers – detail

    I’ll never print the adapters, but maybe one of us will tweak the model to do something else…

    The OpenSCAD source code:

    // RSR Logic Probe / Pulser Cap
    // Ed Nisley KE4ZNU December 2012
    
    // Adapts cigar tube to probe body
    
    // Layout options
    
    Layout = "Build";
                        // Overall layout: Show Build
    			// Parts: Probe
    
    //- Extrusion parameters must match reality!
    //  Print with +1 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.2;
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;           // make holes end cleanly
    
    //----------------------
    // Dimensions
    
    ProbeDia = 18.0;				// dia of main body
    ProbeTipDia = 6.8;				// dia at end of plastic cone
    ProbeTipLen = 30.0;				// length of metal ferrule + tip
    ProbeConeLen = 17.5;			// cone taper length
    
    TubeOD = 17.25;
    TubeWall = 0.50;
    TubeID = TubeOD - 2*TubeWall;
    
    TubeLen = 15;					// slip fit over tube body
    
    BodyLen = 20;					// slip fit over probe body
    
    WallThick = 3.5*ThreadWidth;		// basic adapter wall thickness
    
    AdapterLen = TubeLen + BodyLen;
    AdapterOD = ProbeDia + 2*WallThick;
    AdapterSides = 4*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);
    
    }
    
    module Probe() {
    	union() {
    		cylinder(r=((ProbeDia + HoleWindage)/2),
    				 h=(BodyLen + 1.2*Protrusion),$fn=2*AdapterSides);
    		translate([0,0,(BodyLen + Protrusion)])
    			cylinder(r1=(ProbeDia + HoleWindage)/2,
    					 r2=ProbeTipDia/2,
    					 h=ProbeConeLen,$fn=2*AdapterSides);
    		cylinder(r=ProbeTipDia/2,h=(BodyLen + ProbeConeLen + ProbeTipLen),$fn=2*AdapterSides);
    	}
    }
    
    module ProbeSleeve() {
    
    	difference() {
    		cylinder(r=AdapterOD/2,h=AdapterLen);
    		translate([0,0,-Protrusion])
    			Probe();
    		PolyCyl((TubeOD + HoleWindage),(AdapterLen + Protrusion),2*AdapterSides);
    	}
    }
    
    //----------------------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Show")
        ProbeSleeve();
    
    if (Layout == "Build")
        translate([0,0,AdapterLen])
    		rotate([180,0,0])
    			ProbeSleeve();
    
    if (Layout == "Probe")
    	Probe();