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

  • Printed Chain Mail: Subtractive Model

    This is a subtractive version of Zomboe’s Chainmail, built by removing chunks from a solid rectangle the size of one link:

    Chain Mail Link - Subtractive
    Chain Mail Link – Subtractive

    Until what’s left is, indeed, a single link:

    Chain Mail Link
    Chain Mail Link

    The pillars in the original model weren’t nearly large enough; Slic3r omitted them from the G-Code. They’re now as wide as the bars and √2 times that width long, which means they actually get a bit of fill.

    Then a pair of nested loops replicates that link across the entire fabric:

    Chain Mail Sheet
    Chain Mail Sheet

    That technique didn’t work with Skeinforge (because it sent the nozzle scampering all over each layer, knocking things loose) and it didn’t work with Slic3r 0.9.8 (because it had problems with bridges), but Slic3r 0.9.10, hot from github, produced good results:

    Chain Mail - as built
    Chain Mail – as built

    There were some strings connecting adjacent links, but a few minutes with a flush cutter solved that. Retraction was 1 mm at 80 mm/s = 480 mm/min, which seems to work fine in other contexts, but adjacent links fell inside the 1 mm minimum distance setting I’d been using. That’s now down to 0.5 mm, which should suffice for nearly everything.

    The M2 sounded like I was hitting it with a hammer: each of the 480 pillar layers (!) required a quick squirt and a retraction, followed by a 500 mm/s move. Worked fine and didn’t miss a step anywhere along the way.

    A view from the bottom shows it really is flexy:

    Chain Mail - bottom
    Chain Mail – bottom

    I used zero perimeter threads on these tiny links, which means you can see the ripply edges of the second layer that was crosswise to the length of the link bars. Next time, I’ll try one perimeter thread, which should smooth that out.

    The links stuck to the glass like they were glued, which, indeed, they were: White Rain Unscented Extra Hold Hairspray in a pump bottle (either they didn’t have Maximum Hold pump spray or I couldn’t see it). I’m not a big fan of aerosol anything and decided to try wiping the stuff across the platform glass, rather than filling the air with a fine mist and getting some on the glass. Seems to work, but more examples are needed…

    The Slic3r configuration:

    ; generated by Slic3r 0.9.10-dev on 2013-04-17 at 17:28:11
    ; layer_height = 0.25
    ; perimeters = 0
    ; top_solid_layers = 3
    ; bottom_solid_layers = 3
    ; fill_density = 0.10
    ; perimeter_speed = 100
    ; infill_speed = 100
    ; travel_speed = 500
    ; nozzle_diameter = 0.35
    ; filament_diameter = 1.73
    ; extrusion_multiplier = 0.9
    ; perimeters extrusion width = 0.40mm
    ; infill extrusion width = 0.40mm
    ; solid infill extrusion width = 0.40mm
    ; top infill extrusion width = 0.40mm
    

    The OpenSCAD source code, with the platform marker cubes expanded to cover the M2’s glass plate:

    // Chain Mail Sheet
    // For Slic3r and M2 printer
    // Ed Nisley KE4ZNU - Apr 2013
    
    Layout = "Build";			// Link Build
    
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.2;
    
    Protrusion = 0.1;			// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Dimensions
    
    BarWidth = 5 * ThreadWidth;
    BarThick = 3 * ThreadThick;
    
    LinkSquare = IntegerMultiple(13.0,ThreadWidth);
    LinkHeight = 2*BarThick + 1*BarThick;
    
    LinkOutDiagonal = LinkSquare*sqrt(2) - BarWidth;
    LinkInDiagonal = LinkSquare*sqrt(2) - 2*(BarWidth/2 + BarWidth*sqrt(2));
    
    echo("Outside diagonal: ",LinkOutDiagonal);
    
    SheetSizeX = 75;
    SheetSizeY = 100;
    
    NumLinksX = 1 + floor(SheetSizeX / LinkOutDiagonal);
    NumLinksY = 1 + floor(SheetSizeY / LinkOutDiagonal);
    
    echo("Links X: ",NumLinksX," Y: ",NumLinksY);
    
    LinkSpacing = 0.59 * LinkOutDiagonal;
    
    //-------
    
    module ShowPegGrid(Space = 10.0,Size = 1.0) {
    
      RangeX = floor(95 / Space);
      RangeY = floor(125 / Space);
    
    	for (x=[-RangeX:RangeX])
    	  for (y=[-RangeY:RangeY])
    		translate([x*Space,y*Space,Size/2])
    		  %cube(Size,center=true);
    
    }
    
    //-------
    // Create basic link
    
    module Link() {
    
    	rotate(45)
    		difference(convexity=2) {
    			translate([0,0,LinkHeight/2]) {
    				difference(convexity=2) {
    					intersection() {		// outside shape
    						cube([LinkSquare,LinkSquare,LinkHeight],center=true);
    						rotate(45)
    							cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight],center=true);
    					}
    					intersection() {		// inside shape
    						cube([(LinkSquare - 2*BarWidth),(LinkSquare - 2*BarWidth),(LinkHeight + 2*Protrusion)],center=true);
    						rotate(45)
    							cube([LinkInDiagonal,LinkInDiagonal,(LinkHeight +2*Protrusion)],center=true);
    					}
    				}
    			}
    			for (i=[-1,1]) {				// create bars
    				translate([0,-i*(sqrt(2)*BarWidth/2),BarThick])
    					rotate(45 + 180*(i+1)/2)
    						cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight]);
    				translate([i*(sqrt(2)*BarWidth/2),0,-BarThick])
    					rotate(135 + 180*(i+1)/2)
    						cube([LinkOutDiagonal,LinkOutDiagonal,LinkHeight]);
    			}
    		}
    }
    
    //-------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "Link") {
      Link();
    }
    
    if (Layout == "Build") {
    	for (ix=[-(NumLinksX/2 - 0):(NumLinksX/2 - 1)])
    		for (iy=[-(NumLinksY/2 - 0):(NumLinksY/2 - 1)])
    			translate([ix*LinkSpacing + LinkSpacing/2,iy*LinkSpacing + LinkSpacing/2,0])
    				Link();
    }

    [Update: The original doodles, in case I ever need the background info:]

    Chain Mail - Link Dimension Doodles
    Chain Mail – Link Dimension Doodles
  • Makergear M2: Z-minimum Switch

    The best orientation for the Z-minimum switch seems to be slightly angled back:

    M2 - Z min limit switch
    M2 – Z min limit switch

    I used an M4x0.7 socket head cap screw for the height adjustment, with a Nylock nut below the stage:

    M2 - Z min limit screw
    M2 – Z min limit screw

    The assembly instructions show a hex head screw, but the item numbers don’t match the BOM listings. The SHCS lets me hold it firmly in position with the ball-end driver provided in the M2 tool kit while adjusting it:

    • 1/4 turn (the handle is square-ish) = 0.7/4 = 0.175 mm
    • 1/6 turn (the shaft is hex) = 0.12 mm
    • 1/12 turn (you can do it!) = 0.06mm
    • less than that is probably fooling yourself.

    I printed a pair of tomlombardi’s  7 mm wrenches, which work well for adjusting the Nylock nut underneath the Z axis stage:

    M2 - 7 mm wrenches
    M2 – 7 mm wrenches

    The left end of the top wrench didn’t adhere to the glass plate, but the business end of the wrench came out OK.

    I adjusted the screw to trip the switch with the nozzle 1.0 mm above the platform, then feed that offset in using a G92 Z1.0 instruction in my customized Start G-Code.

    However, the most accurate way to set the switch height involves measuring the as-printed thickness of the skirt extrusion around the object. The average value should be 0.25 mm (for my current slic3r settings, anyhow) and all sides should be equally thick: adjust the screw to change the average and adjust the platform screws to remove any tilt. You’ll quickly accumulate a pile of skirt threads, but they make good tchotchkes when you give a presentation on your new toy:

    M2 skirt extrusions
    M2 skirt extrusions

    You could fiddle with the G92 value to make the average thickness come out right, but I favor making the machine as accurate as possible, so that the software begins from a known-good mechanical setting.

  • CO2 Capsule Fins: 16 Gram Threaded Edition

    I redesigned those fins to fit 16 gram threaded CO2 cartridges in PLA on the M2:

    M2 CO2 capsule fins
    M2 CO2 capsule fins

    The original intent was to have both the square box and the internal X struts be exactly two threads wide, but the two fins on the sides show slic3r had some trouble doing that. I finally made them wide enough for a little fill, which produced the rather chunky version attached to the capsule.

    A closer look while printing shows the fin width:

    M2 - CO2 Capsule Fins - on platform
    M2 – CO2 Capsule Fins – on platform

    It was actually a present to go along with a box of the capsules, so I printed just one in a bit of a hurry. He probably couldn’t get them back across the border, but it’s the thought that counts, right?

    The slic3r header:

    ; generated by Slic3r 0.9.8 on 2013-04-04 at 20:53:07
    
    ; layer_height = 0.25
    ; perimeters = 1
    ; top_solid_layers = 3
    ; bottom_solid_layers = 3
    ; fill_density = 0.10
    ; perimeter_speed = 100
    ; infill_speed = 200
    ; travel_speed = 500
    ; scale = 1
    ; nozzle_diameter = 0.35
    ; filament_diameter = 1.70
    ; extrusion_multiplier = 0.9
    ; perimeters extrusion width = 0.40mm
    ; infill extrusion width = 0.40mm
    ; first layer extrusion width = 0.39mm
    

    The OpenSCAD source has dimensions for various capsules as commented-out cruft, so your mileage may vary:

    // CO2 capsule tail fins
    // Ed Nisley KE4ZNU - Apr 2013
    
    Layout = "Build";            // Show Build FinBlock Cartridge Fit
    
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +0 shells and 3 solid layers
    
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    
    HoleWindage = 0.2;
    
    Protrusion = 0.1;            // make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Capsule dimensions
    
    //- 12 gram capsule
    
    /*
    BodyDia = 18.70;
    BodyRad = BodyDia/2;
    
    BodyLength = 53.0;                        // between hemispherical endcap centers
    BodyBaseLength = 21;                    // tip to endcap center
    
    TipDia = 7.40;
    TipRad = TipDia/2;
    TipLength = IntegerMultiple(4.0,ThreadThick);
    
    FilletLength = 5.0;                        // fillet between tip and cone
    FilletTop = TipLength + FilletLength;
    
    FilletBaseDia = 8.60;
    FilletBaseRad= FilletBaseDia/2;
    FilletTopDia = 9.5;
    FilletTopRad = FilletTopDia/2;
    
    ConeTop = 16.0;                            // tip to tangent with endcap
    ConeLength = ConeTop - FilletTop;
    */
    
    //- 16 gram capsule
    
    /*-- unthreaded
    BodyDia = 22.0;
    BodyRad = BodyDia/2;
    
    BodyLength = 53.0;                        // between hemispherical endcap centers
    BodyBaseLength = 27;                    // tip to endcap center
    
    TipDia = 8.30;
    TipRad = TipDia/2;
    TipLength = IntegerMultiple(7.4,ThreadThick);
    
    FilletLength = 8.3;                        // fillet between tip and cone
    FilletTop = TipLength + FilletLength;
    
    FilletBaseDia = 8.6;
    FilletBaseRad= FilletBaseDia/2;
    FilletTopDia = 18.1;
    FilletTopRad = FilletTopDia/2;
    
    ConeTop = 23.0;                            // tip to tangent with endcap
    ConeLength = ConeTop - FilletTop;
    */
    
    /*-- threaded */
    BodyDia = 22.0;
    BodyRad = BodyDia/2;
    
    BodyLength = 53.0;                        // between hemispherical endcap centers
    BodyBaseLength = 27;                    // tip to endcap center
    
    TipDia = 9.4;
    TipRad = TipDia/2;
    TipLength = IntegerMultiple(12.0,ThreadThick);
    
    FilletLength = 5.0;                        // fillet between tip and cone
    FilletTop = TipLength + FilletLength;
    
    FilletBaseDia = TipDia;
    FilletBaseRad= FilletBaseDia/2;
    FilletTopDia = 15.1;
    FilletTopRad = FilletTopDia/2;
    
    ConeTop = 23.0;                            // tip to tangent with endcap
    ConeLength = ConeTop - FilletTop;
    
    echo(str("Cone Length: ",ConeLength));
    
    IntersectZ = ConeTop;                    // coordinates of intersect tangent
    IntersectX = sqrt(pow(BodyRad,2) - pow(BodyBaseLength - ConeTop,2));
    
    echo(str("IntersectZ: ",IntersectZ));
    echo(str("IntersectX: ",IntersectX," dia: ",2*IntersectX));
    
    /* */
    
    //-------
    // Fin dimensions
    
    FinThick = 2*ThreadWidth;            // outer square
    StrutThick = 3*ThreadWidth;            // diagonal struts
    
    FinSquare = 1.25*BodyDia;
    FinTaperLength = sqrt(2)*FinSquare/2 - sqrt(2)*FinThick - ThreadWidth;
    
    FinBaseLength = 1.5*TipLength;
    FinFlatTop = ConeTop;
    
    //-------
    
    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);
    
    }
    
    //-------
    // CO2 cartridge outline
    
    module Cartridge() {
    
    $fn = 48;
    
    union() {
    translate([0,0,BodyBaseLength]) {
    cylinder(r=BodyDia/2,h=BodyLength);
    translate([0,0,BodyLength])
    sphere(r=BodyRad);
    }
    
    intersection() {
    translate([0,0,BodyBaseLength])
    sphere(r=BodyRad);
    
    union() {
    translate([0,0,(TipLength + FilletLength+ConeLength)])
    cylinder(r=BodyRad,h=(BodyBaseLength - ConeLength));
    translate([0,0,(TipLength + FilletLength)])
    cylinder(r1=FilletTopRad,r2=IntersectX,h=(ConeLength + Protrusion));
    translate([0,0,TipLength])
    cylinder(r1=FilletBaseRad,r2=FilletTopRad,h=(FilletLength + Protrusion));
    }
    
    }
    
    translate([0,0,FilletTop])
    cylinder(r1=FilletTopRad,r2=IntersectX,h=ConeLength);
    
    translate([0,0,TipLength])
    cylinder(r1=FilletBaseRad,r2=FilletTopRad,h=(FilletLength + Protrusion));
    
    translate([0,0,-Protrusion])
    PolyCyl(TipDia,(TipLength + 2*Protrusion));
    
    }
    
    }
    
    //-------
    // Diagonal fin strut
    
    module FinStrut() {
    intersection() {
    rotate([90,0,45])
    translate([0,0,-StrutThick/2])
    linear_extrude(height=StrutThick)
    polygon(points=[
    [0,0],
    [FinTaperLength,0],
    [FinTaperLength,FinBaseLength],
    [0,(FinBaseLength + FinTaperLength)]
    ]);
    translate([0,0,FinFlatTop/2])
    cube([2*FinSquare,2*FinSquare,FinFlatTop], center=true);
    }
    }
    
    //-------
    // Fin outline
    
    module FinBlock() {
    $fn=12;
    union() {
    translate([0,0,FinBaseLength/2])
    difference() {
    intersection() {
    minkowski() {
    cube([FinSquare - 2*ThreadWidth,
    FinSquare - 2*ThreadWidth,
    FinBaseLength],center=true);
    cylinder(r=FinThick,h=Protrusion,$fn=8);
    }
    cube([2*FinSquare,2*FinSquare,FinBaseLength],center=true);
    }
    difference() {
    cube([(FinSquare - 2*FinThick),
    (FinSquare - 2*FinThick),
    (FinBaseLength + 2*Protrusion)],center=true);
    for (Index = [0:3])
    rotate(Index*90)
    translate([(FinSquare/2 - FinThick),(FinSquare/2 - FinThick),0])
    cylinder(r=2*StrutThick,h=(FinBaseLength + 2*Protrusion),center=true,$fn=16);
    }
    }
    for (Index = [0:3])
    rotate(Index*90)
    FinStrut();
    cylinder(r=IntegerMultiple(TipDia/2 + 4*ThreadWidth,ThreadWidth),h=TipLength);
    }
    }
    
    //-------
    // Fins
    
    module FinAssembly() {
    
    difference() {
    FinBlock();
    translate([0,0,2*ThreadThick])                // add two layers to close base cylinder
    Cartridge();
    }
    
    }
    
    module FinFit() {
    
    translate([0,0.75*BodyBaseLength,2*ThreadThick])
    rotate([90,0,0])
    difference() {
    translate([-FinSquare/2,-2*ThreadThick,0])
    cube([IntegerMultiple(FinSquare,ThreadWidth),
    4*ThreadThick,
    1.5*BodyBaseLength]);
    translate([0,0,5*ThreadWidth])
    Cartridge();
    }
    
    }
    
    //-------
    // Build it!
    
    ShowPegGrid();
    
    if (Layout == "FinStrut")
    FinStrut();
    
    if (Layout == "FinBlock")
    FinBlock();
    
    if (Layout == "Cartridge")
    Cartridge();
    
    if (Layout == "Show") {
    FinAssembly();
    color("LightYellow") Cartridge();
    }
    
    if (Layout == "Fit")
    FinFit();
    
    if (Layout == "Build")
    FinAssembly()
    
  • Makergear M2: Filament Guide Tube Friction

    While changing to black filament, I measured the force required to pull the (natural PLA) filament through the translucent guide tube arching over the M2’s chassis from the spool to the extruder:

    M2 Electronics Case on chassis
    Makergear M2 3D Printer with cardboard on build platform

    A strike-anywhere kitchen match (bet you can’t buy those any more!) provided more than enough heat to bend the end of the filament into a loop suitable for the pull scale:

    M2 - Filament loop for pull test
    M2 – Filament loop for pull test

    The results:

    • Tube reasonably straight: 0.5 lb = 2.2 N
    • Tube arched to middle of X axis: 1 lb = 4.5 N
    • Tube sharply bent to X axis nearest spool: 1.5 lb = 6.7 N

    The force increases slightly while tugging filament off the spool, as the spool does not rotate freely on the printed arm jutting out from the frame, but those numbers are in the right ballpark.

    The effective diameter of the extruder drive gear is about 11.5 mm, so overcoming the tube friction requires somewhere between 10 and 40 mN·m of torque. That’s applied at the one point in the whole system most likely to show the result of uneven loading, because it directly affects the pressure of the molten plastic behind the nozzle.

    That’s considerable motivation to get rid of the filament guide tube…

  • Makergear M2: Pronterface Configuration

    I use Kliment’s Pronterface for printer control: simplicity with enough knobs.

    The .pronsolerc file:

    set port /dev/ttyACM0
    set baudrate 115200
    set build_dimensions 200x240x195-100-120+0
    set temperature_abs 200
    set last_bed_temperature 70.0
    set last_temperature 155.0
    set xy_feedrate 30000
    set z_feedrate 2500
    set e_feedrate 300
    set last_file_path /mnt/bulkdata/Project Files/Thing-O-Matic/Calibration
    set temperature_pla 165
    set preview_grid_step1 10
    set preview_grid_step2 20.0
    set preview_extrusion_width 0.4
    set bedtemp_pla 70
    
    

    Line 3 sizes the preview and offsets the XY=0 origin to the center of the plot.

    The 200 mm X axis dimension is slightly larger than the actual 195 mm buildable area on the platform, but if the object gets that close to the maximum size, this isn’t the place to discover it.

    The 240 mm Y axis dimension is slightly shorter than the actual 250 mm buildable area and slightly larger than the distance between the snouts of the bulldog clips holding the glass plate to the heater. In this case, the object can slightly exceed the preview size if it fits between the clips.

    Lines 12 and 13 produce a relatively coarse grid that’s both meaningful and easy on the eyes, with the XY dimensions in Line 3 producing a major grid line crossing at the origin where it should be:

    M2 Pronterface - screen shot
    M2 Pronterface – screen shot
  • Makergear M2: Bridging Test Object

    The overhang quality is on the low side of OK, but that’s without any particular configuration tweaking:

    M2 - Overhang test - overhang view
    M2 – Overhang test – overhang view

    A few strands didn’t quite anchor to the far side of the overhang opening and hang down inside:

    M2 - Overhang test - overhang detail
    M2 – Overhang test – overhang detail

    Curiously, the slab on the other side transitioned from the usual 0.10 honeycomb fill to completely solid about half way up:

    M2 - Overhang test - slab view
    M2 – Overhang test – slab view

    As with all the other objects, there’s no stringing or oozing. Looks good to me!

    The slic3r configuration, which doesn’t show the bridge speed of 100 mm/s:

    ; generated by Slic3r 0.9.8 on 2013-04-08 at 19:55:09
    
    ; layer_height = 0.25
    ; perimeters = 1
    ; top_solid_layers = 3
    ; bottom_solid_layers = 3
    ; fill_density = 0.10
    ; perimeter_speed = 100
    ; infill_speed = 200
    ; travel_speed = 500
    ; scale = 1
    ; nozzle_diameter = 0.35
    ; filament_diameter = 1.70
    ; extrusion_multiplier = 0.9
    ; perimeters extrusion width = 0.40mm
    ; infill extrusion width = 0.40mm
    ; first layer extrusion width = 0.39mm
    

    The OpenSCAD source came directly from Starno’s object on Thingiverse.

  • Makergear M2: Post and Hole Calibration Test Objects

    Despite the profusion of surface-finish and print quality test objects, I really care about the dimensions of a 3D printed object, because I tend to build widgets rather than art objects. These two objects, from walter’s Hole and Column Test Print, produce calibrated holes and columns from 0.20 mm to 10.00 mm in diameter, incrementing by 0.20 mm, that should slip neatly together:

    M2 - walter hole-column test
    M2 – walter hole-column test

    Of course, they didn’t, but they came surprisingly close for a first attempt.

    The 0.20 and 0.40 posts simply aren’t there, because they’re too small to print with a 0.35 mm diameter nozzle. The 0.60 through 1.40 mm posts were present, albeit fugly, and posts larger than that looked increasingly better.

    Although all the holes were present, in the sense that you could see a disturbance in the top and bottom infill pattern, the first visibly open hole appeared at the 0.80 mm spot… and it was immeasurably small. Some holes had misplaced perimeter strands stretching across the openings, which is probably due to excessive speed from my fiddling around with the numbers.

    Measuring them with a digital caliper, with no effort at finding the best orientation, then slapping the data into a Libreoffice spreadsheet, produces an interesting graph:

    M2 - Initial Hole and Post Diameter Calibration
    M2 – Initial Hole and Post Diameter Calibration

    Above about 3 mm diameter: posts are 0.1 mm too small and holes are 0.3 mm too small. Around 2 mm, posts are too big and holes are way too small. What’s important: above maybe 2.5 mm, the error is essentially constant and does not scale with diameter, so a simple Finagle Constant (or two) can solve (most of) the problem.

    Some experiments involving slic3r’s small-perimeter speed seem in order; it was 25 mm/s for these pieces.

    More care in measurement would produce better answers, but the real question is whether you can produce holes and columns with known sizes; the answer (as expected) remains “with some care”. That’s not surprising; I expect to have an M2 + PLA version of the small hole diameter Finagle Constant that I’ve been using with Skeinforge + Thing-O-Matic; the correction will certainly fall in the same ballpark.

    The slic3r configuration:

    ; generated by Slic3r 0.9.8 on 2013-04-01 at 16:20:49
    
    ; layer_height = 0.25
    ; perimeters = 1
    ; top_solid_layers = 3
    ; bottom_solid_layers = 3
    ; fill_density = 0.10
    ; perimeter_speed = 100
    ; infill_speed = 300
    ; travel_speed = 500
    ; scale = 1
    ; nozzle_diameter = 0.35
    ; filament_diameter = 1.70
    ; extrusion_multiplier = 0.9
    ; perimeters extrusion width = 0.40mm
    ; infill extrusion width = 0.40mm
    ; first layer extrusion width = 0.39mm
    

    The source code comes from the Thingiverse customizer as bare G-Code, so there’s not much point in reproducing it here.