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.

Author: Ed

  • Quilting Hexagon Template Generator

    Quilting Hexagon Template Generator

    Mary took on the task of finishing a hexagonal quilt from pieced strips, only to discover she’ll need several more strips and the myriad triangles required to turn hexagons into strips. The as-built strips do not match any of the standard pattern sizes, which meant ordinary templates were unavailing. I offered to build a template matching the (average) as-built hexagons, plus a triangle template based on those dimensions.

    Wikipedia has useful summaries of hexagon and equilateral triangle geometry and equations.

    Quilters measure hexes based on their finished side length, so a “1 inch hex” has sides measuring 1 inch, with the seam allowance extending ¼ inch beyond the sides. It’s difficult to measure finished sides with sufficient accuracy, so we averaged the side-to-side distance across several hexes.

    Some thrashing around produced a quick-and-dirty check piece that matched (most of) the stack of un-sewn hexes:

    Quilting Hexagon Cutting Template
    Quilting Hexagon Cutting Template

    That one came from a knockoff of the circle template, after some cleanup & tweakage, but failed user testing for not withstanding the side force from the rotary cutter blade. The inside and outside dimensions were correct, however, so I could proceed with some confidence I understood the geometry.

    Both the pattern width (the side-to-side distance across the inside of the hex) and the seam allowance appearing in the Customizer appear in inches, because that’s how things get measured outside the Basement Laboratory & Fabrication Facility:

    FinishedWidthInch = 2.75;
    FinishedWidth = FinishedWidthInch * inch;
    
    SeamAllowanceInch = 0.25;
    SeamAllowance = SeamAllowanceInch * inch;

    You feed in one side-to-side measurement and all other hex dimensions get calculated from that number; quilters default to a ¼ inch seam allowance. Remember, standard quilt hexes are measured by their side length, so just buy some standard templates.

    This is one of the few times I’ve needed triangle graph paper:

    Hex Quilting Template - geometry doodles
    Hex Quilting Template – geometry doodles

    After I gave up trying to get it right on square-grid paper, of course.

    Solidifying those relations:

    Quilting Hex Template - build layout
    Quilting Hex Template – build layout

    Then math got real:

    Hex Quilting Templates - on strips
    Hex Quilting Templates – on strips

    Both templates have non-skid strips to keep the fabric in place while cutting:

    Hex Quilting Template - grip strips
    Hex Quilting Template – grip strips

    I should have embossed the size on each template, but this feels like a one-off project and YAGNI. Of course, that’s how I felt about the circle templates, so maybe next time I’ll get it right.

    As it turned out, Mary realized she needed a template for the two half-triangles at the end of each row:

    Quilting Hex Template - half-triangle
    Quilting Hex Template – half-triangle

    It’s half of the finished size of the equilateral triangle on the right, with seam allowance added all around. The test scrap of fabric on the left shows the stitching along the hypotenuse of the half-triangle, where it joins to the end-of-row hexagon. Ideally, you need two half-triangle templates, but Mary says it’s easier to cut the fabric from the back side than to keep track of two templates.

    The family portrait now has three members:

    Quilting Hex Template - family
    Quilting Hex Template – family

    The OpenSCAD source code as a GitHub Gist:

    // Quilting – Hexagon Templates
    // Ed Nisley KE4ZNU – July 2020
    // Reverse-engineered to repair a not-quite-standard hexagon quilt
    // Useful geometry:
    // https://en.wikipedia.org/wiki/Hexagon
    /* [Layout Options] */
    Layout = "Build"; // [Build, HexBuild, HexPlate, TriBuild, TriPlate, EndBuild, EndPlate]
    //——-
    //- Extrusion parameters must match reality!
    // Print with 2 shells
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleFinagle = 0.2;
    HoleFudge = 1.00;
    function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;
    Protrusion = 0.1; // make holes end cleanly
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    inch = 25.4;
    //——-
    // Dimensions
    /* [Layout Options] */
    FinishedWidthInch = 2.75;
    FinishedWidth = FinishedWidthInch * inch;
    SeamAllowanceInch = 0.25;
    SeamAllowance = SeamAllowanceInch * inch;
    TemplateThick = 3.0;
    TriKnob = true;
    EndKnob = false;
    /* [Hidden] */
    FinishedSideInch = FinishedWidthInch/sqrt(3);
    FinishedSide = FinishedSideInch * inch;
    echo(str("Finished side: ",FinishedSideInch," inch"));
    CutWidth = FinishedWidth + 2*SeamAllowance;
    CutSide = CutWidth/sqrt(3);
    echo(str("Cut side: ",CutSide / inch," inch"));
    // Make polygon-circles circumscribe the target widths
    TemplateID = FinishedWidth / cos(180/6);
    TemplateOD = CutWidth / cos(180/6);
    /* [Hidden] */
    TriRadius = FinishedSide/sqrt(3);
    TriPoints = [[TriRadius,0],
    [TriRadius*cos(120),TriRadius*sin(120)],
    [TriRadius*cos(240),TriRadius*sin(240)]
    ];
    echo(str("TriPoints: ",TriPoints));
    EndPoints = [[TriRadius,0],
    [TriRadius*cos(120),TriRadius*sin(120)],
    [TriRadius*cos(120),0]
    ];
    echo(str("EndPoints: ",EndPoints));
    TipCutRadius = 2*(TriRadius + SeamAllowance); // circumscribing radius of tip cutter
    TipPoints = [[TipCutRadius,0],
    [TipCutRadius*cos(120),TipCutRadius*sin(120)],
    [TipCutRadius*cos(240),TipCutRadius*sin(240)]
    ];
    HandleHeight = 1 * inch;
    HandleLength = (TemplateID + TemplateOD)/2;
    HandleThick = IntegerMultiple(3.0,ThreadWidth);
    HandleSides = 12*4;
    StringDia = 4.0;
    StringHeight = 0.6*HandleHeight;
    DentDepth = HandleThick/4;
    DentDia = 15 * DentDepth;
    DentSphereRadius = (pow(DentDepth,2) + pow(DentDia,2)/4)/(2*DentDepth);
    KnobOD = 15.0; // Triangle handle
    KnobHeight = 20.0;
    //——-
    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=HoleAdjust(FixDia)/2,h=Height,$fn=Sides);
    }
    //——-
    // Hex template
    module HexPlate() {
    difference() {
    cylinder(r=TemplateOD/2,h=TemplateThick,$fn=6);
    translate([0,0,-Protrusion])
    cylinder(r=TemplateID/2,h=(TemplateThick + 2*Protrusion),$fn=6);
    }
    for (i=[1:6/2])
    rotate(i*60)
    translate([0,0,TemplateThick/2])
    cube([HandleLength,HandleThick,TemplateThick],center=true);
    }
    module HexHandle() {
    difference() {
    rotate([90,0,0])
    scale([1,HandleHeight/(TemplateOD/2),1])
    rotate(180/HandleSides)
    cylinder(d=HandleLength,h=HandleThick,center=true,$fn=HandleSides);
    translate([0,0,-HandleHeight])
    cube([2*TemplateOD,2*TemplateOD,2*HandleHeight],center=true);
    translate([0,HandleThick,StringHeight])
    rotate([90,090,0])
    rotate(180/8)
    PolyCyl(StringDia,2*HandleThick,8);
    for (j=[-1,1]) {
    translate([0,j*(DentSphereRadius + HandleThick/2 – DentDepth),StringHeight])
    rotate(180/48)
    sphere(r=DentSphereRadius,$fn=48);
    }
    }
    }
    module HexTemplate() {
    HexPlate();
    HexHandle();
    }
    //——-
    // Triangle template
    module TriPlate() {
    linear_extrude(height=TemplateThick)
    intersection() {
    offset(delta=SeamAllowance) // basic cutting outline
    polygon(points=TriPoints);
    rotate(180)
    polygon(points=TipPoints);
    }
    }
    module TriTemplate() {
    union() {
    if (TriKnob)
    cylinder(d=KnobOD,h=KnobHeight,$fn=HandleSides);
    TriPlate();
    }
    }
    //——-
    // End piece template
    module EndPlate() {
    linear_extrude(height=TemplateThick)
    intersection() {
    offset(delta=SeamAllowance) // basic cutting outline
    polygon(points=EndPoints);
    rotate(180)
    polygon(points=TipPoints);
    }
    }
    module EndTemplate() {
    union() {
    if (EndKnob)
    translate([0,(TriRadius/2)*sin(30),0])
    cylinder(d=KnobOD,h=KnobHeight,$fn=HandleSides);
    EndPlate();
    }
    }
    //——-
    // Build it!
    if (Layout == "HexPlate")
    HexPlate();
    if (Layout == "HexBuild")
    HexTemplate();
    if (Layout == "TriPlate")
    TriPlate();
    if (Layout == "TriBuild")
    TriTemplate();
    if (Layout == "EndPlate")
    EndPlate();
    if (Layout == "EndBuild")
    EndTemplate();
    if (Layout == "Build") {
    translate([1.5*TriRadius,-TriRadius,0])
    rotate(180/6)
    TriTemplate();
    translate([-1.5*TriRadius,-TriRadius,0])
    rotate(180/6)
    EndTemplate();
    translate([0,TemplateOD/2,0])
    HexTemplate();
    }

  • Pan Lid Handle Quieting

    Pan Lid Handle Quieting

    A surprisingly heavy stainless steel pan lid from the local ReStore has only one fault: when placed upside-down on the counter while we’re tending the pan contents, it will rock back and forth for nearly a minute. The lid has a rubberized insert for finger protection:

    Pan lid - original handle
    Pan lid – original handle

    However, the inserts cover only the side of the handle, so the metal arch rests on the counter. Setting it up in the shop let me scuff up the handle contact points:

    Pan lid - contact point
    Pan lid – contact point

    Then some Dremel grinding wheel work recessed the handle just barely below the inserts and changed the arch enough to keep it off the counter:

    Pan lid - recessed handle crest
    Pan lid – recessed handle crest

    The lid now stops rocking after a few seconds and is much quieter while doing so. It may require a bit more grinding, but it’s much better after this small intervention.

  • Miniblind Cord Caps: White PETG

    Miniblind Cord Caps: White PETG

    I managed to smash another miniblind cord cap and used white PETG this time around:

    Miniblind cord caps - white PETG
    Miniblind cord caps – white PETG

    It’s the same solid model as before, sliced with whatever improvements have transpired during the last four years.

    Made four of ’em, preemptively replaced the cap on the adjacent window, and tucked the last two away against future need.

  • Makergear M2 V4 Nozzle: Silicone Refresh

    Makergear M2 V4 Nozzle: Silicone Refresh

    After a year and a half, the silicone coat I’d applied to the M2’s nozzle had pretty much worn away, so I peeled off the remnants, buffed up the brass, and mushed on another coat:

    Makergear M2 V4 Nozzle - High-temp silicone coat
    Makergear M2 V4 Nozzle – High-temp silicone coat

    The coverage isn’t even, particularly in the direction I can neither see nor reach with the hot end still in the printer, but it’s way less hassle than recalibrating the Z=0 position. The very thin layer over the brass around the nozzle will vanish immediately on the skirt surrounding the first part.

    I should definitely recoat the nozzle more often, because PETG doesn’t stick to silicone nearly as well as it does to brass: a nice new coat makes the PETG burned-snot problem Just Go Away.

  • Harvesting 18650 Lithium Cells

    Harvesting 18650 Lithium Cells

    With a Dutchess County Household Hazardous Waste Collection Day coming up, I’ve been harvesting usable lithium cells from a variety of old batteries:

    Harvested 18650 3P lithium batteries
    Harvested 18650 3P lithium batteries

    The pile of 18650 3P blocks over on the right are some obviously corroded deaders and the lowest performers from these tests:

    Harvested 3P 18650 Packs
    Harvested 3P 18650 Packs

    I doubt they’ll get recycled, as there’s entirely too much overhead involved in dismantling boxes full of cells like these, but I hope they’ll get a decent burial somewhere.

  • Can Opener Re-Gearing

    Can Opener Re-Gearing

    Six years on, I just deployed the last of the aluminum spares from the original CNC project:

    Can opener - new gear installed
    Can opener – new gear installed

    I swear the cutter gear on the left does not show that rust in person!

    This can opener has a slightly larger bolt than the previous ones, so I embiggened the hole with a step drill:

    Can opener - redrilling new gear
    Can opener – redrilling new gear

    Having run out of aluminum gears, I’ll be forced to make a hob to make a steel gear. Drat!

  • Closing the Dmesg Audit Firehose

    I’m not entirely clear what’s being audited in the Manjaro Linux boxes I’ve recently set up, nor what the difference between res=success and res=failed might mean for the x11vnc unit:

    [   98.632347] audit: type=1131 audit(1594859418.419:110): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=x11vnc comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
    [   98.632348] audit: audit_lost=46 audit_rate_limit=0 audit_backlog_limit=64
    [   98.632349] audit: kauditd hold queue overflow
    [   98.649743] audit: type=1130 audit(1594859418.433:111): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=x11vnc comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=failed'
    [   98.649745] audit: audit_lost=47 audit_rate_limit=0 audit_backlog_limit=64
    [   98.649746] audit: kauditd hold queue overflow
    [  100.515527] audit: type=1101 audit(1594859420.299:112): pid=843 uid=1000 auid=1000 ses=2 msg='op=PAM:accounting grantors=pam_unix,pam_permit,pam_time acct="ed" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'

    That’s the better part of two seconds in the life of the box and, later on, the pace picks up. Casual searching suggests nobody else knows what’s going on, either, apart from the fact than that it obviously has something to do with systemd and, thus, is just the way things are these days.

    Add audit=off to the default kernel command-line parameters by editing /etc/default/grub thusly:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=UUID=whatever udev.log_priority=3 audit=off"

    Then update the bootloader:

    sudo grub-mkconfig -o /boot/grub/grub.cfg 

    Whereupon dmesg becomes all quiet and (mostly) meaningful to this civilian.