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

  • ABS Coating on Aluminum Build Plate: Thickness Thereof

    Printing ABS objects on an ABS film atop a heated aluminum plate works just about as perfectly as I could want, as witness those calibration objects. It turns out that the thickness of the ABS film makes a big difference in how well the first layer bonds to it.

    I’m coating the plates with scrap ABS objects dissolved in MEK, because MEK seems to be less aggressively flammable than acetone. It smells horrible, though, and spreading a layer of toxic gunk with the consistency of honey can’t possibly be good for me. I use dead credit cards as spreaders and wonder if there’s a better way; a brush would clog up almost instantly.

    The rough rule of thumb:

    • If the ABS layer isn’t obvious, then it’s too thin.

    A Companion Cube growing out of a good pink film layer:

    Companion Cube on ABS coated plate
    Companion Cube on ABS coated plate

    Peeling a smaller Cube off a plate shows how well it bonds to clear film. Notice how the film peels off the build plate without leaving any residue except for a tear in the film covering the hollow underside of the Cube.

    Companion Cube - Bottom surface with ABS coating
    Companion Cube – Bottom surface with ABS coating

    These outline extrusions show the effect of a too-thin film, where the extrusion simply peeled off the film. Where it’s thick enough, the extrusion is welded right to the surface. Intermediate thicknesses tend to rip on both sides of the extrusion.

    ABS coatings from aluminum build plates
    ABS coatings from aluminum build plates

    In round numbers, the perfectly formed film at the lower left is between 0.05 mm (the darker regions) and 0.09 mm (the deepest pink). The others range from 0.02 mm to 0.05 mm and are too thin for good bonding. Even the thickest film doesn’t add much to the first layer thickness.

    The other part of the secret is extruding the first layer at 10 mm/s, which is 25% of the 40 mm/s I use for the rest of the object layers. The platform is at 120 °C, the Thermal Core at 210 °C, and the extrusion sticks like it’s welded… which, in fact, it is.

    I think that a too-thin film cools the extrusion before it can bond with the film, while a just-right film melts slightly on contact. Extruding at 10 mm/s guarantees enough contact time for the filament to melt the film and cool down before the nozzle puts any tension on it: corners come out perfectly.

    The other part of the puzzle requires an absolutely level build platform at a constant height from the nozzle. The platform leveling described there helps, but it’s a hassle to get everything set up.

  • Thing-O-Matic: Protect the ABP Motor Terminals on an HBP

    This should go without saying, but I got it wrong the first time: protect those little pins that drive the ABP belt motor if you’re not using them, particularly if you have a grounded aluminum build plate a few millimeters away.

    I used a pair of jumpers, side by side, that did not connect the two pins, because they were close at hand when I first shorted the build plate to the pin carrying +12 V. A jumper that connects the pins will blow the motor control MOSFET on the Extruder Controller if you (or the G-Code) should happen to ever turn it on by mistake, so you need two.

    Protected motor terminals on HBP
    Protected motor terminals on HBP

    Better, just put some heatshrink tubing over both pins.

    Heatshrink on ABP motor terminals
    Heatshrink on ABP motor terminals

    You could print up a little dummy plug for the thing…

  • Un-milling Some Slots

    The first aluminum build plates had to fit around the gimcrackery atop my tweaked ABP: two solderless grounding lugs and a lump of Wire Glue. The new HBP setup put the grounding lug below the fixed plate and did away with the lump, so the removable plate could have five holes and a wiper cutout without any fancy trimming.

    I’d squared up three plates and machined only two for the ABP, so I had one plate that just needed drilling. Rather than machining two new plates, I filled the cutouts on the old plates with JB Industro Weld epoxy, flycut the excess, and drilled new holes.

    Flycut and drilled epoxy fill
    Flycut and drilled epoxy fill

    This was straightforward manual CNC: get the plate square on the table, touch off the plate edges, and then drill the holes in two steps.

    If those thin epoxy webs break off the outside of the holes, it’s not the end of the world: the plates won’t go anywhere because they’re indexed by the holes on the other side.

    Memo to Self: Next time, make a fixture to hold the plates relative to a starting hole and eliminate all the tedious alignment steps.

  • Thing-O-Matic: HBP With Aluminum Build Plate

    An aluminum plate coated with ABS provides a very flat, very adhesive build platform, but that kludge atop the ABP didn’t provide enough stability or adjustability. I decided to scrap the ABP and modify the HBP to use the same removable plates.

    The ABP kludge involved simply resting an aluminum plate atop the Heater PCB, which is ordinary PCB material with heat applied to only one surface and, on my ABP, has developed a pronounced warp. I decided to clamp the Heater to a thinner aluminum plate, ignoring the fact that PCB material has a much higher coefficient of thermal expansion than aluminum. Although the heater PCB may want to distort, I’m counting on the aluminum to maintain a flat upper surface.

    HBP Heater and aluminum sub-platform adjuster
    HBP Heater and aluminum sub-platform adjuster

    Those bolt heads sit in a 0.2 mm recess that lowers them just enough to be flush with the surface of the removable plate.

    Then the removable plate sits atop the flat plate atop the heater: the two plates should snuggle together in Z and I think there’s no need to clamp them together. The holes have slight clearance around the bolt heads, making the plate a drop-in fit.

    HBP with aluminum plates
    HBP with aluminum plates

    This view shows the small notch filed in the front left corner of the removable plate. I use a small scraper blade to pry the hot top plate loose after a build session, grab it with pliers, and carry it away for cooling. The Sherline mill’s tooling plate provides a wonderful cold surface and the ABS gives off a distinct snap when it cools enough to detach from the aluminum plate.

    Separation notch in aluminum build plate
    Separation notch in aluminum build plate

    Although it’s not automated, swapping plates isn’t a tedious affair. The real delay comes from heating a cold plate to operating temperature again, which requires about five minutes.

    The silicone wiper holds the removable plate against the bolt heads, providing some stability in the XY plane. There’s no need for precise indexing.

    HBP Heater and sub-platform with wiper
    HBP Heater and sub-platform with wiper

    The Heater normally attaches to the HBP with six bolts, which severely overconstrains the surface. Here, three (center left, front+rear right) bolts clamp the heater to the sub-plate and three (front+rear left, center right) extend through the HBP plywood to nuts epoxied to the bottom surface.

    Six matching springs from my Parts Heap support the whole affair, with the three on the clamping bolts being more compressed by the nuts below the Heater PCB. They come without pedigree and nearly anything that fits should work; it’s not like they must support an engine block.

    The M3 bolts have a 0.5 mm thread pitch, so one turn changes the plate height by 0.5 mm and 1/6 turn (which is easy to make with a hexagonal wrench) changes it by 0.08 mm. The threads catch on the plate and Heater, so I may saw off some longer partially threaded bolts to get a smooth cylinder through the holes.

    I did the initial adjustment on the surface plate with the entire XY stage assembly up on parallel blocks. Those blocks really should be under the Y guide rods inserted in the bearings, but this was enough to get a good first approximation to a level surface.

    HBP initial height adjustment
    HBP initial height adjustment

    And then it went back into the Thing-O-Matic…

    I thought of the X Rod Follower while I had this all apart, but after putting it together, I wasn’t going to build the follower just to tear the stage down right away.

  • Thing-O-Matic: X Axis Motor Wire Strain Relief

    As the Y stage moves front-to-back, the X axis motor wires tend to bend at the cable tie lashing them to the Y stage. While I had the XY stage apart, I wrapped a bit of self-vulcanizing tape around the skein of motor wires to provide some strain relief.

    X Axis motor wire strain relief
    X Axis motor wire strain relief

    It’s not great, but it’s better than nothing.

  • Microscope LED Ring Illuminator

    A batch of LED ring lights arrived from halfway around the planet and I’d earmarked one for a microscope ring illuminator, despite the crappy color spectrum of white LEDs. It’s better than the fluorescent desk lamp I’d been using up to this point.

    This shows the business end of the LED ring light, which would probably look better more professional without the full-frontal Barbie color scheme:

    Microscope LED Ring light - snout view
    Microscope LED Ring light – snout view

    It’s less overwhelming from the top:

    Microscope with LED illuminator
    Microscope with LED illuminator

    The power cable came with the ring. I unsoldered it, fed the end through the shade, resoldered it, snipped off the automobile lamp adapter, wired it to a switch and a 12 V 200 mA wall wart, and hot-melt-glued the switch to the microscope. Yet another vampire load, alas.

    The two parts must be printed separately to eliminate any problem with overhang, as the finished widget would have vertical walls on both sides. I thought about support material, realized that would be a lot like work, and split the thing into two parts.

    LED ring light - mounting plate and shade
    LED ring light – mounting plate and shade

    The walls on the shade ring show the same backlash problem that cropped up there; I built these before tweaking the belts.

    The mounting plate screws into the microscope’s accessory thread:

    Microscope LED Ring Light - Mount Plate
    Microscope LED Ring Light – Mount Plate

    Admittedly, “screws into” may be an exaggeration: the mount is just a cylindrical feature slightly larger than the microscope’s minor thread diameter; it’s barely more than a snug friction fit. I clipped out four small sections to allow that ring to bend slightly as it engages the threads.

    A shade contains the LED ring and keeps direct light off the objective lenses. There’s a tiny hole on one side to let the power wires out:

    Microscope LED Ring Light - Shade
    Microscope LED Ring Light – Shade

    The two parts got glued together with the same ABS-in-MEK gunk that I apply to the aluminum build plate:

    Clamping LED ring light parts
    Clamping LED ring light parts

    I applied three blobs of hot-melt glue inside the shade, lined up the LED ring’s power wire with the exit hole, and smooshed it into place. Pause for a breath and it’s done!

    The result actually looks pretty good, despite the weird yellow-and-blue spectrum you get free with every “white” LED. I reset the camera’s color correction using a white sheet of paper. This is an ordinary M3 socket head cap screw, familiar to Thing-O-Matic owners everywhere, and a tweaked needle-point tweezer:

    Sample image using LED ring light
    Sample image using LED ring light

    The microscope camera mount works surprisingly well, particularly given how simple it was to build.

    The OpenSCAD source makes the shade walls a bit taller than you see above. When I run out of pink filament, this one’s on the rebuild list!

    // Microscope LED Ring Illuminator Mount
    // Ed Nisley - KE4ZNU - Mar 2011
    
    // Build with...
    //	extrusion parameters matching the values below
    //	2 extra shells
    //	3 solid surfaces at top + bottom
    
    Build = "Ring";					// Mount or Ring
    
    // Extrusion parameters for successful building
    
    ThreadZ = 0.33;						// should match extrusion thickness
    WT = 1.75;							// width over thickness
    ThreadWidth = ThreadZ * WT;			// should match extrusion width
    
    HoleWindage = ThreadWidth;			// enlarge hole dia by extrusion width
    
    // Screw mount dimensions
    
    MountOD = 46.85 - ThreadWidth;		// Microscope thread diameter (thread minor)
    MountDepth = 2.5;					// ... length
    MountID = MountOD - 6*ThreadWidth;	// ID of mount body -- must clear lenses
    
    echo(str("Mount ID: ",MountID));
    echo(str("Mount OD: ",MountOD));
    
    PlateThick = 3*ThreadZ;				// Thickness of mounting plate beyond rings
    
    echo(str("Plate: ",PlateThick));
    
    // LED Ring holder dimensions
    
    RingID = 54.0;
    RingOD = 71.0;
    RingFit = 0.5;						// radial gap from ID and OD
    
    InnerShade = 6.0;					// Shade walls around ring
    OuterShade = 10.0;
    ShadeWall = 4*ThreadWidth;			//  wall thickness
    
    HolderID = RingID - 2*RingFit - 2*ShadeWall;
    HolderOD = RingOD + 2*RingFit + 2*ShadeWall;
    
    echo(str("Holder ID:",HolderID));
    echo(str("Holder OD:",HolderOD));
    
    LeadWidth = 4.0 + HoleWindage;		// LED power lead hole
    LeadTall = 2.0 + HoleWindage;
    
    Protrusion = 0.1;					// extend holes beyond surfaces for visibility
    
    //---------------
    // Create thread gripper and plate
    
    module Mount() {
    
      difference() {
    	union() {
    	  translate([0,0,PlateThick])
    		cylinder(r=(MountOD/2 + HoleWindage),h=MountDepth);
    	  cylinder(r=HolderOD/2,h=PlateThick);
    	}
    
    	translate([0,0,-Protrusion])
    	  cylinder(r=MountID/2,h=(PlateThick + MountDepth + 2*Protrusion));
      }
    
    }
    
    //----------------
    // Create LED ring holder
    
    module Ring() {
    
      difference() {
    	union() {
    	  cylinder(r=HolderOD/2,h=PlateThick);
    
    	  translate([0,0,PlateThick]) {
    		difference() {
    		  cylinder(r=HolderOD/2,h=OuterShade);
    		  cylinder(r=(HolderOD/2 - ShadeWall),h=(OuterShade + Protrusion));
    		}
    
    		cylinder(r=(HolderID/2 + ShadeWall),h=InnerShade);
    	  }
    	}
    
    	translate([0,0,-Protrusion])
    	  cylinder(r=HolderID/2,h=(InnerShade + PlateThick + 2*Protrusion));
    
    	translate([(HolderOD/2 - ShadeWall/2),0,(PlateThick + ShadeWall/2 + LeadTall/2)]) {
    	  scale([ShadeWall*2,LeadWidth,LeadTall])
    		rotate(a=[0,90,0])
    		  cylinder(r=0.5,h=1.0,center=true,$fn=12);
    	}
      }
    
    }
    
    //---------------
    // Build what's needed
    
    if (Build == "Mount") {
      Mount();
    }
    else {
      Ring();
    }
    
  • Thing-O-Matic: X Axis Rod Follower

    This represents the first pass at un-constraining the X stage, so the poor little X axis stepper motor doesn’t have such a hard time of it and we can all get out of the sand-the-plywood-to-fit mindset. The Y stage has a similar mechanism, albeit with three bearings on the rod.

    As seen from the front, the rear guide rod constrains the X stage in roll and yaw, while this Follower constrains pitch. The bearings turn in X, slide very slightly as needed in Y, and prevent motion in Z. Slight angle and distance mismatches between the rods no longer matter; I think the as-built (pre-sanding) rods will be sufficiently parallel for all practical purposes.

    I have yet to install this, as I have a few other thing to do before tearing the entire XY assembly apart again; this is just a see-if-it-fits prototype:

    Prototype X Axis rod follower
    Prototype X Axis rod follower

    The front view:

    X Axis follower - model front view
    X Axis follower – model front view

    I wanted to mount it on the rear face of the X stage Idler plate, but there’s simply not enough room between the rod and the plywood Idler plate. Indeed, this version may be slightly too chubby for the space available in front of the Drive plate.

    The OpenSCAD code produces a recess that clamps the belt into the drive serrations; the prototype doesn’t have that. The rear view shows the recess; I don’t know if that will build successfully. The dimple just below the top bearing bolt hole fits around the nut holding the build platform in place.

    X Axis follower - model rear view
    X Axis follower – model rear view

    My Little Box o’ Tiny Bearings disgorged a pair of hard-inch bearings, but something along the lines of a 603 or 693 bearing would be better. Having shields on both sides would be a nice touch. The recently expanded table there gives some useful bearing dimensions.

    The M3x12 bolts on the bearings cut their own threads on the way into the slightly undersized holes. I think that will be adequate, but you could sink nuts into the back.

    The OpenSCAD source code will should auto-size the Follower around the bearings and your own measured / guesstimated clearances. Obviously, smaller bearings are better and there’s precious little clearance to the Y stage even with 3/8 inch OD bearings.

    Make sure the extrusion settings near the top match your actual build values and that both collections match what the printer actually produces, because there’s not much room around the features for fill.

    The top fits flush underneath the HBP stage to maintain proper alignment. That’s not really necessary, given the four bolts holding the Follower to the Drive plate, but there it is.

    The Preload value adjusts the Z position of the lower bearing: + up, – down. It’s at zero for the prototype and the as-built Follower has 0.16 mm of preload: the bearings are 0.16 mm too close together. I think that’s OK, although I might dial it back a little bit by setting Preload=-0.1. For all I know, it’ll relax to fit and eventually wind up being marginally rattly.

    The Build value at the top controls whether the model has the rods & bearings to show how it fits together (as above) or just the Follower block laid on its back for exporting to the STL file.

    The OpenSCAD source:

    // Thing-O-Matic X Stage rear guide rod follower
    // Ed Nisley - KE4ZNU - Mar 2011
    
    include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
    
    Build = false;						// set true to generate buildable layout
    
    $fn = 8;							// default for holes
    
    // Extrusion values
    // Use 2 extra shells behind the perimeter
    //  ... and 3 solid shells on the top & bottom
    
    ThreadThickness = 0.33;
    ThreadWT = 1.75;
    ThreadWidth = ThreadThickness * ThreadWT;
    
    HoleWindage = ThreadWidth;			// enlarge hole dia by extrusion width
    
    Protrusion = 0.1;					// extend holes beyond surfaces for visibility
    
    // Bearing dimensions
    
    BearingOD = (3/8) * inch;			// I used a hard-inch bearing -- try a 603 or 693
    BearingID = (1/8) * inch;
    BearingThick = (5/32) * inch;
    
    BearingBoltDia = 3.0;				// allow this to shrink: drill & tap the threads!
    BearingBoltRadius = BearingBoltDia/2;
    
    BearingStemOD = BearingBoltDia + 6*ThreadWidth;
    BearingStemRadius = BearingStemOD/2;
    BearingStemLength = 2.0;
    
    // X guide rod dimensions
    
    RodDia = (3/8) * inch;				// hard inch rod
    RodRadius = RodDia/2;
    RodLength = 75;						// for display convenience
    
    RodClearTop = 12.6;					// clearance from HBP to rod
    RodClearSide = 9.0;					//  ... idler to rod
    RodClearBottom = 10.7;				//  ... rod to Y stage
    
    RodClearCirc = 1.5;					//  ... around circumference
    
    // Drive mounting piece (from ABP teardown)
    
    DriveHolesX	= 16.0;					// on-center distance
    DriveHolesZ = 9.0;					// on-center distance
    DriveHoleZOffset = -5.0;			// below bottom of HBP platform
    
    DriveHeight = 28.0;
    
    DriveBoltDia = 3.0 + HoleWindage;	// bolt dia to hold follower in place
    DriveBoltRadius = DriveBoltDia/2;
    
    DriveBoltHeadDia = 6.0 + HoleWindage;
    DriveBoltHeadRadius = DriveBoltHeadDia/2;
    DriveBoltWeb = 4.5;					// leave this on block for 12 mm bolts
    
    HBPNutDia = 4.0;					// HBP mounting nut in middle of idler
    HBPNutRadius = HBPNutDia/2;
    HBPNutRecess = 0.5;					//  ... pocket for corner of nut
    HBPNutZOffset = -10.0;				//  ... below bottom of HBP platform
    
    BeltWidth = 7.0;					// drive belt slots
    BeltThick = 1.2;					//  ... backing only, without teeth
    BeltZOffset = -22.5;				//  ... below bottom of HBP platform
    
    // Bearing locations
    
    Preload = 0.0;						// positive to add pressure on lower bearing
    
    TopZ = RodRadius + BearingOD/2;
    BottomZ = Preload - TopZ;
    
    // Follower dimensions
    
    BlockWidth = 28.0;					// along X axis, must clear bolts in idler
    BlockHeight = RodDia + 2*BearingOD - Preload;
    BlockThick = (RodClearSide + RodRadius) - BearingThick/2 - BearingStemLength;
    
    BlockHeightPad =  RodClearTop - BearingOD;
    
    echo(str("Block Height: ",BlockHeight));
    echo(str("Block Height Pad: ",BlockHeightPad));
    echo(str("Block Thick: ",BlockThick));
    
    BottomPlateWidth = 10.0;
    BottomPlateThick = 5.0;
    
    BlockTop = RodRadius + RodClearTop;
    
    BlockOffset = BlockThick/2 + BearingThick/2 + BearingStemLength;
    
    // Construct the follower block with
    
    module Follower() {
    
      difference() {
    	union() {
    	  translate([0,BlockOffset,0])
    		difference() {
    		  union(){
    			cube([BlockWidth,BlockThick,BlockHeight],center=true);
    			translate([0,0,(BlockHeight + BlockHeightPad)/2])
    			  cube([BlockWidth,BlockThick,BlockHeightPad],center=true);
    		  }
    		  for(x=[-1,1]) for(z=[0,1])
    			  translate([x*DriveHolesX/2,
    						Protrusion/2,
    						(BlockHeight/2 + BlockHeightPad + DriveHoleZOffset - z*DriveHolesZ)])
    				rotate([90,0,0])
    				  cylinder(r=DriveBoltRadius,
    							h=(BlockThick + Protrusion),
    							center=true);
    			for(x=[-1,1]) for(z=[0,1])
    			  translate([x*DriveHolesX/2,
    						(-(DriveBoltWeb + Protrusion)/2),
    						(BlockHeight/2 + BlockHeightPad + DriveHoleZOffset - z*DriveHolesZ)])
    				rotate([90,0,0])
    				  cylinder(r=DriveBoltHeadRadius,
    							h=(BlockThick - DriveBoltWeb + Protrusion),
    							center=true);
    		  translate([0,
    					((BlockThick - BeltThick + Protrusion)/2),
    					(BlockHeight/2 + BlockHeightPad + BeltZOffset)])
    			cube([(BlockWidth + 2*Protrusion),
    				 (BeltThick + Protrusion),
    				 BeltWidth],center=true);
    		  }
    
    	  translate([0,BearingStemLength/2 + BearingThick/2,TopZ])
    		rotate([90,0,0])
    			cylinder(r=BearingStemRadius,h=BearingStemLength,center=true,$fn=10);
    	  translate([0,BearingStemLength/2 + BearingThick/2,BottomZ])
    		rotate([90,0,0])
    		  cylinder(r=BearingStemRadius,h=BearingStemLength,center=true,$fn=10);
    	}
    
    	translate([0,(BlockOffset - BearingStemLength/2),TopZ])
    	  rotate([90,0,0])
    		cylinder(r=BearingBoltRadius,
    				h=(BlockThick + BearingStemLength + 2*Protrusion),
    				center=true);
    	translate([0,(BlockOffset - BearingStemLength/2),BottomZ])
    	  rotate([90,0,0])
    		cylinder(r=BearingBoltRadius,
    				h=(BlockThick + BearingStemLength + 2*Protrusion),
    				center=true);
    
    	translate([0,
    			  (BlockThick + BearingStemLength + BearingThick/2 - (HBPNutRecess - Protrusion)/2),
    			  (BlockHeightPad + BlockHeight/2 + HBPNutZOffset)])
    	  rotate([90,0,0])
    		cylinder(r=HBPNutRadius,h=(HBPNutRecess + Protrusion),center=true);
    
    	rotate([0,90,0])
    	  cylinder(r=(RodRadius + RodClearCirc),h=RodLength,center=true,$fn=32);
    
      }
    }
    
    // Arrange things for construction
    
    if (Build)
    	translate([0,(-BlockHeightPad/2),(BlockOffset + BlockThick/2)])
    	  rotate([-90,0,0])
    		Follower();
    
    // Arrange things for convenient inspection
    
    if (!Build) {
    
      Follower();
    
      translate([0,0,TopZ])
    	rotate([90,0,0])
    	  #cylinder(r=BearingOD/2,h=BearingThick,center=true,$fn=32);
    
      translate([0,0,BottomZ])
    	rotate([90,0,0])
    	  #cylinder(r=BearingOD/2,h=BearingThick,center=true,$fn=32);
    
      rotate([0,90,0])
    	  #cylinder(r=RodDia/2,h=RodLength,center=true,$fn=32);
    
    }
    

    [Update: It’s installed and works wonderfully!]

    [Update: You should use carmiac’s version, which prints better.]