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: Sewing

Fabric arts and machines

  • Tailor’s Clapper: 3D Printed Finger Grips

    Tailor’s Clapper: 3D Printed Finger Grips

    With the pockets milled into the oak blocks, the next step is to insert a pair of comfy 3D printed finger grips:

    Ironing weight - prototype grip
    Ironing weight – prototype grip

    Getting comfy required a bank shot off the familiar chord equation to find the radius of a much larger circle producing the proper depth between the known width. The recess then comes from subtracting a hotdog from a lozenge exactly filling the wood pocket.

    Ironing Weight Finger Grip - recess chord
    Ironing Weight Finger Grip – recess chord

    A pair of grips takes just under two hours to print while requiring no attention, which I vastly prefer to tending the Sherline.

    The wood pocket is 7 mm deep and the grips stand 6.5 mm tall, leaving just enough room for three blobs of acrylic adhesive to hold them together. After squishing the grips into their pockets, a pair of right angles aligned everything while the adhesive cured:

    Ironing weight - grip adhesive curing
    Ironing weight – grip adhesive curing

    Mary asked for a longer weight for a place mat project, with a slightly narrower block to compensate for the additional length:

    Ironing weight - seam ironing B
    Ironing weight – seam ironing B

    The grip and pocket were the same size, so it was just a matter of tweaking the block size and cutting more wood.

    All in all, a quick project with satisfying results!

    The OpenSCAD source code as a GitHub Gist:

    // Oak ironing weight finger grips
    // Ed Nisley KE4ZNU 2023-01
    Layout = "Show"; // [Block,Grip,Show,Build]
    //- Extrusion parameters must match reality!
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    Protrusion = 0.1; // make holes end cleanly
    inch = 25.4;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    ID = 0;
    OD = 1;
    LENGTH = 2;
    //———-
    // Dimensions
    // Length along X axis
    Block = [250.0,50.0,39.0]; // overall wood block
    BlockRadius = 10.0;
    CornerRadius = 10.0;
    Kerf = 0.2;
    Socket = [160.0,25.0,6.5]; // raw recess into block
    SocketRadius = Socket.y/2;
    echo(Socket=Socket,SocketRadius=SocketRadius);
    WallThick = ThreadWidth; // Thinnest printed wall
    Clearance = 0.5; // between grip and recess
    GripBlock = Socket – [2*Clearance,2*Clearance,Clearance];
    GripBlockRadius = SocketRadius – Clearance;
    echo(GripBlock=GripBlock);
    GripDepth = 5.0; // finger grip recess
    GripRecess = [GripBlock.x – 2*WallThick,GripBlock.y – 2*WallThick,GripDepth];
    GripRecessRadius = GripBlockRadius – WallThick;
    echo(GripRecess=GripRecess,GripRecessRadius=GripRecessRadius);
    GripChordRadius = (pow(GripDepth,2) + pow(GripRecess.y,2)/4) / (2*GripDepth);
    echo(GripChordRadius=GripChordRadius);
    NumSides = 4*8;
    //———-
    // Shapes
    module WoodBlock() {
    difference() {
    hull()
    for (i=[-1,1], j=[-1,1]) // rounded block
    translate([i*(Block.x/2 – BlockRadius),j*(Block.y/2 – BlockRadius),-Block.z/2])
    cylinder(r=BlockRadius,h=Block.z,$fn=NumSides);
    for (j=[-1,1]) // grip socket
    translate([0,j*(Block.y/2 + Protrusion),0])
    rotate([j*90,0,0])
    hull() {
    for (i=[-1,1])
    translate([i*(Socket.x/2 – SocketRadius),(Socket.y/2 – SocketRadius),0])
    cylinder(r=SocketRadius,h=Socket.z + Protrusion,$fn=NumSides);
    }
    cube([2*Block.x,2*Block.y,Kerf],center=true);
    }
    }
    module Grip() {
    difference() {
    hull()
    for (i=[-1,1]) // overall grip block
    translate([i*(GripBlock.x/2 – GripBlockRadius),0,0])
    cylinder(r=GripBlockRadius,h=GripBlock.z,$fn=NumSides);
    hull() {
    for (i=[-1,1]) // grip recess
    translate([i*(GripBlock.x/2 – GripRecessRadius – WallThick),
    0,
    GripChordRadius + GripBlock.z – GripDepth])
    sphere(r=GripChordRadius,$fn=NumSides);
    }
    }
    }
    //———-
    // Build them
    if (Layout == "Block")
    WoodBlock();
    if (Layout == "Grip")
    Grip();
    if (Layout == "Show") {
    color("Brown")
    WoodBlock();
    color("Silver")
    for (j=[-1,1])
    translate([0,j*(Block.y/2 – GripBlock.z),0])
    rotate([j*-90,0,0])
    Grip();
    }
    if (Layout == "Build") {
    for (i=[-1,1])
    translate([i*(Block.y/2 – GripBlock.z),0,0])
    rotate([0,0,90])
    Grip();
    }

  • Tailor’s Clapper: CNC Pocketing

    Tailor’s Clapper: CNC Pocketing

    Separating the interior contour of the finger grip from its overall shape let me reduce the woodworking to a simple pocketing operation:

    Ironing Weight Finger Grip
    Ironing Weight Finger Grip

    Start by aligning the finished block to put the joint between the pieces parallel to the X axis, then touch off at the center:

    Ironing Weight - alignment
    Ironing Weight – alignment

    A pair of clamps screwed to the tooling plate act as fixtures to align the block when it’s flipped over to mill the other pocket.

    Just to see how it worked, I set up a GCMC program to produce a trochoidal milling pattern using the sample program:

    Tailors Clapper - Pocket Milling Path
    Tailors Clapper – Pocket Milling Path

    Now, most folks would say the Sherline lacks enough speed and stiffness for trochoidal milling:

    Ironing weight - trochoidal milling
    Ironing weight – trochoidal milling

    Aaaand I would agree with them: chugging along at 24 in/min = 600 mm/min doesn’t put the 10 k RPM spindle speed to good use. Fortunately, oak doesn’t require much in the way of machine stiffness and the trochoid path does ensure good chip clearance, so there’s that.

    If I had to do a lot of trochoid milling, I’d tweak the GCMC sample code to short-cut the return path across the circle diameter, rather than air-cut the last half of every circumference.

    The code starts by emptying a circular pocket so the trochoid path begins in clear air, rather than trenching into solid wood.

    Eventually it finishes the pocket:

    Ironing weight - grip pocket
    Ironing weight – grip pocket

    After the trochoid finishes, one climb-milling pass around the perimeter clears the little ripple between each trochoid orbit.

    Flip it over, clamp it down, touch off the middle, and do it all again.

    The next step is filling those pockets with a pair of comfy grips.

    The GCMC source code as a GitHub Gist:

    // Ironing weight pocketing
    // Ed Nisley KE4ZNU – 2023-01
    //—–
    // Library routines
    include("/opt/gcmc/example/cc_hole.inc.gcmc");
    include("varcs.inc.gcmc");
    include("tracepath_comp.inc.gcmc");
    include("trochoidal.inc.gcmc");
    /*
    include("tracepath.inc.gcmc");
    include("engrave.inc.gcmc");
    */
    //—–
    // Useful constants
    SafeZ = 10.0mm; // above all obstructions
    TravelZ = 2.0mm; // within engraving / milling area
    BlockHome = [0.0mm,0.0mm,TravelZ]; // Origin on surface at center of pocket
    FALSE = 0;
    TRUE = !FALSE;
    //—–
    // Overall values
    Socket = [160.0mm,25.0mm,7.0mm]; // raw grip recess into block
    RoundEnds = TRUE; // TRUE for smooth rounded endcaps
    SocketRadius = RoundEnds ? Socket.y/2 : 10.0mm;
    comment("SocketRadius: ",SocketRadius);
    CutterDia = 6.32mm – 0.15; // actual cutter diameter – windage
    MillStep = 0.25 * CutterDia; // stepover in XY plane
    comment("CutterDia: ",CutterDia," MillStep: ",MillStep);
    MillClean = MillStep/2;
    PlungeSpeed = 150.0mm; // cutter Z plunge into work
    MillSpeed = 600.0mm; // XY speed
    if (CutterDia > SocketRadius) {
    error("Cutter too large for corner radius");
    }
    CornerOC = head(Socket,2) – 2*[SocketRadius,SocketRadius];
    comment("CornerOC: ",CornerOC);
    Corners = RoundEnds ? // rear left CCW around slot
    {-CornerOC/2, CornerOC/2} :
    {[-CornerOC.x,CornerOC.y]/2, [-CornerOC.x,-CornerOC.y]/2, [CornerOC.x,-CornerOC.y]/2, CornerOC/2};
    comment("Corners: ", Corners);
    if (RoundEnds) {
    SlotPerimeter = {[0.0mm,Socket.y/2,-Socket.z]}; // entry point at center rear
    SlotPerimeter += {Corners[0] + [0.0mm,SocketRadius]};
    SlotPerimeter += varc_ccw([-SocketRadius,-SocketRadius],SocketRadius) + SlotPerimeter[-1];
    SlotPerimeter += varc_ccw([+SocketRadius,-SocketRadius],SocketRadius) + (Corners[0] + [-SocketRadius,0.0mm]);
    SlotPerimeter += {Corners[1] + [0.0mm,-SocketRadius]}; // across front
    SlotPerimeter += varc_ccw([+SocketRadius,+SocketRadius],SocketRadius) + SlotPerimeter[-1];
    SlotPerimeter += varc_ccw([-SocketRadius,+SocketRadius],SocketRadius) + (Corners[1] + [+SocketRadius,0.0mm]);
    }
    else {
    SlotPerimeter = {[0.0mm,Socket.y/2,-Socket.z]}; // entry point at center rear
    SlotPerimeter += {Corners[0] + [0.0mm,SocketRadius]};
    SlotPerimeter += varc_ccw([-SocketRadius,-SocketRadius],SocketRadius) + SlotPerimeter[-1];
    SlotPerimeter += {Corners[1] + [-SocketRadius,0.0mm]};
    SlotPerimeter += varc_ccw([+SocketRadius,-SocketRadius],SocketRadius) + SlotPerimeter[-1];
    SlotPerimeter += {Corners[2] + [0.0mm,-SocketRadius]}; // across front
    SlotPerimeter += varc_ccw([SocketRadius,SocketRadius],SocketRadius) + SlotPerimeter[-1];
    SlotPerimeter += {Corners[3] + [SocketRadius,0.0mm]};
    SlotPerimeter += varc_ccw([-SocketRadius,SocketRadius],SocketRadius) + SlotPerimeter[-1];
    }
    //— Begin cutting
    goto([-,-,TravelZ]);
    goto(BlockHome);
    if (!RoundEnds) { // clear corners outward of main pocket
    foreach(Corners; xy) {
    comment("Plunge corner at: ",xy);
    feedrate(PlungeSpeed);
    goto(xy);
    move([-,-,-Socket.z]);
    comment(" pocket");
    feedrate(MillSpeed);
    cc_hole(xy,(SocketRadius – MillClean),CutterDia/2,MillStep,-Socket.z);
    goto([-,-,TravelZ]);
    comment(" done!");
    }
    }
    comment("Open slot");
    TrochRadius = (Socket.y – CutterDia)/2 – MillClean;
    TrochPath = {[-(Socket.x/2 – TrochRadius – CutterDia/2 – MillStep),TrochRadius],
    [ (Socket.x/2 – TrochRadius – CutterDia/2 – MillStep),TrochRadius]};
    comment(" clear landing zone");
    xy = [TrochPath[0].x,0.0mm];
    feedrate(PlungeSpeed);
    goto(xy);
    move([-,-,-Socket.z]);
    feedrate(MillSpeed);
    cc_hole(xy,Socket.y/2 – MillClean,CutterDia/2,MillStep,-Socket.z);
    goto([-,-,TravelZ]);
    comment(" trochoid pocket milling");
    feedrate(MillSpeed);
    trochoid_move(TrochPath[0],TrochPath[1],
    -Socket.z, TrochRadius, MillStep);
    goto([-,-,TravelZ]);
    comment("Clean slot perimeter");
    feedrate(MillSpeed);
    goto([-,-,-Socket.z]);
    tracepath_comp(SlotPerimeter,CutterDia/2,TPC_CLOSED + TPC_LEFT + TPC_ARCIN + TPC_ARCOUT);
    goto([-,-,TravelZ]);
    goto(BlockHome);
    #!/bin/bash
    # Ironing weight finger grip pocketing
    # Ed Nisley KE4ZNU – 2023-01
    Flags='-P 4 –pedantic' # quote to avoid leading hyphen gotcha
    # Set these to match your file layout
    LibPath='/opt/gcmc/library'
    Prolog='prolog.gcmc'
    Epilog='epilog.gcmc'
    #—–
    gcmc $Flags \
    –include "$LibPath" –prologue "$Prolog" –epilogue "$Epilog" \
    "Ironing weight grip pocket.gcmc" > "Grip pocket.ngc"
    view raw pocket.sh hosted with ❤ by GitHub

  • Tailor’s Clapper: Laser-Cut Woodwork

    Tailor’s Clapper: Laser-Cut Woodwork

    Creating the rounded-rectangle shape of a tailor’s clapper in LightBurn, then cutting it out, doesn’t pose much of a challenge:

    Ironing weight - cutting oak plank
    Ironing weight – cutting oak plank

    That was a prototype cut from an oak plank with some fairly obvious splits. It turned out OK, but ¾ inch oak is obviously right at the limit of my 60 W laser’s abilities:

    Ironing weight - laser cut edges
    Ironing weight – laser cut edges

    The “production” clappers came from a nicer plank that was just barely long enough:

    Ironing weight - laser cuts - top
    Ironing weight – laser cuts – top

    The cut, at 2 mm/s and 70% power, just barely penetrates the plank:

    Ironing weight - laser cuts - bottom
    Ironing weight – laser cuts – bottom

    Unlike the top picture, I put the plank on the knife-edge supports, resulting in the small charred lines perpendicular to the cut.

    The edges came out thoroughly charred:

    Ironing weight - laser cuts - edges
    Ironing weight – laser cuts – edges

    Spread yellow wood glue smoothly on one piece, stick another to it, then align and clamp:

    Ironing weight - clamping
    Ironing weight – clamping

    I offset the cut 1 mm outside the nominal shape to allow Mr Belt Sander to remove the char while reducing the block to size. Obviously, there is no real tolerance, other than that it must fit Mary’s hand, and they all came out nice and straight.

    Some of the char seems embedded deep in the wood grain and leaves a dark mark despite removing the extra millimeter:

    Ironing weight - seam ironing B
    Ironing weight – seam ironing B

    Contrary to what I feared, the characteristic wood-stove odor dissipated after a day or two: they’re entirely inoffensive. Which was fortunate, as the slightest odor would cause them to fail incoming inspection.

    The longer weight on the far left came from a plank with a conspicuous knot on one end. The stress from supporting that branch while the tree grew apparently made the wood much denser, as the same 2 mm/s 70% cut setting barely made it halfway through the plank. I finished the job by cutting the outline with Tiny Bandsaw™, which didn’t proceed any faster than the laser and left a much less uniform path for Mr Belt Sander.

    I’d definitely consider making any future tailor’s clappers by laminating three half-inch oak planks that would be much easier to cut, but my woodpile doesn’t have anything like that.

    The wood remains unfinished, as part of its job is to absorb moisture from steam-ironed fabric (which is not happening in the photo). Applying stains / sealers / finishes would definitely improve the wood’s appearance, but wreck its performance. Around here, function always outweighs form.

  • Ironing Weight, a.k.a. Tailor’s Clapper: Overview

    Ironing Weight, a.k.a. Tailor’s Clapper: Overview

    Mary wanted some ironing weights, formally known as tailor’s clappers, to produce flatter seams as she pieced fabric together:

    Ironing weight - flattened seam
    Ironing weight – flattened seam

    The weights are blocks of dense, hard, unfinished wood:

    Ironing weight - seam ironing A
    Ironing weight – seam ironing A

    One can buy commercial versions ranging from cheap Amazon blocks to exotic handmade creations, but a comfortable grip on a block sized to Mary’s hands were important. My lack of woodworking equipment constrained the project, but the picture shows what we settled on.

    The general idea is a rounded wood block with 3D printed grips:

    Ironing Weight Finger Grip
    Ironing Weight Finger Grip

    All other clappers seem to have a simple slot routed along the long sides, presumably using a round-end or ball cutter, which means the cutter determines the shape. This being the age of rapid prototyping, I decided to put the complex geometry in an easy-to-make printed part inserted into a simple CNC-milled pocket.

    The first pass at the grip models:

    Ironing Weight Finger Grip - slicer preview
    Ironing Weight Finger Grip – slicer preview

    Both recesses came from spheres sunk to their equators with their XY radii scaled appropriately, then hulled into the final shape. Customer feedback quickly reported uncomfortably abrupt edges along the top and bottom:

    Ironing Weight - maple prototype
    Ironing Weight – maple prototype

    We also decided the straight-end design didn’t really matter, so all subsequent grips have rounded ends to simplify milling the pocket into the block.

    With the goal in mind, the next few posts will describe the various pieces required to make a nice tailor’s clapper customized to fit the user’s hand.

  • Bobbin Rock

    Bobbin Rock

    Mary handed me a bobbin with a trouble report: it fit into the bobbin holder either way, but would go into the sewing machine either poorly or not at all.

    Based on past experience with this lot of bobbins (*), I expected to find a burr inside the steel hub left behind by the saw cut creating the drive dog slot, so this came as a surprise:

    Bobbin Rock - overview
    Bobbin Rock – overview

    A closer look:

    Bobbin Rock - detail
    Bobbin Rock – detail

    That pebble was jammed in place so firmly I needed a pin punch: a small screwdriver wasn’t enough.

    It came new from the factory like that, which makes one wonder just exactly what the factory floor looks like.

    More likely, the bobbins spend their last few hours in a vibratory polisher and that little rock just crept with all the walnut shell kibble.

    Works fine now, so we’ll call it a win.

    (*) I gave her a lot of 100 to ensure she never had to unload a bobbin to keep her new Juki well-fed.

  • Splined Neck Cozy Pattern

    Splined Neck Cozy Pattern

    Mary made a neck cozy based on a Craftsy description using a pattern I’d extracted from the low-res photo and rescaled to the proper size. The perimeter came out grittier than I like, but the laser had no trouble chopping it from a sheet of paper, and she cut smoothly around the lumps:

    Neck Cozy mask - right
    Neck Cozy mask – right

    It looks better on her, but you get the general idea:

    Neck Cozy - rev 1 finished
    Neck Cozy – rev 1 finished

    After some experience, however, she wanted to lengthen the top and bottom seams to improve the way it draped, which meant I had to modify the extracted pattern. The original pattern in the Craftsy photo was hand-drawn (which is perfectly fine) and the two halves were of two different sizes; we decided to work with the left half and produce a symmetric result.

    Rather than fiddle with the bitmap, I drew a rectangle around the outside of the left pattern mask, converted it to a path, moved the nodes to key locations, then fiddled with the control points to lay the splines along the perimeter:

    Neck Cozy pattern - LB splines
    Neck Cozy pattern – LB splines

    Removing the bitmap makes the splines much more obvious and shows the much smoother perimeter:

    Neck Cozy pattern - LB extended splines
    Neck Cozy pattern – LB extended splines

    Adding a few nodes to change the splined shape is much simpler than fiddling with the bitmap, particularly when tweaking their position as directed by someone who knows how the fabric will eventually take shape.

    Add fiducial marks and a label, duplicate the shape, mirror it to get the other half, and fire the laser:

    Neck Cozy pattern - as cut right
    Neck Cozy pattern – as cut right

    Fabric cutting isn’t in my wheelhouse, but I made the offer …

    The LightBurn layout as a GitHub Gist:

    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.

  • Dogbone Pillow Pattern

    Dogbone Pillow Pattern

    Mary is putting together a dogbone headrest pillow for a friend who will be spending a lot of time in a chair. It’ll be similar to this one from a while ago:

    Dog Bone Pillow
    Dog Bone Pillow

    She used Bonnie Browning’s pattern and I offered to laser-cut it as practice for other projects I have in mind.

    It eventually worked out well enough:

    Dog Bone Pillow - cut pattern
    Dog Bone Pillow – cut pattern

    Fold a piece of fabric in half, align the pattern’s bottom edge with the fold, cut around the perimeter, make two more, and sew ’em together.

    My first mistake was attempting to assemble the two halves of the pattern from the PDF document into a bitmap image using The GIMP:

    D0G-BONE pattern - rejoined
    D0G-BONE pattern – rejoined

    That is both tedious and unnecessary, as I found out while trying to align the pieces.

    The end goal is a simple and symmetric vector path defining the outline, including a line across the bottom, suitable for laser cutting. Rather than assembling an image, tracing it into a bunch of vectors, then cleaning up the mess, just lay a smooth spline vector path around half of it and invoke symmetry, much as happened with the Lip Balm Holder.

    So import the slightly misaligned bitmap into LightBurn, draw a rectangle over just the left half, convert the rectangle to a path, then add a few nodes anchoring the splines to key points of the image:

    Dog Bone Pillow - LB half pattern first splines
    Dog Bone Pillow – LB half pattern first splines

    Although it’s not visible, the top and bottom spline nodes defining the vertical line down the middle are not quite vertically aligned, even though I dragged them to the middle of the pattern. Unsurprisingly, the bitmap image is not exactly aligned with the axes, even though the conversion from PDF to bitmap is entirely digital; the original design may be off by an itsy that would never matter for its intended application.

    Tweak the splines / control points, add a few more nodes, and in short order the vector path runs pretty nearly along the middle of the bitmap image:

    Dog Bone Pillow - LB half pattern overlay
    Dog Bone Pillow – LB half pattern overlay

    Rather than trying to draw the second half just like the first half, duplicate the path and mirror the copy left-to-right to get the right half of the pattern. Grab the lower-left corner of the copy and snap it to the lower-right corner of the original, whereupon you will find the two points at the top of those lines don’t quite line up.

    This is a grossly zoomed look at the top center, with the two red angles showing the two halves not quite meeting in the middle:

    Dog Bone Pillow - LB top center spline mismatch
    Dog Bone Pillow – LB top center spline mismatch

    Now the magic happens.

    In quick succession:

    • Select the right-side path
    • Invoke Arrange → Two-point Rotate / Scale
    • Zoom way in on the bottom center
    • Click on the center point to define the Rotate center
    • Zoom way in on the top center
    • Click-n-drag the right corner to snap it onto the left corner
    • Done!

    What just happened is that the right half now directly adjoins the left half, with the upper and lower center points overlapping.

    Invoke the node editor and delete the center lines from both halves, leaving just the (overlaid) top and bottom nodes. Select both paths, then invoke Edit → Auto-join selected shapes to merge the two halves into one:

    Dog Bone Pillow - LB splines
    Dog Bone Pillow – LB splines

    I missed the clip line in the middle of the top, but that’s why the first version is always a prototype.

    This was easy, but it’s good to stay in practice …