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

  • 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);
    }
  • Knitted Spider: Eyemaxxing

    Knitted Spider: Eyemaxxing

    A 3D printed spider with a knitted texture seemed a sufficient oxymoron to justify its existence:

    Knitted Spider - black eyes
    Knitted Spider – black eyes

    But all-black looked rather somber, even for an All Hallow’s Eve decoration, so I used PrusaSlicer’s Multi-Material Painting to print the eyes in retina-burn orange:

    Knitted Spider - orange eyes - wipe tower
    Knitted Spider – orange eyes – wipe tower

    The chunky wipe tower shows the cost of switching filaments for a quartet of little eyes. The new Prusa INDX extruder design reduces that waste, but I’m not going there.

    You can see the block of painted-on support under the palps, which worked better than overenthusiastic automatic support generation.

    The consensus suggested the spider suffered from insufficient eye, so I upleveled it to maximum spider spec:

    Knitted Spider - 8 eyes - on platform
    Knitted Spider – 8 eyes – on platform

    Which looks like evolution in action:

    Knitted Spider - iteration
    Knitted Spider – iteration

    The additional eyes came from a trivial OpenSCAD / BOSL2 sphere:

    include <BOSL2/std.scad>
    spheroid(d=5.0,style="icosa");
    

    Which is both small and large enough to have a useful number of facets:

    Knitted Spider - 5mm icosa sphere eye model
    Knitted Spider – 5mm icosa sphere eye model

    Those facets will come in handy for Multi-Material Painting.

    Adding the sphere to the spider model turned out to be trickier than I imagined, because PrusaSlicer requires object to sit flat on the platform, but merging the sphere and spider models got it done:

    Knitted Spider - merged models
    Knitted Spider – merged models

    Then you can use the Move tool to haul the sphere into place:

    Knitted Spider - eye positioning
    Knitted Spider – eye positioning

    Use the Scale tool to reduce it to a suitable size.

    With the eye in place, copy-n-paste creates a duplicate Merged sphere at the same coordinates, which you chivvy into its proper spot. Repeat as needed for more eyes!

    The sphere facets are far below the 0.4 mm nozzle’s resolution, but they simplify painting the eye with “Smart Fill” angle settings:

    Knitted Spider - 8 eyes - slicer material painting
    Knitted Spider – 8 eyes – slicer material painting

    I had initially thought to just drop separate spheres in place and assign them to the orange extruder, but the slicer (quite properly) treats them as separate objects and creates balls sitting in sockets.

    Instead, the eyes must become part of the spider’s shape, have their exterior surfaces painted, then get sliced. In order to do that, I exported the 8-eyed spider as a new STL file and imported it back for painting & slicing:

    Knitted Spider - 8 eyes - slicer model
    Knitted Spider – 8 eyes – slicer model

    The original single-color spider prints in an hour and adding any number of eyes doubles the time, so those MMU3 tool changes are expensive. Although the printer is reliable, the auto-retract spools I set up sometimes retract the filament beyond the feed gear inside the MMU3, which the firmware detects and calls for manual intervention. It’s best to be puttering in the basement while the printer buzzes away.

  • Shower Squeegee Hanger

    Shower Squeegee Hanger

    Perhaps a 3 mm spacer behind the Command Hook holding the shower squeegee to the stall will let the blade dry out between uses:

    Shower Squeegee Hanger - installed
    Shower Squeegee Hanger – installed

    It’s fluorescent green acrylic, because why not?

    As with all such things, start with a scan of the base:

    Command Hook - base scan
    Command Hook – base scan

    Then:

    • Import into LightBurn
    • Draw a rectangle fitting the base
    • Convert to a path
    • Node Edit to put the corner nodes on the perimeter
    • Tweak node handles to match curves to perimeter
    • Fire The Laser

    Contrary to what I expected, the base is not symmetric.

    The layout includes another, slightly inset, path to cut a matching shape of 3M 300LSE adhesive to stick the Command Hook onto the acrylic:

    Shower Squeegee Hanger - spacer plate
    Shower Squeegee Hanger – spacer plate

    You could stick a rectangle of 300LSE to the acrylic and cut both in one operation, but making the sheet slightly smaller prevents sticky edges, at the cost of aligning the cut sheet on the fly.

    The Command Hook’s base is not flat, even after mostly removing the remainder of the previous Hook adhesive, so the 300LSE didn’t bond across the whole thing. If water weakens the bond and it falls off the wall (surely in the middle of the night), the next time around I’ll sand the base flat.

  • Bike Rack Tray Holder: Small Version

    Bike Rack Tray Holder: Small Version

    Mary wanted to haul seedlings started in half-gallon milk bottles to their destination and I figured they shouldn’t slide around while being transported:

    Milk bottle seedling starter carrier
    Milk bottle seedling starter carrier

    That’s a half-width drawer from the same salvaged collection that produced the Bike Rack Tray Holder and a few minutes with LightBurn adapted the wider cardboard bike rack mount to fit the narrower drawer:

    Bike Rack Tray Holder - small - LightBurn layout
    Bike Rack Tray Holder – small – LightBurn layout

    Basically, use Node Edit to delete the horizontal lines, move the sides inward by half the difference of the drawer widths, then draw a few short lines to close the gaps.

    Hot-melt gluing four layers of cardboard with crossed corrugations, plus three flat bottom layers, got it done:

    Bike Rack Tray Holder - small drawer - installed
    Bike Rack Tray Holder – small drawer – installed

    Those are the same stretchy TPU straps, with an additional link on each rear chain to compensate for the slightly higher block mount and a slightly narrower front block to fit in the slightly narrower drawer handle:

    Bike Rack Tray Holder - half-width drawer straps
    Bike Rack Tray Holder – half-width drawer straps

    Of course, the only way to know what didn’t fit was to make a pair of the original ones, try them on for size, then adapt the OpenSCAD code accordingly.

    That was surprisingly easy …

  • Freezer Tray Rack

    Freezer Tray Rack

    The new chest freezer’s interior has a rectangular lump on the right side over the compressor, atop which we’d been stacking foam trays of ground meat. To forestall a tragic landslide, I made a quick-n-easy rack held together with hot-melt glue:

    Freezer Tray Rack - test fit
    Freezer Tray Rack – test fit

    It doesn’t look like it grew there, but it’ll suffice:

    Freezer Tray Rack - installed
    Freezer Tray Rack – installed

    The weird black things are silicone molds for 4 fl. oz. ice balls (known in these parts as “iceteroids”) suited for chilling the water used to quench veggies after steaming / blanching, prior to freezing.

    The LightBurn layout arranges the parts in tool-layer rectangles matching a shipping box of 6.5 mm cardboard rugged enough for at least a prototype:

    Freezer Tray Rack - LightBurn layout
    Freezer Tray Rack – LightBurn layout

    The jawbreaker boxes.py URL adds 5 mm to the shelf height for a little more clearance. You’ll likely have different cardboard in your stockpile, so tweak as needed, add vent holes in the sides & back, and Fire The Laser.

  • Input-Remapper Key Macros

    Input-Remapper Key Macros

    Having gotten the Huion H610Pro V2 tablet buttons working again, I must document the input-remapper settings I use for all the UI devices under my fingers.

    Button 3 on the tablet fills in the fields for WordPress media images:

    WordPress Media Fields
    WordPress Media Fields

    Which start out with only the Title field prefilled with the name I created when I saved the file:

    PXL_20260826_234256883 - Chipboard Fragment Coaster - detail.jpg
    

    I highlight everything to the left of “Chipboard” and tap Button 3 to fire this series of keystrokes into the browser to cut the highlighted file name, then copy-n-paste everything else into the other three fields:

    modify(KEY_LEFTCTRL,key(x)).
    modify(KEY_LEFTCTRL,key(a)).
    modify(KEY_LEFTCTRL,key(c)).
    key(KEY_TAB).
    modify(KEY_LEFTCTRL,key(v)).
    key(KEY_TAB).
    modify(KEY_LEFTCTRL,key(v)).
    modify(KEY_RIGHTSHIFT,key(key_tab)).
    modify(KEY_RIGHTSHIFT,key(key_tab)).
    modify(KEY_RIGHTSHIFT,key(key_tab)).
    modify(KEY_RIGHTSHIFT,key(key_tab)).
    modify(KEY_LEFTCTRL,key(v))
    

    Part of creating those image files in GIMP involves cropping the file to a standard aspect ratio (4:3, 16:9, rarely 32:9 for really skinny images), then scaling to make the widest / tallest edge 1500 pixels with this dialog (invoked by the * key on the numeric keypad):

    GIMP Scale Image fields
    GIMP Scale Image fields

    For unknown reasons, Pixel 10a phone cameras have reverted to 72 DPI images, rather then the previous 300 DPI. Because some programs / browsers / whatever set the physical image size by dividing the number of pixels by the DPI, I prefer to set those fields to 300 DPI.

    So click to put the cursor in the widest field, then hit Button 4 to fill in the rest with these keystrokes:

    modify(KEY_LEFTCTRL,key(a)).
    key(KEY_1).key(KEY_5).key(KEY_0).key(KEY_0).
    key(KEY_TAB).key(KEY_TAB).key(KEY_TAB).key(KEY_TAB).
    key(3).key(0).key(0).
    key(KEY_TAB).key(KEY_TAB)
    

    Fortunately, the Resolution fields are locked, so filling in either one sets the other to match, and the keystrokes work correctly in either the Width or Height field.

    For unknown reasons, the Huion tablet appears once in the lsusb listing:

    Bus 001 Device 017: ID 256c:006d HUION Huion Tablet
    
    

    But dmesg shows many variations:

    [    2.826523] input: HUION Huion Tablet Pen as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0004/input/input15
    [    2.826632] input: HUION Huion Tablet Pad as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0004/input/input16
    [    2.826723] input: HUION Huion Tablet Touch Strip as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0004/input/input17
    [    2.826816] input: HUION Huion Tablet Dial as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0004/input/input18
    [    2.826941] uclogic 0003:256C:006D.0004: input,hidraw11: USB HID v1.11 Keypad [HUION Huion Tablet] on usb-0000:00:14.0-4.2/input0
    [    2.834767] uclogic 0003:256C:006D.0005: hidraw4: USB HID v1.11 Device [HUION Huion Tablet] on usb-0000:00:14.0-4.2/input1
    
    

    Those devices (endpoints, whatever) change as various other USB devices get plugged / unplugged / enumerated:

    12986.011937] usb 1-4.2: USB disconnect, device number 16
    [12986.359640] usb 1-4.2: new full-speed USB device number 17 using xhci_hcd
    [12986.579858] usb 1-4.2: New USB device found, idVendor=256c, idProduct=006d, bcdDevice= 1.00
    [12986.579876] usb 1-4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [12986.579882] usb 1-4.2: Product: Huion Tablet
    [12986.579887] usb 1-4.2: Manufacturer: HUION
    [12986.642042] input: HUION Huion Tablet Pen as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0014/input/input50
    [12986.642609] input: HUION Huion Tablet Pad as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0014/input/input51
    [12986.643357] input: HUION Huion Tablet Touch Strip as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0014/input/input52
    [12986.643699] input: HUION Huion Tablet Dial as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.2/1-4.2:1.0/0003:256C:006D.0014/input/input53
    [12986.644245] uclogic 0003:256C:006D.0014: input,hidraw0: USB HID v1.11 Keypad [HUION Huion Tablet] on usb-0000:00:14.0-4.2/input0
    [12986.707886] uclogic 0003:256C:006D.0015: hidraw1: USB HID v1.11 Device [HUION Huion Tablet] on usb-0000:00:14.0-4.2/input1
    [14148.081803] input: HUION Huion Tablet Pad as /devices/virtual/input/input55
    
    

    On some occasions, based on no events I understand, input-remapper will recognize the tablet as any one of:

    drwxr-xr-x  2 ed ed 4.0K Feb 18  2025 'HUION Huion Tablet'/
    drwxr-xr-x  2 ed ed 4.0K Sep  1 10:43 'HUION Huion Tablet Pad'/
    drwxr-xr-x  2 ed ed 4.0K Apr  3  2024 'HUION Huion Tablet Pen'/
    
    

    The dates show it’s been ‘HUION Huion Tablet Pad’ for a while, but ya never know what tomorrow will bring.

    The Elecom Deft Pro trackball at my right hand has seven buttons (three hidden around the ball) and a scroll wheel with up-down switches (called Wheel Right and Wheel Left from their horizontal mouse ancestry):

    Elecom Deft Pro trackball
    Elecom Deft Pro trackball

    Yeah, I oughta scrub that puppy more often.

    The wheel up-down switches map to the Home and End keys with the Ctrl key held down to jump to the beginning and end of the page:

    KEY_LEFTCTRL+KEY_HOME
    KEY_LEFTCTRL+KEY_END
    

    The wheel also has a push switch (the Middle mouse button) that I find inconvenient, so Button 6 (labeled Fn1 on the button) under my forefinger does that:

    BTN_MIDDLE
    

    Closing a browser tab happens so often it’s mapped to the small square button just over the resolution slide switch where my thumb can hit it:

    KEY_LEFTCTRL+w
    

    The Kensington Expert Mouse trackball (which continues to work!) under my left hand:

    Kensington Expert Mouse Trackball - worn button
    Kensington Expert Mouse Trackball – worn button

    Has had its buttons thoroughly rearranged:

    LL = Mouse Button LEFT → BTN_RIGHT
    UL = Mouse Button MIDDLE → XF86Back
    LR = Mouse Button RIGHT → BTN_LEFT
    UR = Mouse Button 4 → BTN_MIDDLE
    
    

    Your mileage will most certainly be different.