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

  • HQ Sixteen: Improved Control Cap Final Assembly

    HQ Sixteen: Improved Control Cap Final Assembly

    My version of the Handi-Quilter HQ Sixteen grip control caps requires some assembly:

    Control Button Caps - solid model - build view
    Control Button Caps – solid model – build view

    Getting the OEM caps off the handlebars required carefully applying torque through a strap wrench, but they eventually came free:

    HQ Sixteen - OEM grip cap - screw holes
    HQ Sixteen – OEM grip cap – screw holes

    I don’t know what the unused screw hole between the two gnarly holes was for; perhaps they discovered one hole was inadequate.

    The alert reader will note the two screw holes are not the same distance from the end of the tube, which required rebuilding the plug model to match:

    Control Button Caps - solid model - plug holes
    Control Button Caps – solid model – plug holes

    Which is why I didn’t glue the plug into the cap before I got the OEM caps off.

    Redrill the tube holes to 3 mm, file the burrs from both the OEM and my drilling, smooth the edges, and the plug fit perfectly. Then I seated the M3 square nuts behind those hole and, after installing the new plugs in the handlebars, glued the caps in place with a simple fixture to ensure the front faced forward:

    - HQ Sixteen - grip cap faceplate gluingHQ Sixteen - grip cap gluing
    – HQ Sixteen – grip cap faceplate gluingHQ Sixteen – grip cap gluing

    The clamp gently compresses the foam enough to hold the flats against the bench block while the JB Plastic Bonder cures.

    After verifying all the buttons worked, I glued the faceplates to the cap bodies:

    HQ Sixteen - grip cap faceplate gluing
    HQ Sixteen – grip cap faceplate gluing

    The tape held the faceplate in place while I snugged the clamps.

    Modulo my weak graphic design skills, the caps look pretty good:

    HQ Sixteen - grip cap installed - right
    HQ Sixteen – grip cap installed – right

    And, after a bit of wiring yet to be described, the buttons do exactly what their legends suggest:

    HQ Sixteen - grip cap installed - left
    HQ Sixteen – grip cap installed – left

    The white sheet with feeble graphics can be peeled off, so I have another chance to tart it up.

    The overall idea was to replace the failing Start/Stop switch while duplicating that switch on both caps. While I was at it, I also duplicated the Needle Up/Down button, because who wants asymmetric caps?

    Mary is assembling another quilt and the new switches will get plenty of action …

  • Metal Spring Clamp: TPU Jaw Pads

    Metal Spring Clamp: TPU Jaw Pads

    Setting up the Makergear M2 to print TPU (eSun 95A) involved a cold pull to get the remaining PETG out of the nozzle, some manual flushing, then printing test cubes to figure out a reasonable speed / temperature combination:

    Makergear M2 - first TPU test cube
    Makergear M2 – first TPU test cube

    A 10 mm solid cube came out overstuffed and the first 20 mm cube lacked enough infill to hold its top up, but the third cube looked surprisingly good at 230 °C and 30 mm/s with 15% 3D Honeycomb infill:

    Makergear M2 - TPU test cubes
    Makergear M2 – TPU test cubes

    With that settled, I conjured pairs of soft (-ish) jaw pads for the far-too-many metal spring clamps having worn out their vinyl pads:

    Spring clamp jaws - installed
    Spring clamp jaws – installed

    Those were the first attempt and worked well enough to suggest nicely rounded endcaps instead of flat cylinders:

    Spring Clamp Jaws - show view
    Spring Clamp Jaws – show view

    Unlike the first version, they now build standing on their rectangular clamp jaw opening:

    Spring Clamp Jaws - slicer preview
    Spring Clamp Jaws – show view

    Those two groups have different lengths (1 inch and 1-⅛ inch) with PrusaSlicer combining the OpenSCAD program’s output.

    The as-built pads are essentially un-photographable:

    Spring clamp jaws - group build
    Spring clamp jaws – group build

    TPU is tough enough to make the single-layer brim un-tearable, but they’re easy enough to separate & trim with scissors. Even the 5 mm brim has a tenuous grip on glass + Suave hair “spray” applied from a dropper bottle, so I should try a BuildTak sheet that’s been on the to-do pile for far too many years.

    Similarly, TPU is flexy enough to make a precise fit unnecessary: push firmly to force the pads onto the jaws and you’re done.

    The OpenSCAD source code as a GitHub Gist:

    // Spring clamp replacement jaw pad
    // Ed Nisley – KE4ZNU
    // 2025-04-26
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Clamp]
    Ends = "Round"; // [Flat,Round]
    Sets = 1;
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 2*3*4;
    WallThick = 2.0;
    CushionOD = 10.0;
    CushionStem = 10.0;
    JawAngle = 60/2; // just for Show
    JawWidth = 1.000*INCH; // clamps are hard-inch sizes: 1.0 and 1.125
    Jaw = [1.5,50,JawWidth]; // roughly one jaw
    Gap = 2.0;
    $fn = 2*3*4;
    //———-
    // Define objects
    //—–
    // Clamp jaw
    module Clamp() {
    up(WallThick)
    cuboid(Jaw,anchor=BOTTOM+BACK);
    }
    module Pad() {
    difference() {
    union() {
    cyl(d=CushionOD,h=Jaw.z + 2*WallThick,anchor=BOTTOM,
    rounding = (Ends == "Flat") ? 0 : CushionOD/2);
    cuboid([Jaw.x + 2*WallThick,CushionStem,Jaw.z + 2*WallThick],
    rounding=WallThick/2,anchor=BOTTOM+BACK);
    }
    Clamp();
    }
    }
    //———-
    // Build things
    if (Layout == "Clamp") {
    Clamp();
    }
    if (Layout == "Show") {
    for (i = [-1,1])
    right(i*(CushionOD + Gap)/2)
    zrot(i*JawAngle) {
    Pad();
    color("Silver",0.5)
    Clamp();
    }
    }
    if (Layout == "Build") {
    for (n = [0:(Sets – 1)])
    for (i = [-1,1])
    right(i*((CushionOD + Gap)/2 + n*(CushionOD + Gap)))
    up(CushionStem) back(Jaw.z/2) xrot(90)
    Pad();
    }
  • Champion Hose Nozzle: TPU Washer

    Champion Hose Nozzle: TPU Washer

    There being nothing like a good new problem to take one’s mInd off one’s old problems, I set the Makergear M2 to printing TPU and made a washer for the Champion Hose Nozzle:

    Champion hose nozzle - TPU vs rubber washers
    Champion hose nozzle – TPU vs rubber washers

    It turns out PrusaSlicer can produce models for simple shapes using the Shape Gallery. Subtracting a 7.5 mm cylinder (as a “negative shape”) from a 12.7 mm = ½ inch cylinder does the trick, with the washer all of 2.5 mm thick.

    The ID of the thread inside the nozzle is slightly smaller than 12.7 mm, but TPU is bendy enough to let me push it through sideways and reorient it against the front of the nozzle.

    The conical part of the nozzle seals against the washer, leaving only a very slight ooze of water, and opens far enough to produce a jet. The TPU is solid enough to not vibrate in the flow and the nozzle no longer howls at low flow rates.

    None of the other nozzles in the box have a washer up in there, so they all depend on a much better machined fit than I achieved.

    At least the Champion nozzle is once again usable, should it ever emerge from the bottom of the box.

  • Improved Sony AS30V Helmet Mount Adapter Plate

    Improved Sony AS30V Helmet Mount Adapter Plate

    Last week a wind gust blew my Tour Easy over while resting on its kickstand at Mary’s garden; I rarely depend on the kickstand for that very reason, but some days are like that. Anyhow, the mount for the Sony AS30V helmet camera did exactly what it should by releasing the camera, rather than grinding it into the ground.

    Calling it a “mount” may be overstating the case:

    Sony HDR-AS30V camera on bike helmet - inverted
    Sony HDR-AS30V camera on bike helmet – inverted

    I was still using that helmet, albeit with a better mirror mount, but it was getting rather crusty and the hook-n-loop straps were definitely sun-faded, so I built a better mount with an adapter plate matching a new-old-stock helmet from the stash:

    Sony AS30V Helmet mount - side view
    Sony AS30V Helmet mount – side view

    The white slab atop the helmet curves to match the helmet contour, with the ridge fitting into the vent slot:

    AS30 helmet mount - solid model - show view
    AS30 helmet mount – solid model – show view

    OK, the helmet isn’t orange, but you get the idea. The sphere has a 153 mm radius, calculated from the Official Sony helmet mount’s bottom curve, minus a ring shaping the central groove:

    AS30 helmet mount - solid model - tab ring
    AS30 helmet mount – solid model – tab ring

    This upside-down view shows the interesting parts:

    AS30 helmet mount - solid model
    AS30 helmet mount – solid model

    The flat side sticks to the camera’s holder with a custom-cut sheet of craft adhesive shaped like this:

    AS30 helmet mount - glue
    AS30 helmet mount – glue

    The overall outline of those things comes from a scan of the bottom of the Sony camera holder, passed through Inkscape and LightBurn to generate the curves:

    AS30 Baseplate scan
    AS30 Baseplate scan

    The large notches in the sides pass hook-n-loop straps intended to break away when the helmet hits the ground again. The front tunnel (of two, because symmetry) passes a cable tie preventing the camera from parting company with the mount during normal riding and holding the yellow latch in the Locked position:

    Sony AS30V Helmet mount - rear view
    Sony AS30V Helmet mount – rear view

    It is just barely possible to slide the cable tie over the front of the camera to release the latch.

    The camera rides upside-down to protect the lens from scuffs and scrapes. Fortunately, there’s a setting to invert the picture.

    For completeness, the front view:

    Sony AS30V Helmet mount - front view
    Sony AS30V Helmet mount – front view

    The furry patch covers the microphone pores to kill (most of) the wind noise.

    The sharp ventral angle matches the helmet’s midline ridge in the back, but obviously isn’t needed over the vent hole in the front. I decided to not bother making a comprehensive model of the hole, not least because I didn’t really know the camera’s exact front-to-back location.

    Works fine where it sits, though:

    Burnett Signal Timing - 2025-04-23
    Burnett Signal Timing – 2025-04-23

    NYSDOT’s signal timing at Burnett Blvd and Rt 55 remains bicycle-hostile, same as it ever was.

    The OpenSCAD source code and baseplate shape as a GitHub Gist:

    // Sony AS30 helmet mount
    // Ed Nisley – KE4ZNU
    // 2025-04-20
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Ball,Tab,Glue]
    Gap = 5; // [0:5:20]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    WallThick = 1.0; // enough stiffness against flat pad
    HelmetRadius = 153.0; // from chord equation on curved pad = magic number
    Groove = [30.0,100,3.0,]; // roughly the groove along helmet midline
    Pad = [38,53,10]; // baseplate size, thick enough without fancy trig
    Strap = [3.0,15.0,10*Pad.z]; // hook-n-loop strap holes, double-thick
    Tie = [100,6.0,2.0 + Protrusion]; // cable tie around camera
    TieOffset = 14.0; // … from end of pad
    $fn=96;
    //———-
    // Define shapes
    module Ball() {
    difference() {
    sphere(r=HelmetRadius);
    Tab();
    }
    }
    // Rough approximation of the helmet groove
    module Tab() {
    m = 2.0; // roughly the chord height beyond the tab
    rotate_extrude(convexity=10) {
    right(HelmetRadius)
    zrot(180)
    polygon([
    [0,0],
    [0,Groove.x/2],[Groove.z + m,Groove.x/2],[m,0],
    [Groove.z + m,-Groove.x/2],[0,-Groove.x/2],
    [0,0]
    ],convexity=10);
    }
    }
    // Baseplate with all the cutouts
    module BasePlate() {
    difference() {
    linear_extrude(height=Pad.z,convexity=10)
    import("AS30 Baseplate layout.svg",layer="Baseplate");
    up(WallThick + HelmetRadius)
    yrot(90)
    Ball();
    for (i = [-1,1]) // strap clearance at edge of helmet hole
    right(i*Groove.x/2)
    cube([(Pad.x – Groove.x)/2,Strap.y,Strap.z],center=true);
    for (i = [-1,1]) // cut through edge of pad
    right(i*Pad.x/2)
    cube([(Pad.x – Groove.x),Strap.y,Strap.z],center=true);
    for (j = [-1,1])
    fwd(j*(Pad.y/2 – TieOffset)) up(WallThick)
    cuboid(Tie,anchor=BOTTOM);
    }
    }
    //———-
    // Build things
    if (Layout == "Glue")
    projection(cut=true)
    BasePlate();
    if (Layout == "Tab")
    Tab();
    if (Layout == "Show") {
    xrot(180)
    BasePlate();
    down(WallThick + HelmetRadius + Gap)
    yrot(90)
    color("Orange",0.75) Ball();
    }
    if (Layout == "Build")
    BasePlate();
    if (Layout == "Ball")
    Ball();
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!– Created with Inkscape (http://www.inkscape.org/) –>
    <svg
    width="11in"
    height="8.5in"
    viewBox="0 0 279.40056 215.90043"
    version="1.1"
    id="SVGRoot"
    inkscape:version="1.4.1 (93de688d07, 2025-03-30)"
    sodipodi:docname="AS30 Baseplate layout.svg"
    xml:space="preserve"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape&quot;
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd&quot;
    xmlns:xlink="http://www.w3.org/1999/xlink&quot;
    xmlns="http://www.w3.org/2000/svg&quot;
    xmlns:svg="http://www.w3.org/2000/svg&quot;
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;
    xmlns:cc="http://creativecommons.org/ns#"><sodipodi:namedview
    id="namedview7"
    pagecolor="#ffffff"
    bordercolor="#0000ff"
    borderopacity="1"
    inkscape:pageshadow="0"
    inkscape:pageopacity="0"
    inkscape:pagecheckerboard="1"
    inkscape:document-units="mm"
    showgrid="true"
    units="mm"
    gridtolerance="9.9"
    guidetolerance="10.4"
    inkscape:snap-perpendicular="true"
    inkscape:snap-tangential="true"
    width="700mm"
    borderlayer="false"
    inkscape:showpageshadow="true"
    viewbox-width="700"
    guidecolor="#ff00e3"
    guideopacity="0.49803922"
    inkscape:zoom="1.6945884"
    inkscape:cx="86.451671"
    inkscape:cy="111.82656"
    inkscape:window-width="1780"
    inkscape:window-height="1091"
    inkscape:window-x="0"
    inkscape:window-y="0"
    inkscape:window-maximized="0"
    inkscape:current-layer="layer1"
    objecttolerance="31"
    inkscape:deskcolor="#d1d1d1"
    showguides="true"><inkscape:grid
    type="xygrid"
    id="grid9"
    units="mm"
    spacingx="5"
    spacingy="5"
    dotted="false"
    empspacing="2"
    originx="148.5"
    originy="127.29919"
    color="#ff0000"
    opacity="0.18431373"
    empcolor="#4040ff"
    empopacity="0.49411765"
    visible="true" /><sodipodi:guide
    position="157.7549,120.64599"
    orientation="1,0"
    id="guide1"
    inkscape:locked="false" /></sodipodi:namedview><defs
    id="defs2" /><g
    inkscape:label="Baseplate"
    inkscape:groupmode="layer"
    id="layer1"
    transform="translate(0,5.4354331)"><path
    id="path1"
    style="fill:none;fill-rule:evenodd;stroke:#0c96d9;stroke-width:0.0998686;stroke-linejoin:round"
    d="m -18.99969,190.42075 3.09576,-6.45581 h 32.08112 l 2.82285,6.45581 -10e-6,40.00473 -3.02778,6.53957 -31.33905,-0.14658 -3.63324,-6.39299 z"
    sodipodi:nodetypes="ccccccccc"
    inkscape:label="Aligned path" /></g><g
    inkscape:groupmode="layer"
    id="layer2"
    inkscape:label="Original"><image
    width="57.658115"
    height="65.193459"
    preserveAspectRatio="none"
    xlink:href="AS30%20Baseplate%20scan.jpg"
    id="image1"
    x="112.42073"
    y="67.772316"
    transform="rotate(0.87516737,-355.84202,2.7177945)"
    style="display:inline" /><path
    id="rect1"
    style="fill:none;fill-rule:evenodd;stroke:#0c96d9;stroke-width:0.0998686;stroke-linejoin:round"
    d="m 120.39572,83.160307 3.09576,-6.45581 h 32.08112 l 2.82285,6.45581 -1e-5,40.004733 -3.02778,6.53957 -31.33905,-0.14658 -3.63324,-6.39299 z"
    sodipodi:nodetypes="ccccccccc"
    transform="translate(0,5.4354331)" /></g><metadata
    id="metadata11"><rdf:RDF><cc:Work
    rdf:about=""><cc:license
    rdf:resource="http://creativecommons.org/licenses/by-nc-sa/4.0/&quot; /></cc:Work><cc:License
    rdf:about="http://creativecommons.org/licenses/by-nc-sa/4.0/"><cc:permits
    rdf:resource="http://creativecommons.org/ns#Reproduction&quot; /><cc:permits
    rdf:resource="http://creativecommons.org/ns#Distribution&quot; /><cc:requires
    rdf:resource="http://creativecommons.org/ns#Notice&quot; /><cc:requires
    rdf:resource="http://creativecommons.org/ns#Attribution&quot; /><cc:prohibits
    rdf:resource="http://creativecommons.org/ns#CommercialUse&quot; /><cc:permits
    rdf:resource="http://creativecommons.org/ns#DerivativeWorks&quot; /><cc:requires
    rdf:resource="http://creativecommons.org/ns#ShareAlike&quot; /></cc:License></rdf:RDF></metadata></svg>
    view raw gistfile1.txt hosted with ❤ by GitHub
  • Tour Easy: Broken Seat Parts

    Tour Easy: Broken Seat Parts

    So hardened socket head cap screws survive fifteen years of hard service on my Tour Easy’s seat stay:

    Tour Easy - broken seat stay screw
    Tour Easy – broken seat stay screw

    I replaced both screws with stainless steel 1-½ 10-32 socket head screws, with a reshaped head on the drive side, and we’ll see how long these last.

    A few days later the continuing creak led to finding a broken gear clamp on the left side of the seat back:

    Tour Easy - replacement seat frame clamp
    Tour Easy – replacement seat frame clamp

    Apart from the atypical lack of grime, you couldn’t tell that’s the replacement clamp, because the broken one looked exactly the same way. The clamp strap broke where it bent around the bottom edge of the seat pan bracket, probably due to the flexing caused by the broken seat stay screw.

    Riding season is in full effect!

  • Bird Box: Rotating T-Nuts

    Bird Box: Rotating T-Nuts

    A bird box from long ago emerged from the heap and took its place in an upstairs window:

    Bird Box window mount - installed
    Bird Box window mount – installed

    That big open back held an acrylic sheet letting us watch wrens raise their family; snugging it against the window makes that sheet superfluous. We’re hoping to lure the Wreath Finches from their preferred spot by the front door, but we’re open to any birds in need of a nesting spot.

    The aluminum angle formerly securing the box to various wood window frames wasn’t going to work here, so I conjured a pair of rotating T-nuts to fit the track in the plastic window frame:

    Bird Box window mount - nuts
    Bird Box window mount – nuts

    They’re made from a 5/16-18 T-nut and two layers of 3 mm plywood, all glommed together with E6000-Plus adhesive because it did not scamper out of the way when I opened the Adhesives Cabinet.

    Some doodling convinced me a pair of quarter-circles welded back-to-back, minus cutouts for the metal T-nuts, would suffice:

    Bird Box window mount - nuts
    Bird Box window mount – nuts

    The radius must be a little less than the width of the opening into the channel (20 mm) and the diameter must be a little more than the width of the channel behind that opening (32-ish mm), so I picked 17 mm. The metal T-nut flange is just over 20 mm, but the spike cutouts (omitted from the LightBurn layout) let it slip through the opening.

    A random block of wood positions the box away from the frame enough to clear the outermost flange carrying the screen. Drilling oversize ⅜ inch holes countersunk the top of the T-nut into the block and eliminated excessive alignment fussiness.

    Slicing 20 mm off the bolts fit them into the space available, with a pair of stainless washers covering the gaps.

    A doodle with measurements you won’t need, but surely handy for mounting something else around here:

    Bird Box window mount - size doodles
    Bird Box window mount – size doodles

    Now, to see who takes up residence …

  • Champion Hose Nozzle: Needs a Washer?

    Champion Hose Nozzle: Needs a Washer?

    An email discussion suggested the Champion hose nozzle might, once upon a time, have had a washer between the conical and cylindrical sections.

    So I made one:

    Champion hose nozzle - rubber washer
    Champion hose nozzle – rubber washer

    The details:

    • OD = ½ inch
    • ID = 9/32 inch
    • 2.5 mm stamp pad rubber

    It sealed perfectly, but, just before shutting off, the washer vibrated in the water flow and gave off an ear-shattering (even to my deflicted hearing) howl.

    Perhaps a stiffer and thinner washer with a slightly larger OD would work better.

    A quick check of similar nozzles in the Box o’ Hydraulics shows none of them feel like they have a compliant washer in there, but any sufficiently old rubber will have long since fossilized.

    This seems like a good job for a 3D printed washer with a conical face, made from slightly squishy TPU plastic to ease it past the nozzle’s internal threads. All I need is the ability to print TPU …