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

  • Punched Cards: Layered Apollo Eagle V3

    Punched Cards: Layered Apollo Eagle V3

    Fixing some of the outstanding issues produces another Apollo Eagle from layers of punched cards:

    Apollo Eagle - V3 - overview
    Apollo Eagle – V3 – overview

    Stipulated: nobody ever ran punched cards through a multi-color printing process. A posterized version of the Apollo 11 mission patch eagle just seemed appropriate for cards containing a chunk of the mission source code.

    Putting the tail feathers on two layers of reversed cards definitely improved the outcome:

    Apollo Eagle - V3 - tail
    Apollo Eagle – V3 – tail

    The lines across two of the tail feathers come from inadvertently printing a quilting pattern intended for Letter paper after setting up a stack of 1/3 Letter blanks. Trust me on this: you do not discard any salvageable blooper cards.

    The wing feathers get more definition and have sculptured upper layers:

    Apollo Eagle - V3 - wing
    Apollo Eagle – V3 – wing

    The olive branch improved with fewer layers and contouring the claws makes them less chunky:

    Apollo Eagle - V3 - olive branch
    Apollo Eagle – V3 – olive branch

    The beak and head now have slight contouring, with the neck feathers standing out nicely over the logo below:

    Apollo Eagle - V3 - head
    Apollo Eagle – V3 – head

    Although this is the third almost-ready version, it rests on the wings of many previous attempts:

    Apollo Eagle - layered trials
    Apollo Eagle – layered trials

    The card joints on successive layers are now farther apart, although the long run across the middle of the body stands out more than I expected. The small pieces of cards at the top of the wings need more contrast.

  • Basement Air Filter Box: Ewww!

    Basement Air Filter Box: Ewww!

    Late last year I assembled four air filters and a fan quintet into a box filter:

    Basement Air Filter Box - installed
    Basement Air Filter Box – installed

    Running continuously for three months made the air filters look like this (with an unused filter on top for comparison):

    Basement Air Filter Box - 3 months - A
    Basement Air Filter Box – 3 months – A

    I have not stretched the image contrast, so the new filter isn’t the pure white in the top picture, but it’s still about the same white as the cardboard frame. The floor is, indeed, painted gray.

    Looking at the pleats in the other direction to show I’m not making it up:

    Basement Air Filter Box - 3 months - B
    Basement Air Filter Box – 3 months – B

    The inside surface of the filters has the same gray appearance. The fans are, unsurprisingly, immaculate.

    Totally did not expect that!

    The filters sport a MERV 13 rating and snag “most smoke” from the passing air, so they’ve been collecting any fumes not sucked out of the laser cutter, along with whatever arises from other Basement Shop™ activities.

    So I’ll buy another set of filters, build another box, and see what accumulates during the next three months.

  • Auto Parking Light LED Bulbs: FAIL

    Auto Parking Light LED Bulbs: FAIL

    After about eight years and a similar failure last year, this came as no surprise:

    White W5W Parking Light - failed chips
    White W5W Parking Light – failed chips

    It’s a W5W “parking light” in the same fixture as the melty halogen high-beam bulbs (used as daytime running lights at half power), so it gets toasted on those occasions when we drive somewhere.

    The adhesive holding the LED strip to the aluminum shell fossilized and came loose:

    White W5W Parking Light - failed adhesive
    White W5W Parking Light – failed adhesive

    Now that I know what to look for, I’d get LED bulbs with chips soldered directly to the PCB, although it’s not obvious what holds the PCB to the aluminum frame.

    I reinstalled the original incandescent bulbs.

  • LED Garage Light: Desk Lamp Upcycling

    LED Garage Light: Desk Lamp Upcycling

    One of the heatsink panels from the defunct LED garage light now casts a uniform warm-white glow on my desk:

    LED Garage Light - desk light
    LED Garage Light – desk light

    A PCB intended as a lithium battery charger serves as a constant-current supply:

    LED Garage Light - constant current driver
    LED Garage Light – constant current driver

    The three trimpots, from left to right:

    • Constant-voltage limit adjustment
    • Full-charge current setpoint (irrelevant here)
    • Constant-current limit adjustment

    The as-received trimpot settings will be wildly inappropriate for a nominal 10 W COB LED array, so:

    • Connect the output to about 10 Ω of power resistors
    • … with an ammeter in series
    • Connect the input to a 12 VDC / 1-ish A wall wart
    • Adjust the output voltage to 10 V
    • Adjust the output current to 900 mA

    As long as the voltage limit is over about 10 V, it will (likely) never matter, as the LED forward drop doesn’t vary much with temperature. Setting it to something sensible keeps it out of the way.

    The middle trimpot apparently sets a voltage for a comparator to light an LED when the battery current drops below that level as it reaches full charge.

    Although the regulator touts its high efficiency, it does run hot and a heatsink seemed in order:

    LED Garage Light - heatsink
    LED Garage Light – heatsink

    Stipulated: the fins run the wrong way and it’s sitting in the updraft from the main heatsink. It’s Good Enough™.

    The switch on the top comes from the collection of flashlight tailcap switches and controls the 12 V input power. It’s buried up to its button in a generous dollop of JB Kwik epoxy, which seemed the least awful way to get that done.

    The solid model looks about like you’d expect:

    LED Lamp Driver case - switch housing - show solid model
    LED Lamp Driver case – switch housing – show solid model

    The OpenSCAD code exports the (transparent) lid as an SVG so I can import it into LightBurn and laser-cut some thin acrylic. Two tape snippets hold the lid in place pending more power-on hours, after which I’ll apply a few dots of cyanoacrylate adhesive and call it done.

    The case builds in two pieces that glue together to avoid absurd support structures:

    LED Lamp Driver case - switch housing - build solid model
    LED Lamp Driver case – switch housing – build solid model

    A 3D printed adapter goes between the desk lamp arm and the lamp heatsink bolt:

    LED Lamp Driver case - arm adapter - solid model
    LED Lamp Driver case – arm adapter – solid model

    The OpenSCAD source code files for the case and adapter arm as a GitHub Gist:

    // LED Lamp arm adapter
    // Ed Nisley – KE4ZNU
    // 2026-03-18
    include <BOSL2/std.scad>
    Layout = "Adapter"; // [Show,Build,ArmClamp,SinkClamp,Adapter]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.01;
    Gap = 5.0;
    $fn=5*3*4;
    HoleOC = 45.0;
    ArmRad = 7.5;
    ArmWidth = 11.3;
    SinkOD = 11.5;
    SinkThick = 3.2;
    SinkOC = 20.0;
    ClampThick = 5.0; // outside sink, watch thinning due to hull()
    // Define things
    // Screw & bushings in lamp arm bracket
    // … over-long bushings to prevent coincident surfaces
    module ArmClamp() {
    BushingThick = 1.5;
    BushingOD = 9.0;
    union() {
    ycyl(ArmWidth,d=4.0 + HoleWindage); // central M4 screw
    for (j=[-1,1]) {
    back(j*(ArmWidth – BushingThick + Protrusion)/2)
    ycyl(BushingThick + Protrusion,d=BushingOD);
    back(j*(ArmWidth + 10)/2)
    cuboid([2*ArmRad,10,2*ArmRad]);
    }
    }
    }
    module SinkClamp() {
    union() {
    ycyl(2*SinkOC,d=6.0 + HoleWindage); // central M6 screw
    for (j=[-1,1])
    back(j*SinkOC/2) {
    ycyl(SinkThick + Protrusion,d=SinkOD);
    cuboid([SinkOD,SinkThick + Protrusion,2*SinkOD]);
    }
    }
    }
    module Adapter() {
    difference() {
    hull() {
    right(HoleOC)
    ycyl(ArmWidth,r=ArmRad);
    ycyl(SinkOC + SinkThick + 2*ClampThick,d=SinkOD);
    }
    right(HoleOC)
    ArmClamp();
    SinkClamp();
    }
    }
    // Build it
    if (Layout == "ArmClamp")
    ArmClamp();
    if (Layout == "SinkClamp")
    SinkClamp();
    if (Layout == "Adapter")
    Adapter();
    if (Layout == "Build")
    up(SinkOD/2)
    yrot(-atan((ArmRad – SinkOD/2)/HoleOC))
    Adapter();
    // LED Constant-current driver case
    // Ed Nisley – KE4ZNU
    // 2026-03-15
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Case,Lid,LidSVG,Switch]
    /* [Hidden] */
    ThreadThick = 0.2;
    HoleWindage = 0.2;
    Protrusion = 0.01;
    Gap = 5.0;
    WallThick = 1.8;
    TapeThick = 1.5;
    DriverOA = [48.5,13.5 + TapeThick,23.5]; // PCB forward Y, pots along top to rear
    SinkOA = [31.5,12.0,15.5]; // fins forward
    SinkOffset = [(DriverOA.x – SinkOA.x)/2,0,2.0]; // from lower left front corner of PCB
    AdjPots = [14,24,34]; // screwdriver adjust offsets
    AdjOD = 3.0; // … access hole dia
    CaseOA = DriverOA + [2*WallThick,2*WallThick,2*WallThick];
    echo(CaseOA=CaseOA);
    LidOA = [CaseOA.x – WallThick,CaseOA.z – WallThick,1.0];
    Cables = [8.0,3.0 + WallThick/2,LidOA.z];
    SwitchWireOC = DriverOA.x – 6.0;
    SwitchCapBase = [DriverOA.x + WallThick,DriverOA.y + WallThick];
    SwitchCapTop = [DriverOA.x,12.0];
    SwitchCavity = [25.0,10.5,5.5];
    // Define things
    module Lid() {
    difference() {
    cuboid(LidOA,anchor=BOTTOM+FWD+LEFT);
    for (i = AdjPots)
    translate([i,LidOA.y – AdjOD/2 – WallThick/2,-Protrusion])
    cyl(LidOA.z + 2*Protrusion,d=AdjOD,anchor=BOTTOM,$fn=8,spin=180/8);
    translate([LidOA.x/2,-Protrusion,-Protrusion])
    cuboid(Cables + [0,Protrusion,2*Protrusion],rounding=1.0,edges=[BACK+LEFT,BACK+RIGHT],anchor=BOTTOM+FWD);
    }
    }
    module SwitchBox() {
    difference() {
    prismoid(SwitchCapBase,SwitchCapTop,SwitchCavity.z,anchor=BOTTOM);
    down(Protrusion)
    cuboid(SwitchCavity + [0,0,2*Protrusion],anchor=BOTTOM);
    hull()
    for (i=[-1,1])
    right(i*SwitchWireOC/2)
    zcyl(CaseOA.z,d=3.0,$fn=8,spin=180/8);
    }
    }
    module Case() {
    difference() {
    cuboid(CaseOA,chamfer=WallThick/2,anchor=BOTTOM+FWD+LEFT);
    translate([WallThick,WallThick + Protrusion,WallThick])
    cuboid(DriverOA + [0,WallThick + Protrusion,0],anchor=BOTTOM+FWD+LEFT);
    translate(SinkOffset + [WallThick,WallThick + 2*Protrusion,WallThick])
    cuboid(SinkOA,anchor=BOTTOM+BACK+LEFT);
    for (i=[-1,1])
    translate([i*SwitchWireOC/2 + CaseOA.x/2,CaseOA.y/2,CaseOA.z/2])
    zcyl(CaseOA.z,d=2.0,anchor=BOTTOM,$fn=8,spin=180/8);
    translate([WallThick/2,(CaseOA.y + LidOA.z),WallThick/2])
    xrot(90)
    scale([1,1,2])
    Lid();
    }
    }
    // Build it
    if (Layout == "Switch")
    SwitchBox();
    if (Layout == "Case")
    Case();
    if (Layout == "Lid")
    Lid();
    if (Layout == "LidSVG")
    projection(cut=true)
    Lid();
    if (Layout == "Show") {
    Case();
    translate(SinkOffset + [WallThick,WallThick + 2*Protrusion,WallThick])
    color("Gray",0.7)
    cuboid(SinkOA,anchor=BOTTOM+BACK+LEFT);
    translate([CaseOA.x/2,CaseOA.y/2,CaseOA.z])
    SwitchBox();
    translate([WallThick/2,CaseOA.y,WallThick/2])
    xrot(90)
    color("Gray",0.7)
    Lid();
    }
    if (Layout == "Build") {
    fwd(Gap)
    xrot(90)
    Case();
    translate([CaseOA.x/2,(Gap + CaseOA.y/2),0])
    SwitchBox();
    }
  • HQ Sixteen: Bobbin Winder Adjustment and Unwind Adapter

    HQ Sixteen: Bobbin Winder Adjustment and Unwind Adapter

    The Industrial Age bobbin winder for Mary’s HQ Sixteen long-arm machine bunched the thread on one end of the bobbin, rather than distributing it in even layers as it should. Tinkering with the thread tension setting being unavailing, I settled in for some debugging.

    After filling two bobbins from a spool of the thread Mary uses for practice quilts, I decided I should reuse the thread. Mounting the filled bobbin on a 6 mm horizontal shaft attached to the vertical pin normally locating the spool let the thread pay out in the proper orientation, with a duct-tape lashup holding the shaft in place:

    HQ Sixteen bobbin unwind adapter - expedient version
    HQ Sixteen bobbin unwind adapter – expedient version

    I added the stack of washers to keep the bobbin away from the duct tape after having the tape’s adhesive migrate onto the spinning bobbin.

    The thread from the spool or, in my case, a filled bobbin, passes between a pair of tension disks on its way to the bobbin spun by the motor:

    HQ Sixteen bobbin winder - thread path
    HQ Sixteen bobbin winder – thread path

    A conical spring presses the tension disks together, with the thread clamped between them:

    HQ Sixteen bobbin winder - tension disk overview
    HQ Sixteen bobbin winder – tension disk overview

    The instructions suggest using “the lightest tension possible”, but backing the nut off to hang by its fingernails had no effect. The spring has a bent end passing through the slotted shaft, so rotation of the disks won’t unscrew the nut.

    The washer under the mounting screw left slight scars in the black oxide finish on the fixture, presumably from previous attempts to adjust the thing:

    HQ Sixteen bobbin winder - tension disk base
    HQ Sixteen bobbin winder – tension disk base

    The threaded shaft is not exactly parallel to the base, because the upright arm is slightly over-bent, but I think that has no effect on the outcome, because the thread path doesn’t depend on the disk angle.

    Because the thread accumulated on the outer side of the bobbin (to the right in that picture), I loosened the mounting screw and shoved the fixture all the way to the left. That should, if anything, bias the thread accumulation to the other (inner) side of the bobbin.

    As it turned out, relocating the tension disks caused the thread to distribute evenly across the bobbin, with only occasional hesitations and no significant accumulations; Mary pronounced the result entirely satisfactory.

    The motor dataplate says it runs at 7000 RPM, so the 3/4 inch O-ring drives the 4 inch wheel at about 1300 RPM. This was sufficiently terrifying I immediately set up a triac speed control (intended for a router) to throttle it down, but with the bobbins now filling properly we run the motor at full speed and it fills a bobbin in 23 seconds flat.

    After we filled half a dozen bobbins with blue thread for the quilt project, I conjured an adapter from the vasty digital deep for a snippet of 6 mm rod with a D-shaped end:

    Bobbin Unwind Adapter - solid model - show
    Bobbin Unwind Adapter – solid model – show

    The adapter builds on one leg, with a brim for stability:

    HQ Sixteen bobbin unwind adapter - on platform
    HQ Sixteen bobbin unwind adapter – on platform

    And looks like it belongs there:

    HQ Sixteen bobbin unwind adapter - installed
    HQ Sixteen bobbin unwind adapter – installed

    It’s now in the box of HQ Sixteen bobbins, where we both hope it will remain undisturbed forevermore.

    Although the vertical pin locating the spools (and holding the adapter) is nominally 6 mm, burrs in the chrome plating prevented the bobbin’s 6 mm bore from sliding over it. In retrospect, that prevented me from just dropping the bobbin on the pin and unwinding the thread over the side of the bobbin, which likely avoided some serious-to-lethal thread tangles.

    After all that debugging, I had several bobbins full of well-worn thread, so:

    • Chuck a chopstick in the mini-lathe
    • Tape thread to chopstick
    • Put bobbin on another 6 mm shaft
    • Run lathe at a reasonable speed
    • Produce what looks very much like a cocoon
    HQ Sixteen bobbin unwind adapter - thread cocoon
    HQ Sixteen bobbin unwind adapter – thread cocoon

    All’s well that ends well.

    The OpenSCAD source code as a GitHub Gist:

    // HQ Sixteen Bobbin Winder – Unwind adapter
    // Ed Nisley – KE4ZNU
    // 2026-03-27
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.01;
    Gap = 5.0;
    $fn=5*3*4;
    WallThick = 2.0;
    SpoolRodOD = 6.03; // vertical spool rod
    Kerf = 0.5;
    BobbinRodOD = 6.0 + HoleWindage; // horizontal bobbin rod
    BobbinRodDee = 4.95; // … remaining rod
    DeeLength = 20.0; // … recess depth
    DeeRodCyl = 28.0; // … overall rod length
    AdapterOD = BobbinRodOD + 2*WallThick;
    AdapterOAH = 1.5*AdapterOD;
    AdapterOAL = AdapterOD + DeeLength;
    //—–
    // Define things
    // Surplus-deal 6 mm rod with a lengthy flat on one end
    module DeeRod() {
    union() {
    intersection() {
    xcyl(DeeLength + Protrusion,d=BobbinRodOD,anchor=RIGHT);
    down((BobbinRodOD – BobbinRodDee)/2)
    cuboid([DeeLength + Protrusion,BobbinRodOD,BobbinRodDee],anchor=RIGHT);
    }
    xcyl(DeeRodCyl,d=BobbinRodOD,anchor=LEFT);
    }
    }
    module Adapter() {
    difference() {
    union() {
    cyl(AdapterOAH,d=AdapterOD,rounding=WallThick/2);
    xcyl(AdapterOAL – AdapterOD/2,d=AdapterOD,anchor=LEFT);
    }
    zcyl(AdapterOAH + 2*Protrusion,d=SpoolRodOD);
    cuboid([AdapterOD+2*Protrusion,Kerf,AdapterOAH+2*Protrusion]);
    right(AdapterOD/2 + DeeLength + Protrusion)
    DeeRod();
    }
    }
    //—–
    // Build it
    if (Layout == "Show") {
    Adapter();
    color("Green",0.5)
    zcyl(3*AdapterOAH,d=SpoolRodOD);
    color("Magenta",0.5)
    right(AdapterOD/2 + DeeLength + Protrusion)
    DeeRod();
    }
    if (Layout == "Build")
    up(AdapterOD/2 + DeeLength)
    yrot(90)
    Adapter();

  • Corbin K436 Padlock: Shackle Reshaping

    Corbin K436 Padlock: Shackle Reshaping

    After approximately forever, the shackle on the Corbin K436 padlock securing the tandem-length cable we use for the Tour Easy ‘bents refused to push into the body. Lubrication being unavailing, I soaked it in acetone and shook it around for a day to get the inevitable crud out, then pondered the problem.

    Peering into the hole where the shackle enters the body showed the situation:

    Corbin padlock - cam damage
    Corbin padlock – cam damage

    Half a century (more or less: it didn’t accumulate those nicks & dings & tarnish last year) of pushing the shackle into the lock eroded the locking cam, to the extent that the cam no longer slides sideways to let the shackle slide the rest of the way into the body.

    So I introduced the shackle to Mr Bench Grinder and reshaped the end to hit the cam farther down on its angled side:

    Corbin padlock - reshaped shackle
    Corbin padlock – reshaped shackle

    While that certainly reduces the strength of the shackle, there’s a similar notch engaging a similar cam on the other end of the shackle, so it remains as secure as it must be for our simple needs.

    Spraying silicone lube into the body and applying a dab of silicone grease to the cam restored the lock to (nearly) new condition.

    The riding season approaches!

  • Quilting Ruler Pencil Guides: Acrylic

    Quilting Ruler Pencil Guides: Acrylic

    I cut some transparent acrylic pencil guides to go along with the 45° Triangle Ruler:

    Quilting Ruler Pencil Guides
    Quilting Ruler Pencil Guides

    The guides along the rear are the 3D printed versions from a decade ago.

    The three transparent guides taught us:

    • 4 mm is better than 3 mm
    • Entirely transparent guides vanish on the table

    So the engraved ring on the two in the front row carries a cheerful Sharpie color to make them stand out. I wanted to use fluorescent acrylic, but I don’t have any 4 mm sheets and stacking a pair of 3 mm sheets → 6 mm will be too thick for the pencil tip.

    What looks like dirt on the red guide comes from internal reflections or the lack thereof: it’s perfectly transparent in person, honest.