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

  • Effect of First Layer Height on Holes

    This polyholes test piece started with the nozzle 0.45 to 0.50 mm above the build plate. The threads around the holes didn’t bond well to the plate, dragged slightly inward of their intended position, and didn’t join to their neighbors or the infill.

    Polyholes 0.33 mm layer - 0.5 mm starting height
    Polyholes 0.33 mm layer – 0.5 mm starting height

    Adjusting the nozzle downward to start at 0.28 to 0.39 above the plate produced this result:

    Polyholes 0.33 mm layer - 0.3 mm starting height
    Polyholes 0.33 mm layer – 0.3 mm starting height

    So, in round numbers, changing the nozzle’s height by 0.2 mm makes all the difference for an object printed with 0.33 mm layer thickness. That’s why I’ve been so focused on getting a flat, level build platform: a mere 0.2 mm is 60% of the layer thickness!

    The perimeter and additional threads around the holes are now where they should be, plus they’re all bonded to each other and the infill.

    I think Skeinforge positions the center of the perimeter thread at the very outside edge of the object, which means objects are one thread width larger than they should be and holes are one thread width smaller. The HoleWindage parameter I added to nophead’s code compensates for that, although you must manually add it to / subtract it from the critical dimensions.

    [Update: SF does the right thing. See the comments.]

    The larger holes in the second test piece (printed with the correct starting height) came out just about spot on, the mid-size holes are 0.25 mm too large, and the smaller holes are pretty close in absolute terms (and awful in relative terms). There’s no way to get perfect holes, but these are certainly good enough for most purposes and repeatable enough to not require much in the way of tweakage.

    The polyholes sheet is three layers thick. It presents quite an infill challenge, because there’s not much room around the holes (witness the open areas where the available space drops below one thread width) and the Fill plugin doesn’t lay the infill down from one end to the other. The myriad stops, starts, and movements presents many opportunities for blobs, of which you’ll see quite a few.

    Feed 40 mm/s, flow 2 rpm, 210 °C / 120 °C. First layer at 25% feed & flow. Reversal set for 20 rpm, 90 ms in & out, and no early action.

    I measured the thickness of the Outline thread around the actual objects, as described there, to get the first layer thickness. The starting heights for the first piece are the middle array there. These are the heights for the second piece, in units of 0.01 mm:

    33 28 29
    31 28
    31 31
    32 39
    28 32 37

    The OpenSCAD source, which is pretty much directly from nophead:

    // nophead polyholes
    // Modified to use parameters and add diameter Finagle Constant
    
    HoleWindage = 0.6;
    
    NumHoles = 9;
    
    PlateZ = 1.0;
    Protrusion = 0.1;
    HoleZ = PlateZ + 2*Protrusion;
    
    module polyhole(h, d) {
        n = max(round(2 * d),3);
        rotate([0,0,180])
            cylinder(h = h, r = (d / 2) / cos (180 / n), $fn = n);
    }
    
    difference() {
    	cube(size = [NumHoles*10,27,PlateZ]);
        union() {
        	for(i = [1:NumHoles]) {
                translate([(i * i + i)/2 + 3 * i , 8,-Protrusion])
                    polyhole(h = HoleZ, d = (i + HoleWindage));
    
                assign(d = i + 0.5)
                    translate([(d * d + d)/2 + 3 * d, 19,-Protrusion])
                        polyhole(h = HoleZ, d = (d + HoleWindage));
        	}
        }
    }
    
  • Thing-O-Matic: X Axis Rod Follower Installed

    The prototype X Rod Follower turned out to be pretty good fit, after I filed a slot in the back for the belt clamp. The bearings wound up 1.5 mm too close to the centerline, but a pair of #4 washers on each post solved that problem. The tweaked OpenSCAD source below should produce a drop-in replacement.

    X Axis follower in place
    X Axis follower in place

    It’s important to center the bearings on the rod, because they’re designed to support only radial loads. In a normal application the bearings live in a slip-fit pocket that supports the entire outer race, but here an off-center point contact applies an axial force and misaligns the bearing races. They can’t handle axial forces at all: you (well, I) can easily feel the difference an axial millimeter makes.

    With the follower in place, the force required to move the beltless X stage dropped from 0.75 pounds to zero: the stage slides back and forth across the entire length of the rods with a finger tap! The mechanical overconstraint on rods simply Went Away, pretty much as I expected.

    [Update: In case it’s not obvious from the picture, you must remove both bronze bushings from the front of the X stage when you install this Follower. Leave the back pair in place.]

    After installing and tensioning the drive belt, the stage still requires about 1 pound = 0.5 kg = 5 N to push along the rods, but now there’s no mechanical binding at any point along the way. That’s with the motor unplugged from the driver; you don’t want to count the effort required to light the LEDs!

    Now, to reassemble and realign the rest of the build platform again.

    The OpenSCAD source has only a few dimension numbers changed from the previous version, but here it is in one cut-n-paste lump:

    [Update: You should use carmiac’s version, which prints better. The original code says “rear guide rod follower” but it turned out to fit better on the front of the X stage.]

    // Thing-O-Matic X Stage front 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.7;					//  ... 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 + BearingStemLength + BearingThick/2;
    
    echo(str("Drive wall to rod center: ",BlockThick + BearingStemLength + BearingThick/2));
    
    // 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);
    
    }
    
  • Initial HBP + Aluminum Build Plate Alignment

    My intent with the modified HBP and removable aluminum build plate: get a stable, repeatable first layer height. That is where it all starts…

    The thin(ner) aluminum plate clamped to the Heater establishes the overall platform alignment. The G-Code routine at the bottom probes the height at nine locations across the plate, with me shoving a taper gage under the nozzle at each spot and writing down what I read. The accuracy seems to be around ±0.05 mm (pretty much / sorta kinda), based on the spread-out scale on the gage and a good feel for when the gage touches the nozzle.

    The results in mm above the sub-platform, after leveling the HBP with the adjusting bolts:

    3.5 3.4 3.3
    3.5 3.5 3.4
    3.4 3.5 3.6

    The 3.6 mm in the front right comes from the wiper hitting the Thermal Core insulation. I must trim that thing a bit!

    Apart from that, it’s as flat and level as you could possibly want.

    Measuring identical Outline extrusions with a max Z height = 116.5 mm and a 0.33 mm layer thickness on the three build plates produces these numbers, with units of 0.01 mm to save some typing:

    Plate 1
    42 38 35
    43 31
    43 33
    38 34
    37 33 32
    Plate 2
    37 33 31
    35 23
    33 21
    25 15
    19 16 17
    Plate 3
    38 30 29
    37 28
    34 27
    32 31
    28 29 28

    Plate 2 may have trapped a bit of grit underneath the near edge; sometimes the dissolved ABS oozes around the edge or down a bolt head clearance hole to the underside, despite my best efforts.

    Apart from that, they’re about as flat and level as you could possibly want from a loose plate sitting atop a moving platform. While the difference between a 0.43 and a 0.31 mm layer is visibly obvious, I don’t know how to get the plate any more level than that… at least without an entirely different and much heavier mechanical structure.

    The real question comes down to repeatability: will the platform behave the same way under each extrusion, day in and day out, without requiring height adjustment for every object?

    I know a bit about tool height probing, but it’s not clear attaching a Z-minimum limit switch to the side of the HBP, perhaps under the Heater, would track the top surface of the plate with sufficient accuracy. I don’t like touching the nozzle to the build plate itself, because either one may have an insulating layer of ABS or a bit of grit or whatever that would prevent electrical contact. Ditto for optical sensing, which depends on not having any snot hanging from the nozzle.

    It’s definitely true that the platform height depends strongly on the HBP temperature. As nearly as I can tell, the build platform rises by about 0.5 mm as the Heater stabilizes the plates at 120 °C.

    More numbers to follow, as they accumulate.

    The height probing routine, in which you must set a suitable Z height for your very own machine:

    (Measure surface flatness)
    (MakerBot Thing-O-Matic with ABP and aluminum plate)
    (Tweaked for TOM 286)
    (Ed Nisley - KE4ZNU - Mar 2011)
    (-- The usual setup --)
    G21		(set units to mm)
    G90		(set positioning to absolute)
    (**** home axes ****)
    G162 Z F1500	(home Z to get nozzle out of danger zone)
    G161 Y F4000	(retract Y to get X out of front opening)
    G161 X F4000	(now safe to home X)
    G92 X-53.0 Y-59.0	(set XY coordinate zeros)
    G92 Z116.5    (set Z for HBP with aluminum sheet platform)
    G0 X0 Y0 Z5.0
    (-- Begin probing --)
    G1 Z1.0		(center)
    G4 P9000
    G0 Z5.0
    G0 X-40.0	(left center)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 Y-50.0	(left front)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 X0.0		(mid front)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 X40.0	(right front)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 Y0.0		(right center)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 Y50.0	(right rear)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 X0.0		(mid rear)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 X-40.0	(left rear)
    G1 Z1.0
    G4 P9000
    G0 Z5.0
    G0 X0.0	Y0.0	(center again)
    G1 Z1.0
    G4 P9000
    (G0 Z5)
    
  • Monitoring Build Plate Leveling with the Outline Extrusion

    The Skeinforge Outline plugin draws a rectangle around the first perimeter layer of an object. I use that single-width, single-layer extrusion to monitor the height of the nozzle above the build platform and the tilt of the plate. The Outline extrusion will either peel off separately or come off as the film peels away from the plate when I twist the object off.

    These Outlines come from a variety of objects. The one in the lower left was a test case that I stopped after extruding only the Outline.

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

    I measure the Outline along each edge; larger objects provide three data points along each side of the build platform.

    The good part of this is that it reports the build platform’s behavior during an actual extrusion, so you can keep an eye on whether it’s drifting out of alignment. The aluminum plates present a sufficiently flat surface that any variations will be due to a non-level HBP or an off-calibration Z-axis.

    These numbers from around a large Outline told me that I should tweak the Z axis height down by 0.1 mm to increase the first layer thickness back to about 0.33 mm. The lower-right corner was slightly thicker because the wiper hit the Thermal Core insulation.

    0.24 0.22 0.17
    0.27 0.17
    0.27 0.22
    0.28 0.32
    0.22 0.21 0.24

    Given those values, I can tweak the leveling screws to adjust the platform tilt. What I don’t have at this point is any long-term record of how consistent my hacked HBP will be. But at least I’ve got numbers!

  • 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…

  • 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.