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

  • Tour Easy Running Light: Machining & Assembly

    Tour Easy Running Light: Machining & Assembly

    The 1 W red LED in the taillight on Mary’s Tour Easy failed and, because the LED is epoxied into the heatsink forming the business end of the light, I had to machine a replacement. This proceeds much as before, with some improvements & simplifications.

    A revised sketch of the key dimensions shows a clearance hole for the 3 mm screw (to eliminate tapping the heatsink) and a reminder about how to locate the wire holes:

    Tour Easy running light - housing dimensions - M3 clear - detail
    Tour Easy running light – housing dimensions – M3 clear – detail

    Bore a 19 mm ID recess 10 mm deep in the (1 inch OD × ¾ inch ID) aluminum tube and score the ID for improved epoxy griptivity:

    Tour Easy Running Light - heatsink scoring
    Tour Easy Running Light – heatsink scoring

    Knurl the ¾ inch rod to bring the OD to a slip fit in the shell:

    Tour Easy Running Light - heatsink plug knurling
    Tour Easy Running Light – heatsink plug knurling

    Take them ouside, hose down with brake cleaner to get rid of the cutting fluid, butter ’em up with epoxy, align in the lathe, and let ’em cure overnight:

    Tour Easy Running Light - heatsink epoxy fixture
    Tour Easy Running Light – heatsink epoxy fixture

    This time I managed to not cut off the rod, which dramatically simplifies boring the shell and facing the front end of the rod flush with the inside of the shell so the LED PCB sits flat in there:

    Tour Easy Running Light - heatsink front ID
    Tour Easy Running Light – heatsink front ID

    Clean up the shell OD and turn the back to 23 mm OD to fit the PVC tube from the failed taillight:

    Tour Easy Running Light - heatsink shell OD
    Tour Easy Running Light – heatsink shell OD

    Crisp up the edge for a tidy fit:

    Tour Easy Running Light - heatsink shell corner
    Tour Easy Running Light – heatsink shell corner

    Break / file all the corners, then bandsaw the rod and face the back end:

    Tour Easy Running Light - heatsink rear facing
    Tour Easy Running Light – heatsink rear facing

    Set it up on the Sherline mill, find the center, and use manual jogging to poke the holes at the proper coordinates:

    Tour Easy Running Light - heatsink Sherline setup
    Tour Easy Running Light – heatsink Sherline setup

    Take the finished heatsink outside again for more brake cleaner action.

    The 3D printed circuit plate now sports two inserts:

    Running Light Circuit Plate - two inserts - solid model
    Running Light Circuit Plate – two inserts – solid model

    Epoxy the inserts in place, prepare two 1.6 mm = 1/16 inch steel wires, and chop the head off an M3 screw:

    Tour Easy Running Light - heatsink with circuit plate
    Tour Easy Running Light – heatsink with circuit plate

    Stipulated: my center-finding hand is weak.

    Aligning the LED heatsink with those wire holes is a pain:

    • Clean up the 1 W LED PCB
    • Solder the LED in place atop some heatsink compound
    • Push the lens holder (without the lens!) over the LED
    • Insert holder + LED into the heatsink
    • Rotate to put one LED terminal between the wire holes in the heatsink
    • Rotate to align the recesses in the PCB with the wire holes in the heatsink
    • Match-mark the holes on the lens holder with a transfer punch
    • Grab the holder in the Sherline vise
    • Align & drill wire holes in the holder
    • Solder wires to the LED PCB, aimed inward atop the LED leads

    With the LED & lens holder prepared & set aside, butter the circuit plate parts with JB PlasticBonder, align the plate perpendicular to the heatsink using V-blocks / 123 blocks / whatever, and let it cure overnight.

    The lens allows plenty of room to run the wires from the PCB around the LED inside the holder to the holes:

    Tour Easy Running Light - 1W LED lens fit
    Tour Easy Running Light – 1W LED lens fit

    So do that:

    • Dab PlasticBonder on the bottom of the lens holder
    • Stick the LED to the holder (still with no lens!)
    • Thread the LED wires through the holes in the holder, the LED PCB, and into the heatsink
    • Dab PlasticBonder on the bottom of the PCB
    • Ease the holder + LED into the heatsink while pulling the wires through the holes
    • Finally install the lens in the holder
    • Clamp the whole mess lenthwise with padding atop the lens to prevent scratches

    I transferred the circuitry from the failed taillight to the new one, atop refreshed double-sided foam tape:

    Tour Easy Running Light - Arduino side
    Tour Easy Running Light – Arduino side

    With hot-melt glue securing the 2 Ω current-sense resistor to the circuit plate:

    Tour Easy Running Light - regulator side
    Tour Easy Running Light – regulator side

    Slide the PVC case over the circuit plate, secure the end cap with a 25 mm screw, and reinstall on the bike:

    Tour Easy Running Light - taillight installed
    Tour Easy Running Light – taillight installed

    It’s angled 1° up from horizontal:

    Tour Easy Running Light - taillight in use
    Tour Easy Running Light – taillight in use

    Wow, is that thing bright!

  • One-watt LED Thermal Pad Reflow: Nope

    One-watt LED Thermal Pad Reflow: Nope

    While building up another taillight for Mary’s Tour Easy (about which, more later) and based on previous experience, I wondered if the 1 W red LED’s thermal pad was soldered to the circuit board as it should be.

    Lo and behold, the solder paste was reflowed, likely while tinning the six solder pads:

    Tour Easy Running Light - 1W LED PCB solder
    Tour Easy Running Light – 1W LED PCB solder

    But not with the LED in place:

    Tour Easy Running Light - 1W LED base glue
    Tour Easy Running Light – 1W LED base glue

    What looks like melted solder is really an adhesive layer, much like the craft adhesive sheet I use to stick things together. Presumably, they just glue the LEDs to the PCB / heatsink, solder its two leads by hand, and call it done.

    Checking an LED marked “Dead” on the backside of its heatsink shows the amount of solder paste varies, but the LED wasn’t there when it melted:

    1W LED - base glue and PCB solder
    1W LED – base glue and PCB solder

    This not being the first time, I cleaned the adhesive off the center pad and the LED, removed the solder, applied a dab of heatsink grease, and soldered the LED in place.

    Which looked like this on the previous taillight:

    1W LED - thermal grease
    1W LED – thermal grease

    Might be a bit too much grease, but it’s certainly a better heat conductor than adhesive.

  • Worm Bin Vent Covers

    Worm Bin Vent Covers

    The current iteration of our Tumbleweed Can-O-Worms suffers from leakage down the legs:

    Worm Bin - leg leakage
    Worm Bin – leg leakage

    Perhaps surprisingly, the whole process is odorless. This is in the basement where ugly doesn’t count for much.

    The leakage comes through the air vent holes at the top of each leg socket:

    Worm Bin Vent Cover - vent
    Worm Bin Vent Cover – vent

    Unsurprisingly, the “worm tea” (it ain’t water!) dripping from the bottom of the compost tray goes directly through the vent holes and down the leg. It’s not clear to me what they expected.

    A simple 3D printed black TPU cap atop the leg socket should prevent most of the leakage:

    Worm Bin Vent Cover - installed
    Worm Bin Vent Cover – installed

    The odd pattern comes from Concentric infill around the notch, even though Concentric infill seems better suited to round things and fat extrusion threads with a 0.8 mm nozzle than straight lines. The weird stuff on the vertical side is a reflection of the basement and phone flash from the smooth TPU layer edges.

    The tray with the worms and compost sits atop the strut between the socket and the body, with the cap allowing room for the screen keeping the worms out of the sump.

    Ribs on the underside of the cap hold it above the leg socket to let the air through:

    Worm Bin Vent Covers - solid model
    Worm Bin Vent Covers – solid model

    Although five caps fit the MK4’s platform, I printed one or two at a time while tweaking improving the design:

    Worm Bin Vent Covers - PrusaSlicer preview
    Worm Bin Vent Covers – PrusaSlicer preview

    This design is for the original Can-O-Worms shown in the second picture and may not quite fit the new version. We’ll know more when we empty the bottom tray.

    The OpenSCAD source code as a GitHub Gist:

    // Worm Bin Leg Vent Cover
    // Ed Nisley – KE4ZNU
    // 2026-10-16
    include <BOSL2/std.scad>
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.01;
    NumSides = 8*2*3;
    $fn=NumSides;
    LayerHeight = 0.4; // print with 0.8 mm nozzle
    LayerWidth = 0.9;
    WallThick = 1.5*LayerWidth;
    VentOD = 62.0; // at bottom of cover
    VentTopClear = 9.0; // to next layer bottom
    VentSideClear = 11.0; // to bin side
    VentStrutWidth = 3.0;
    CoverHeight = 15.0;
    CoverOD = VentOD + 2*VentSideClear – 2*WallThick;
    NumRibs = 6;
    RibHeight = VentTopClear – WallThick – 2.0;
    RibThick = 2*WallThick;
    //—–
    // Build things
    difference() {
    union() {
    cyl(WallThick,d=CoverOD,circum=true,anchor=BOTTOM) position(TOP) {
    tube(CoverHeight – WallThick,od=CoverOD,wall=WallThick,circum=true,
    anchor=BOTTOM,spin=180/NumSides);
    for (i=[0:NumRibs-1])
    rotate(i*(360/NumRibs) + 180/NumRibs)
    right(CoverOD/3 – RibThick/2)
    cube([CoverOD/3,RibThick,RibHeight],anchor=BOTTOM);
    }
    up(WallThick)
    right(CoverOD/2 – WallThick)
    cube([VentSideClear,VentStrutWidth + 2*WallThick,RibHeight],anchor=BOTTOM+RIGHT);
    right(CoverOD/2 – WallThick + Protrusion)
    cube([VentSideClear – WallThick,VentStrutWidth + 2*WallThick,CoverHeight],anchor=BOTTOM+RIGHT);
    }
    down(Protrusion)
    right(CoverOD/2 – VentSideClear)
    cube([CoverOD,VentStrutWidth,2*CoverHeight],anchor=BOTTOM+LEFT);
    }

  • Window Film Mullion Filler

    Window Film Mullion Filler

    The living room windows suffer from all the thermal problems you might expect in a late-1960s house, despite the slightly more recent storm panes, so I’ve been adding insulating film during the cold season. This works surprisingly well, although the tape holding the film tends to lose its grip in the angle between the (real, not pretend!) mullions and the window sill.

    This year I added triangular fillers to ease the corner:

    LR Window Film - mullion filler
    LR Window Film – mullion filler

    They’re Desk Signs from boxes.py, with the bottoms angled by 2.5° to compensate for the slightly misaligned sill and a small cutout clearing the paint accumulation in the corner:

    LR Window mullion filler - LightBurn layout
    LR Window mullion filler – LightBurn layout

    A strip of tape down each side of the mullion and across the filler anchors the film, producing a slightly baggy fit. Next year I’ll use only one strip down the middle.

  • HQ Sixteen: Improved Table Shimming

    HQ Sixteen: Improved Table Shimming

    Although adding table shims / leveling blocks dramatically improved the HQ Sixteen’s travel along the table, it still had a tendency to roll away when parked at some locations. The padded shims had compressed enough to throw off the alignment between adjacent sections, so returning to the original rigid blocks seemed prudent.

    I removed all the shims to let the middle three sections of the tabletop droop as it did when we got it, put a ten foot saw guide across the entire table, and added 5 mm (!) plates to the stacks already under the high (!) end of the table feet to level the two ends. The floor is not that far out of level, so the table structure itself must be mismatched from one end to the other.

    Adding 3 mm (!) plates under the front pair of legs put the table far enough out of level to prevent the machine from rolling front-to-back on its carriage. I think the carriage is slightly bowed downward in the middle, but now the machine is more inclined (so to speak) to remain in one place.

    The saw guide showed the table sections on each end, despite being screwed firmly to the table structure, were slightly sloped downward toward the center. Shimming the sections with thin cardboard atop their steel mounting brackets leveled them so the machine no longer wanted to roll away when parked at either end, which was a good start.

    Adjoining table sections have peg-in-hole alignment, with their accuracy leaving something to be desired. Shims under the machine tracks level it across the mismatched joints:

    HQ Sixteen - table track shims - detail
    HQ Sixteen – table track shims – detail

    The brown chipboard is 0.7 mm thick and the white cardboard is 0.4 mm, with lengths eyeballometrically matching the misaligned part of the table section. They’re not quite so conspicuous in action:

    HQ Sixteen - table track shims
    HQ Sixteen – table track shims

    I then inserted wood shims under the tabletop to level the three middle sections. Unlike my previous efforts, each section got four shims to level it both front-to-back and side-to-side. After considerable iteration, the HQ Sixteen would remain where it was parked at (almost) every location across the entire table span.

    Then I used a set of small hole gauges to measure the distance between the table’s metal structure and the bottom of the tabletop section near each wood shim. I had previously used a taper gauge that measured the clearance on only the near side and it turns out the metal has plenty of irregularities across its bent shapes.

    Then feed the measured values into the OpenSCAD shim block generator mentioned earlier to get more shims:

    HQ Sixteen - table shims - array - solid model
    HQ Sixteen – table shims – array – solid model

    Slide them in place and remove the wood shims:

    HQ Sixteen - table shims - adjacent sections
    HQ Sixteen – table shims – adjacent sections

    Yes, that’s nearly a 1 mm difference, despite the bottoms of the two table sections being obviously aligned.

    Each block now has a narrow strip of craft adhesive sheet holding it to the table top, in the expectation hope the machine’s normal vibration won’t shake them loose.

    Initial user response is positive: the improved anchor may remain on the shelf.

  • HQ Sixteen: Improved Anchor

    HQ Sixteen: Improved Anchor

    The original anchor / weight keeping the HQ Sixteen from rolling away suffered a disastrous fall, so I conjured a much better-looking replacement from the vasty digital deep:

    HQ Sixteen - improved anchor
    HQ Sixteen – improved anchor

    The handle and fancy nut came from the deceased pepper mill, sitting on laser-cut acrylic in a 3D printed base, with a drawer liner disk peeking out from underneath.

    The orange disk in the solid model represents the steel slug harvested from the old anchor:

    HQ Sixteen Anchor - solid model - Show view
    HQ Sixteen Anchor – solid model – Show view

    A ring of hot-melt glue under the weight keeps it from rattling around in there, with the snug-fitting central post encouraging good positioning. I made the acrylic lid sit flush with the top of the base by the simple expedient of running another ring of glue around it, plunking the base + weight atop it on a flat surface, then taking a deep breath while the glue solidified. The nut & screw thus compress a solid stack of acrylic + glue + steel + glue + PETG-CF, rather than just parts flying in formation.

    The OpenSCAD source code also produces a pair of outlines for laser-cutting the adhesive sheet and acrylic, suitable for export to an SVG file:

    HQ Sixteen Anchor - solid model - cuts
    HQ Sixteen Anchor – solid model – cuts

    They’re offset inward by amounts appropriate for my CO₂ laser:

    if (Layout == "Cuts") {
      left(BaseOD/2 + Gap)
        offset(r=-1.0)
          circle(d=BaseOD);
      right(Cap[OD]/2 + Gap)
        offset(r=-0.2/2)
          projection()
            tube(1.0,id=Cap[ID],od=Cap[OD],anchor=BOTTOM);
    }
    

    It might be prudent to apply those offsets to the original outlines in LightBurn or whatever you use for lasering.

    The OpenSCAD source code as a GitHub Gist:

    // Anchor block for HQ Sixteen
    // Ed Nisley – KE4ZNU
    // 2026-09-29
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Cuts]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    Gap = 10.0/2; // build platform minimum spacing
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 8*3*2*4;
    $fn=NumSides;
    // Sizes
    Screw = [5.5,25.5,5.0]; // 10-24 screw + washer holding it together
    Weight = [11.0,80.0,11.5]; // stamped steel slug
    Cap = [26.0,Weight[OD],5.5]; // acrylic disk with handle hole
    BaseFloor = 10.0;
    BaseOD = 90.0; // printed anchor
    Spacing = 25.0; // Show view separation
    //———-
    // Model things
    module Housing() {
    tube(Screw[LENGTH],id=Screw[OD],od=BaseOD,anchor=BOTTOM) position(TOP) {
    tube(Weight[LENGTH],id=Screw[ID],od=Weight[ID],anchor=BOTTOM); // weight bushing
    tube(BaseFloor – Screw[LENGTH],id=Screw[ID],od=BaseOD,anchor=BOTTOM) position(TOP)
    tube(Cap[LENGTH] + Weight[LENGTH],id=Cap[OD],od=BaseOD,anchor=BOTTOM);
    }
    }
    //———-
    // Build things
    if (Layout == "Show") {
    Housing();
    color("Orange",0.7)
    up(BaseFloor + Spacing)
    tube(Weight[LENGTH],id=Weight[ID],od=Weight[OD],anchor=BOTTOM);
    color("Gray",0.8)
    up(BaseFloor + 2*Weight[LENGTH] + Spacing)
    tube(Cap[LENGTH],id=Cap[ID],od=Cap[OD],anchor=BOTTOM);
    }
    if (Layout == "Cuts") {
    left(BaseOD/2 + Gap)
    offset(r=-1.0)
    circle(d=BaseOD);
    right(Cap[OD]/2 + Gap)
    offset(r=0.2/2)
    projection()
    tube(1.0,id=Cap[ID],od=Cap[OD],anchor=BOTTOM);
    }
    if (Layout == "Build") {
    Housing();
    }

  • HQ Sixteen: Improved Fabric Rod Bushings

    HQ Sixteen: Improved Fabric Rod Bushings

    Descending from the previous bearings / sleeves / bushings, I added a rib to hold them in place as the rod slides back and forth while fiddling with fabric:

    HQ Sixteen - Rod Bushing - rib retainer - solid model - build view
    HQ Sixteen – Rod Bushing – rib retainer – solid model – build view

    An idealized serving suggestion:

    HQ Sixteen - Rod Bushing - rib retainer - solid model - show view
    HQ Sixteen – Rod Bushing – rib retainer – solid model – show view

    Which might count as the “better design” I expected it would need.

    They’re still almost invisible in use:

    HQ Sixteen - Rod Bushing - rib retainer
    HQ Sixteen – Rod Bushing – rib retainer

    Which is as it should be: inconspicuous, no more black dust, and E-Z rotation.

    The modified OpenSCAD source code is added to the original GitHub Gist:

    // Bushing for HQ Sixteen table rods
    // Ed Nisley – KE4ZNU
    // 2026-02-20
    // 2026-09-29 add retaining rib
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 8*3*2*4;
    $fn=NumSides;
    Rod = [25.0,28.7,100.0]; // very short rod
    Sleeve = [Rod[OD] + 0.3,31.2 – 0.2,9.0]; // LENGTH = overall
    Rim = [Sleeve[ID],Sleeve[OD] + 6.0,0.6];
    LockRing = [Sleeve[ID],Sleeve[OD] + 2*(1.0),4.0]; // locks sleeve on plate
    IdlerLength = 15.0; // far right end of rods
    NumSlots = 2*4;
    Kerf = 1.0;
    Gap = 5.0;
    module Bushing(oal,lk=false) {
    difference() {
    union() {
    tube(oal,id=Sleeve[ID],od=Sleeve[OD],anchor=BOTTOM);
    tube(Rim[LENGTH],id=Rim[ID],od=Rim[OD],anchor=BOTTOM);
    if (lk)
    up(oal)
    tube(LockRing[LENGTH],id=LockRing[ID],od=LockRing[OD],chamfer=LockRing[LENGTH]/3,anchor=TOP);
    }
    for (a=[0:NumSlots-1])
    zrot(a*360/NumSlots)
    up(oal/4 + Rim[LENGTH])
    right(Sleeve[ID]/2)
    cuboid([Sleeve[OD],Kerf,oal],anchor=BOTTOM);
    }
    }
    //—–
    // Build things
    if (Layout == "Show") {
    color("Gray",0.5)
    xcyl(Rod[LENGTH],d=Rod[OD]);
    right(Rod[LENGTH]/3)
    zrot(180) yrot(90)
    Bushing(Sleeve[LENGTH]);
    left(Rod[LENGTH]/3)
    yrot(90)
    Bushing(IdlerLength,lk=true);
    }
    if (Layout == "Build") {
    right(Rim[OD]/2 + Gap/2)
    Bushing(Sleeve[LENGTH]);
    left(Rim[OD]/2 + Gap/2)
    Bushing(IdlerLength,lk=true);
    }
    // Bearing sleeve for HQ Sixteen table rods
    // Ed Nisley – KE4ZNU
    // 2026-02-20
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 8*3*2*4;
    $fn=NumSides;
    Rod = [25.0,28.7,100.0]; // very short rod
    Sleeve = [Rod[OD] + 0.3,31.2 – 0.2,9.0]; // LENGTH = overall
    Rim = [Sleeve[ID],Sleeve[OD] + 6.0,0.6];
    IdlerLength = 15.0;
    NumSlots = 2*4;
    Kerf = 1.0;
    Gap = 5.0;
    module Bearing(oal) {
    difference() {
    union() {
    tube(oal,id=Sleeve[ID],od=Sleeve[OD],anchor=BOTTOM);
    tube(Rim[LENGTH],id=Rim[ID],od=Rim[OD],anchor=BOTTOM);
    }
    for (a=[0:NumSlots-1])
    zrot(a*360/NumSlots)
    up(oal/4 + Rim[LENGTH])
    right(Sleeve[ID]/2)
    cuboid([Sleeve[OD],Kerf,oal],anchor=BOTTOM);
    }
    }
    //—–
    // Build things
    if (Layout == "Show") {
    color("Gray",0.5)
    xcyl(Rod[LENGTH],d=Rod[OD]);
    right(Rod[LENGTH]/3)
    yrot(90)
    Bearing(Sleeve[LENGTH]);
    left(Rod[LENGTH]/3)
    yrot(90)
    Bearing(IdlerLength);
    }
    if (Layout == "Build") {
    right(Rim[OD]/2 + Gap/2)
    Bearing(Sleeve[LENGTH]);
    left(Rim[OD]/2 + Gap/2)
    Bearing(IdlerLength);
    }