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

  • Hose Nozzle Flow Restrictors

    Hose Nozzle Flow Restrictors

    Mary wanted less pressure in the spray while watering her plants and I suggested replacing the nozzle’s washer with a flow restrictor:

    Hose Nozzle Flow Restrictors - assembled
    Hose Nozzle Flow Restrictors – assembled

    The 3D-printed TPU base is squishy enough to act as a hose washer:

    Hose Nozzle Flow Restrictor Base - solid model
    Hose Nozzle Flow Restrictor Base – solid model

    A 1.5 mm thick acrylic orifice plate snapped into the opening takes advantage of the laser cutter’s precision:

    Hose Nozzle Flow Restrictors - LightBurn layout
    Hose Nozzle Flow Restrictors – LightBurn layout

    For lack of anything smarter, the holes have areas that are powers-of-two smaller than the nozzle’s 14.2 mm = 158 mm² internal passage: the hole labeled 8 is 158/256 mm² = 0.62 mm² → 0.9 mm diameter.

    Rather than figuring each hole’s diameter, just divide the previous diameter by √2 or rescale it by 100%/√2, which LightBurn can evaluate directly in its Numeric Edits fields. The as-cut holes are larger than their nominal size by about 0.1 mm, but any errors that might cause are definitely in the nature of fine tuning while watering the plants.

    The nozzle’s Shower pattern (on the left in the picture) has a 6.8 L/minute = 110 ml/s flow through an ordinary garden hose washer. The four smallest aperture plates produced these flows:

    Hose Nozzle Flow Restrictors - flow vs dia
    Hose Nozzle Flow Restrictors – flow vs dia

    The flow should scale with the square of the aperture diameter, which I could bully those points into suggesting, but the measurement accuracy produced by filling a gallon jug while tapping my phone’s stopwatch doesn’t justify anything fancier.

    The two smallest apertures reduce the Shower pattern to a very gentle spray requiring far too long to put enough water on the plants. Mary now uses an old plastic sprinkler head with enough holes to produce a dense spray with very little force, with the flow set by fifty feet of PEX pipe running across the width of the house from the town water inlet to the hose bib.

    It was a fun exercise and I learned a little more about printing TPU and fitting acrylic parts therein:

    Hose Nozzle Flow Restrictors - prototypes
    Hose Nozzle Flow Restrictors – prototypes
  • Power Switch Mollyguards

    Power Switch Mollyguards

    It turns out that dragging a USB cable across the top of the UPS for the PC (about to be) running the Sherline mill was enough to flip its flush-mounted hairtrigger power switch. Although I can’t recess the switch, adding a mollyguard should help:

    Mollyguard - UPS power switch
    Mollyguard – UPS power switch

    The power switches on the new outlet strips also seem unduly sensitive and a preemptive strike seemed in order:

    Mollyguard - outlet strip switch
    Mollyguard – outlet strip switch

    Two layers of 3 mm acrylic just barely clear the switch, but should prevent casual trips. AFAICT, the little hexagonal shape fills the hole for an indicator LED this strip doesn’t have.

    Yellow acrylic is deliberately more conspicuous than the bike control mollyguard.

  • Keychron C3 Pro Keyboard: Taming

    Keychron C3 Pro Keyboard: Taming

    Having set the Moonlander to use Auto Shift, I’ve come to depend on it, so I got a Keychron C3 Pro keyboard for one of the Basement Shop’s PCs because it glows in the dark and can be configured with QMK:

    Keychron C3 Pro - tamed
    Keychron C3 Pro – tamed

    The default setup has rainbow hues cycling across the keyboard, which I find entirely too distracting. Although you can manually select the solid-color variant from the myriad possibilities using the keyboard, I forced a solid color with this config.h file:

    #define RGB_MATRIX_DEFAULT_ON true // Sets the default enabled state, if none has been set
    #define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_SOLID_COLOR // Sets the default mode, if none has been set
    #define RGB_MATRIX_DEFAULT_HUE 36  // Sets the default hue value, if none has been set
    #define RGB_MATRIX_DEFAULT_SAT 255 // Sets the default saturation value, if none has been set
    #define RGB_MATRIX_DEFAULT_VAL 255 // Sets the default brightness value, if none has been set
    
    

    Enabling Auto Shift requires this rules.mk file:

    AUTO_SHIFT_ENABLE = yes
    

    Both of those go in the keymap directory defining the keyboard mapping for my custom setup:

    qmk_firmware/keyboards/keychron/c3_pro/ansi/rgb/keymaps/ednisley
    

    The keymap.c file remains unchanged, although I’m mildly tempted to toss the Mac layouts overboard.

    For the record, setting QMK to compile that keyboard configuration goes like this:

    qmk setup -H /base_directory/…/qmk_firmware
    <snippage>
    qmk new-keymap -kb keychron/c3_pro/ansi/rgb -km ednisley
    qmk config user.keyboard=keychron/c3_pro/ansi/rgb user.keymap=ednisley
    qmk compile
    qmk flash
    

    Flashing the keyboard firmware goes like this:

    • Run qmk flash
    • Unplug the USB cable
    • Hold down the Esc key
    • Plug in the USB cable
    • Release the Esc key

    I should boot the Atreus configuration into the current decade, but that’s for later.

  • Earplug Case

    Earplug Case

    A no-assembly-needed earplug case from Printables will be more easily found in Mary’s purse than the previous small bag:

    Earplug case
    Earplug case

    That’s the “grippy bits” version of the model, which really is easier to open than the straight-sided version.

    I printed a few more, loaded them with earplugs, and put them where they may come in handy. In retrospect, I should have used clear PETG to show off the retina-burn plugs.

    Living in the future is great!

  • Outlet Strip Bench Mount

    Outlet Strip Bench Mount

    A spate of tidying-up led to mounting an outlet strip along the back of a bench:

    Outlet Bench Mount - installed
    Outlet Bench Mount – installed

    Rather than drill holes into the top of the bench for those screws, they fit into M4 brass inserts heat-staked into the brackets:

    Outlet Bench Mount - show view
    Outlet Bench Mount – show view

    The holes for those inserts aren’t centered side-to-side on the brackets, because the screw holes aren’t centered on the bent-steel angles forming the outlet strip endplates.

    The bottom arm on the brackets probably isn’t necessary, but they kept the outlet strip from crawling away while I match-drilled two holes for the screws into the side of the benchtop.

    For obvious reasons, the brackets print on their sides:

    Outlet Bench Mount - build view
    Outlet Bench Mount – build view

    Another outlet strip from a different manufacturer is, of course, different, but changing three parameters in the OpenSCAD program summons a different bracket from the vasty digital deep:

    Outlet Bench Mount - different brand
    Outlet Bench Mount – different brand

    Parametric modeling and a 3D printer are exactly the right hammers for the job …

    The OpenSCAD source code as a GitHub Gist:

    // Shower soap dish
    // Ed Nisley – KE4ZNU
    // 2026-06-04
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 3*3*4;
    Gap = 10.0/2;
    $fn=NumSides;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    BenchThick = 21.0; // workbench top
    ScrewOD = 4.0; // into edge of bench
    Insert = [4.0,5.5,10.0]; // robust M4 insert
    WallThick = 10.0;
    BaseThick = 10.0;
    OutletBase = [15.0,40.0];
    HoleOffset = 6.5; // from outside edge of bracket
    HoleOC = 24.0;
    MountOA = [OutletBase.x,OutletBase.y,BenchThick + Insert[LENGTH] + 1.0 + BaseThick];
    //———-
    // Build it
    module Mount() {
    difference() {
    cuboid(MountOA,rounding=1.0,anchor=BOTTOM + BACK);
    up(BaseThick)
    fwd(WallThick)
    cuboid([2*MountOA.x,MountOA.y,BenchThick],anchor=BOTTOM + BACK);
    up(BaseThick + BenchThick/2) back(Protrusion)
    ycyl(OutletBase.y,d=ScrewOD,circum=true,$fn=6,anchor=BACK);
    for (j=[-1,1])
    fwd(MountOA.y/2 + j*HoleOC/2)
    right(HoleOffset – MountOA.x/2)
    up(MountOA.z + Protrusion)
    cyl(Insert[LENGTH],d=Insert[OD],circum=true,$fn=6,anchor=TOP);
    }
    }
    //———-
    // Build it
    if (Layout == "Show") {
    left(Gap + MountOA.x/2)
    Mount();
    right(Gap + MountOA.x/2)
    xflip() Mount(); // mirror for the other end of the outlet strip
    }
    if (Layout == "Build") {
    left(MountOA.z/2)
    up(MountOA.x/2)
    yrot(90)
    Mount();
    fwd(1.5*MountOA.y)
    left(MountOA.z/2 – BenchThick/2 – Insert[LENGTH]/2)
    zrot(180)
    up(MountOA.x/2)
    yrot(-90)
    xflip() Mount(); // mirror for the other end of the outlet strip
    }
  • Prusa MK4: Mesh Bed Leveling Temperature vs. 0.8 mm Ruby Durozzle

    Prusa MK4: Mesh Bed Leveling Temperature vs. 0.8 mm Ruby Durozzle

    After going through the ritual required to install the 0.8 mm nozzle and preload the filament, the hot end looks like this before installing the silicone sock:

    Prusa MK4 hot end - 0.8 mm Durozzle ruby - front
    Prusa MK4 hot end – 0.8 mm Durozzle ruby – front

    The aluminum block doesn’t look nearly as awful as these pictures suggest; those plastic smears serve as reminders of a few previous printing mishaps.

    The nozzle is a 0.8 mm Durozzle with a ruby tip suitable for abrasive filaments like PETG-CF, although this is gooey squishy “natural” TPU:

    Prusa MK4 hot end - 0.8 mm Durozzle ruby - bottom
    Prusa MK4 hot end – 0.8 mm Durozzle ruby – bottom

    The first patio table foot test piece in TPU had terrible adhesion to the Textured Sheet, which I eventually tracked down to an excessively thick first layer. Given that the MK4 homes the axes and performs mesh bed leveling probes over the build area, this was difficult to believe, particularly because it had never been a problem with the Prusa 0.4 mm ObXidian hardened steel nozzle.

    More poking around showed some of the plastic drool left on the outside of the nozzle from the previous print session (as shown in the two pictures above) could remain hardened or at least “not squishy” despite the nozzle being heated before homing and mesh probing. Because probing depends on having the nozzle touch the platform, anything between the nozzle and the steel sheet will raise the Z=0 position and cause all the layers to be too high.

    As far as I can tell, ruby has a thermal coefficient around 40 W/m·K, roughly the same as steel. Both are considerably lower than the 200-ish W/m·K for the aluminum block surrounding the nozzle tube, suggesting most of whatever temperature gradient there may be occurs between the heater and the nozzle, not in the nozzle.

    While puzzling that out, I noticed the nozzle heated to only 160 °C prior to homing and probing, which seemed low for a filament calling for 230 to 250 °C during printing. Ordinary PETG heated to 170 °C, so something was different.

    More puzzling showed the Start G-Code section of the printer’s Custom G-Code sets the home / probe temperature, herein reformatted for readability:

    M140 S[first_layer_bed_temperature] ; set bed temp
    
    M104 T0 S{((filament_notes[0]=~/.*MBL160.*/) ? 160 : 
    (filament_notes[0]=~/.*HT_MBL10.*/) ? (first_layer_temperature[0] - 10) : 
    (filament_type[0] == "PC" or filament_type[0] == "PA") ? (first_layer_temperature[0] - 25) : 
    (filament_type[0] == "FLEX") ? 210 : 
    (filament_type[0]=~/.*PET.*/) ? 175 : 
    170)} ; set extruder temp for bed leveling
    
    M109 T0 R{((filament_notes[0]=~/.*MBL160.*/) ? 160 : 
    (filament_notes[0]=~/.*HT_MBL10.*/) ? (first_layer_temperature[0] - 10) : 
    (filament_type[0] == "PC" or filament_type[0] == "PA") ? (first_layer_temperature[0] - 25) : 
    (filament_type[0] == "FLEX") ? 210 : 
    (filament_type[0]=~/.*PET.*/) ? 175 : 
    170)} ; wait for temp
    
    

    The bursts of line noise after the M104 Set Extruder Temperature and M109 Set Extruder Temperature and Wait commands consist of nested ternary operators sifting placeholder variables defined in other parts of the slicer configuration.

    I had set up the eSun TPU 95A filament parameters based on Prusa’s TPU definition. I eventually discovered that definition includes the text MBL160 in its Notes section, which satisfies the regex in the first ternary operator:

    (filament_notes[0]=~/.*MBL160.*/) ? 160 : … snippage …
    

    Which then emitted the M104 T0 S160 and M109 R160 commands into the G-Code to set the temperature.

    After considerably more flailing around while figuring this out, I changed the filament Notes to read:

    HT_MBL10 -- force higher probe temperature for Durozzle ruby nozzle
    mbl160 -- disabled by lowercase
    

    Which then falls through to the regex in the second ternary operator:

    (filament_notes[0]=~/.*HT_MBL10.*/) ? (first_layer_temperature[0] - 10) : 
    

    Which sets the temperature to 10 °C below the first layer temperature, which I had set to 230 °C, so the probing now occurs at 220 °C.

    I am not making this up.

    Although that may be a bit too hot, the drool on the nozzle softens nicely and smashes flat during probing, thus solving the immediate problem and, without further ado, produced good round and square TPU feet.

  • Translucent vs. Transparent PETG Soap Dishes

    Translucent vs. Transparent PETG Soap Dishes

    In addition to printing bendy objects with TPU, the 0.8 mm nozzle 3D-prints PETG into thin walls with better transparency than the default 0.4 mm nozzle:

    Clear PETG - 0.4 vs 0.8 mm nozzle - side view
    Clear PETG – 0.4 vs 0.8 mm nozzle – side view

    The wall is now 1.0 mm thick, rather than 0.6 mm, and is much closer to being transparent. Those gray links from the RPi camera mount inside the dishes help show the difference.

    The 2.0 mm thick base plate is also more transparent, but mostly just reveals the 0.4 mm thick infill layers:

    Clear PETG - 0.4 vs 0.8 mm nozzle - top view
    Clear PETG – 0.4 vs 0.8 mm nozzle – top view

    More study is needed, even if we already have far more soap dishes than strictly necessary.