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: Electronics Workbench

Electrical & Electronic gadgets

  • Sherline vs. LinuxCNC 2.9.8

    Sherline vs. LinuxCNC 2.9.8

    Notes on finally getting the Sherline CNC mill operating in its new home, with a suitable Axis startup image:

    Sherline setup 2026-06
    Sherline setup 2026-06

    The gray countertop from its former home sits on foam strips soaking up a slight warp with enough isolation to keep things quiet.

    The gantry required the usual fiddling to make the cable hoist the Z axis directly upward, with the orange flag on the counterweight barely visible below the monitor.

    I recently touched the box of precision XYZ positioners and there might be something useful, albeit grossly overqualified, in there to simplify dropping the laser pointer beam directly through the spindle bore.

    A clean installation of LinuxCNC 2.9.8 on an ancient Dell Optiplex 9020 proceeded smoothly. Installing x11vnc let the rest of the proceedings happen from upstairs in the Comfy Chair. For unknown reasons, vinagre works better than Reminna as a VNC client, after recalling F11 enters / exits fullscreen mode.

    The mesaflash utility accompanying LinuxCNC 2.9.8 did not recognize the Mesa 6i25 card. Fetching & compiling the most recent version (3.5.17) cleared that hump and flashed the bitmap:

    sudo mesaflash --verbose --device 5i25 --write 5i25/configs/hostmot2/5i25_prob_rfx2.bit
    

    The 6i25 wants to be known as a 5i25, with its jumpers in their default positions:

    Mesa 6i25 - jumper locations
    Mesa 6i25 – jumper locations

    For unknown reasons, the button originally known as btn-trigger became btn-joystick for a while and has now reverted to btn-trigger. It’s labeled 1 in the four-button cluster:

    Logitech Dual-Action Gamepad - relabeled
    Logitech Dual-Action Gamepad – relabeled

    Which required changing the pin name in the Kicad library component:

    Sherline HAL schematic - Logitech button 1 name
    Sherline HAL schematic – Logitech button 1 name

    Which required converting the old Kicad library format into the new Kicad library format, a completely automatic process without, AFAICT, any unpleasant side effects.

    The new name fed into the schematic as expected, after minor fumbling while re-adding the modified component and setting its annotation number:

    Sherline HAL schematic - Logitech AZ button logic
    Sherline HAL schematic – Logitech AZ button logic

    The X axis home microswitch has (apparently) become more bouncy while it was idle, so I increased the number of samples before HAL sees a change in that GPIO input:

    Sherline HAL schematic - home switch debounce
    Sherline HAL schematic – home switch debounce

    The dbounce block runs in the servo thread at 1 m per tick, so those 20 samples take all of 20 ms while the X axis moves 0.15 mm. At some point I should apply a scope to that switch, but for now It Just Works™.

    Considerably to my surprise, compiling the modified Kicad schematic into a HAL file proceeded without incident, despite various Python updates in the last five years.

    Kicad produces an “intermediate XML file” containing the netlist data intended for a conversion / export program, which is basically what my Kicad-to-HAL lashup does. I told Kicad to use Bash’s true command as a converter:

    Sherline HAL schematic - netlist export
    Sherline HAL schematic – netlist export

    So I can run the Kicad-to-HAL converter manually:

    python ../Kicad\ Conversion/Kicad-to-HAL.py Sherline\ HAL\ -\ Logitech\ Gamepad\ jogging.xml Sherline.hal
    

    You could tell Kicad to run it and it would probably Just Work™, but I’m used to peering at the results and dinking with my program.

    Which produced a new Sherline.hal file that Just Worked™ with the existing Sherline.ini file containing the configuration constants.

    The Sherline has cut only air so far, but, as the man said, “E pur si muove.”

  • 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.

  • Samsung Dishwasher Drying Fan Replacement

    Samsung Dishwasher Drying Fan Replacement

    The Samsung dishwasher (model DW80K7050US/AA 03) that Came With The House fails immediately after entering the Dry part of the cycle: a relay in the control PCB under the door goes doink, all the LEDS go off then on again, the countdown timer stops changing, and that repeats as long as you like.

    After considerable listening & pondering, I decided one event early in the Dry cycle involved starting a fan to vent the steam out of the interior. The wiring diagram shows the fan has a Fault wire: perhaps the fan has failed.

    The maintenance manual shows different fans in three different places, although the control board has a connector for only one. By process of elimination, I found the fan atop the cabinet:

    Samsung dishwasher - top view
    Samsung dishwasher – top view

    The cable from the fan in the vented compartment on the left burrows under the gray duct, around its back side, and plugs into the small white connector on the right. You must ease the cable from a row of hooks guiding it around the back of the duct, which requires slightly lifting the duct.

    Unhook the two metal straps, remove four screws from the black vent, and lift it off the top to reveal the duct outlet pores:

    Samsung dishwasher - fan duct - overview
    Samsung dishwasher – fan duct – overview

    Remove four more screws, lift the fan duct assembly just a little bit, and pry open three latches around the fan compartment with a consumer electronics case-cracking tool:

    Samsung dishwasher - fan housing
    Samsung dishwasher – fan housing

    The new fan (on the right) looks very much like the OEM fan (on the left), even though it’s the $15 version rather than the $150 version you might buy from similar randomly named sellers if you were so inclined:

    Samsung dishwasher - OEM vs new fan
    Samsung dishwasher – OEM vs new fan

    Detach the old fan & its cable, drop the new fan in place, snake its cable, plug its plug, and install All The Things in reverse order.

    Unfortunately, after shoving the dishwasher back into its cubby, the new fan didn’t change the failure at all.

    I hitched the old fan up to the bench supply and it spun just like it should. Wiring the Fault wire to a 5 V supply through a resistor shows it’s the usual tachometer signal pulsing as the rotor spins.

    Which means the next step requires more pondering and PCB probing. The failure is too consistent to be a Heisenbug, but maybe something shook loose in there.

  • 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
    }
  • Aneng AN8009 Resistance Offset

    Aneng AN8009 Resistance Offset

    Before measuring a wire resistance in the laser cutter, I checked the resistance of the two test leads on the Aneng AN8009 meter (“Check your zero!”) to show an unsteady reading around dozen ohms.

    Poking around inside showed the internal fuse apparently making poor contact with its holder, as poking it changed the random values:

    Aneng 8009 low-current fuse
    Aneng 8009 low-current fuse

    Two tiny drops of Caig DeoxIT stabilized the reading around 1 Ω across several different combinations of test probes, so I declared victory. There is surely an offset calibration buried in the firmware, but it’s no longer a trimpot available to service technicians.

    The ceramic fuse has an internal resistance of about an ohm, but swapping it for a replacement fuse with 0.2 Ω resistance didn’t materially change the results. It’s worth noting those glass fuses are slightly longer than they should be, surely due to their leads, and required slightly bending the fuseholder clips.

  • Prusa MK4 Camera Lighting

    Prusa MK4 Camera Lighting

    Although the Raspberry Pi camera has a good view of the Prusa MK4’s extruder, there’s not much light under there:

    RPi Camera Mount - image
    RPi Camera Mount – image

    There’s also not much room for a lighting fixture on the printer where it must mount, so I modified a trio of nominally 12 V / 4 W COB LED panels:

    Prusa MK4 - Extruder sidelight - COB LEDs
    Prusa MK4 – Extruder sidelight – COB LEDs

    Their “4 W” rating seems aspirational, at best, as a 12 VDC supply pushes only 75 mA through the panel, so they tick along at 900 mW. If you expect cheap eBay / Amazon components to live up to their specs, dream on.

    The modifications:

    • Unsolder the pins
    • Crunch off the surprisingly precise 27.4 Ω SMD resistor
    • Clean up the rubble
    • Wire the panels directly in series, ignoring their bridge rectifiers

    The 15 LEDs on each panel are arranged in five parallel chains of three LEDs for a total forward drop of 8.3 V, so putting three panels in series works with the MK4’s 24 V power supply.

    Stick them onto the MK4 power supply case with foam tape and wire them directly to the 24 V terminals:

    Prusa MK4 - Extruder sidelight - installed
    Prusa MK4 – Extruder sidelight – installed

    There’s very little clearance between the machine frame and the X Axis carriage on the threaded rod. Putting the LEDs in a 3D printed case and routing the wires lower on the column would be nice touches:

    Prusa MK4 - Extruder sidelight - front view
    Prusa MK4 – Extruder sidelight – front view

    The panels start at 30 mA when cold and drop to 25 mA as they warm up in the 63 °F = 17 °C Basement Shop. Each panel dissipates 250 mW: bright enough for the task, dim enough to avoid overpowering the camera’s limited dynamic range, and definitely within whatever power rating they should have.

    Looking over the camera’s shoulder in normal shop lighting suggests it’s about right:

    Prusa MK4 - Extruder sidelight - camera overview
    Prusa MK4 – Extruder sidelight – camera overview

    A staged scene with the shop lights turned off:

    Prusa MK4 - Extruder sidelight - low-light view
    Prusa MK4 – Extruder sidelight – low-light view

    Call it Good Enough™ for the purpose.

  • RPi Camera RTSP Setup

    RPi Camera RTSP Setup

    The rpicam.cfg file holding the parameters for the Raspberry Pi watching the Prusa MK 4 printer:

    bitrate=2000000 
    framerate=15
    timeout=0 
    nopreview= 
    codec=libav 
    libav-format=mpegts 
    width=1280
    height=720
    rotation=180
    roi=0.00,0.00,1.0,1.0
    hdr=auto
    

    The RPi camera for the wren nest is just taped to the window, but has a configuration providing a bigger picture:

    bitrate=2000000 
    framerate=15
    timeout=0 
    nopreview= 
    codec=libav 
    libav-format=mpegts 
    width=1920 
    height=1080 
    roi=0.00,0.00,1.0,1.0
    hdr=auto
    
    

    The useful pieces:

    • bitrate sets the average data rate, which may be too high for comfort outside your immediate LAN
    • framerate need not be as high as you think
    • nopreview prevents a preview picture while starting
    • width and height do the obvious thing, but don’t try to be too clever
    • roi picks the image from a specific part of the camera sensor, so you can adjust the image layout if you have a rigidly fixed camera
    • hdr doesn’t do anything for cheap RPi cameras

    Putting all the fiddly config in a file reduces the command line invocation to a mere jawbreaker:

    rpicam-vid --config rpicam.cfg -o - | cvlc stream:///dev/stdin --sout '#rtp{sdp=rtsp://:5886/wrens}' &
    

    Although you’d want to set that up to run automagically when the RPi starts up, for now I just fire it off as needed through an SSH session, with the ampersand letting it run after that terminal session closes.

    The RTSP port (5886) and stream (wrens) can be anything you like, which comes in handy when squirting streams through port-forwarded firewall pinholes using a router that cannot handle different external and internal port numbers.

    Useful background info: