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

  • OMTech Laser Cutter vs. Ortur YRC-1 Rotary: Job Checklist

    OMTech Laser Cutter vs. Ortur YRC-1 Rotary: Job Checklist

    The process of switching the laser cutter from “normal” operation to the Ortur YRC-1 rotary and back again requires a checklist:

    Ortur YRC-1 Setup Checklist - installed
    Ortur YRC-1 Setup Checklist – installed

    Which looks like this:

    Ortur YRC-1 Setup Checklist
    Ortur YRC-1 Setup Checklist

    The same thing as a PDF will be more printable or readable.

    Previous posts cover what goes into making it work:

    Notes:

    • Always disable the rotary’s stepper driver before connecting or disconnecting its cable.
    • The Ortur YRC-1 rotary has a pulley ratio of 1:3, so the step/rev value is three times the DIP switch setting on the stepper driver. For this setup, 1600 → 4800 step/rev.
    • The honeycomb frame is a parallelogram, not a rectangle. I align the cardboard baffle / fixture to the bottom edge of the frame and the rotary to the bottom edge of the fixture opening, but your machine will be different. The angular alignment may not be off by enough to matter, but consistency is a virtue.
    • The Rotary.lbset and Linear.lbset files live on a file server with daily backups. Such backups will come in handy when you inadvertently overwrite one of those files with the other one. Trust me on this.
    • The Rotary.lbset file does not have Rotary Mode enabled, because the KT332N does not home the Y axis in that mode. If your rotary lacks a home switch, then it doesn’t matter and you’re on your own.
    • The KT332N controller has a [Reset] button that allegedly does a power-on reset and reloads all the changed Machine Settings. This sometimes does not work as expected: power-cycling the controller is the only way to be sure.
    • The autofocus operation must hit the focus pad, which can be ensured by positioning the pen near the pad, jogging the platform a few millimeters under the pen, tweaking X and the gantry while peering down parallel to the pen, then doing the autofocus.
    • The focus pad has a crosshair clearing the chonky Ortur 3-step jaws, but I set the controller’s [Origin] at the foot of the pad’s base for more elbow room.
    • The Z axis distance field in LightBurn’s Move window does not accept formulas, so you must divide the workpiece diameter by two. Using a focus stick to verify the ensuing nozzle-to-workpiece distance is a Good Idea™.
    • The LightBurn Job Origin dot must be on the top row, because the KT332N does not go into regions with negative coordinates. With the chuck on the left and the [Origin] just to its right, the upper left dot locks the LightBurn selection to the physical limits.
    • Selecting [Use Selection Origin] puts the Job Origin at the upper left (per the dot) of whatever you’ve selected, not everything on the LightBurn workspace. [User Origin] then locks the selection to the [Origin] set on the controller.

    As the saying goes, it works for me …

  • Translucent Night Light Light Guide

    Translucent Night Light Light Guide

    Our house came with several single-LED night lights featuring a transparent light guide / reflector:

    Nightlight light guide - original
    Nightlight light guide – original

    The plate had snapped off one of them and, being me, I wondered if I could replace it with something similar.

    Years passed.

    Obviously, this must be made from a transparent substance, which 3D printed things are not, but after some fiddling with parameters I thought the result might be informative.

    The guide plate is a section of a spherical surface, here approximated by a BOSL2 spheroid():

    Nightlight light guide - view side - solid model
    Nightlight light guide – view side – solid model

    The original is 3 mm thick, but 2 mm worked out better for my purposes by reducing the amount of infill:

    Nightlight light guide - wall side - solid model
    Nightlight light guide – wall side – solid model

    The intricate base latches into the lamp’s plastic case:

    Nightlight light guide - base - solid model
    Nightlight light guide – base – solid model

    The result is, at best, translucent, because it’s definitely not transparent:

    Nightlight light guide - translucent vs transparent
    Nightlight light guide – translucent vs transparent

    The zigzag pattern seems to come from the icosohedral approximation to the sphere, because it follows the surface tesselation.

    Getting the base shape right required several iterations, each printed with the model cut off just above the bottom of the guide plate:

    Nightlight light guide - test pieces
    Nightlight light guide – test pieces

    The first two attempts needed attention from a flush cutting pliers before fitting into the case, but they don’t call it rapid prototyping for nothin’.

    The original and replacement plugged into an outlet strip:

    Nightlight light guide - original vs printed on outlet strip
    Nightlight light guide – original vs printed on outlet strip

    While you can see the vague outline of the strip behind the printed light guide, it’s definitely lacking in detail:

    Nightlight light guide - outlet strip detail
    Nightlight light guide – outlet strip detail

    The striations throw more light into the room than the original:

    Nightlight light guide - printed
    Nightlight light guide – printed

    Fiddling with the 3D printing parameters might make it more transparent, but it’s going back into the box it came from after giving me a better idea of which parameters to tweak the next time around.

    The OpenSCAD source code as a GitHub Gist:

    // Nightlight light guide
    // Ed Nisley – KE4ZNU
    // 2026-01-13
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Plate,Base,Pipe]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 10*3*4;
    $fn=NumSides;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    function ChordRadius(m,c) = (m^2 + (c^2)/4) / (2*m);
    PlateThick = 2.0;
    PlateOA = [60.0,50.0,PlateThick];
    PlateRound = 5.0;
    PlateTaper = 1.0;
    PlateAngle = atan(-2/60); // original plate angle, far end closer to wall
    PlateM = 2.4;
    PlateRadius = ChordRadius(PlateM,PlateOA.x); // light guide plate
    echo(PlateRadius=PlateRadius);
    WallThick = 2.0;
    MountOA = [23.4,17.0,5.5];
    MountRadius = ChordRadius(4.3,MountOA.x); // base arc in housing
    echo(MountRadius=MountRadius);
    PipeThick = 5.0;
    //———-
    // Define shapes
    // Oddly intricate base fitting into housing
    // Replete with magic numbers
    module Base() {
    difference() {
    union() {
    intersection() {
    cuboid([MountOA.x,MountOA.y,5.5],anchor=BOTTOM);
    back(6.5)
    tube(MountOA.z,or=MountRadius,wall=1.5,anchor=BOTTOM+BACK);
    }
    for (i=[-1,1])
    right(i*18.5/2)
    back(11.5)
    cuboid([1.8,8.0,MountOA.z],anchor=BOTTOM+BACK);
    for (i=[-1,1])
    right(i*22.0/2)
    cuboid([1.4,2.0,MountOA.z],anchor=BOTTOM+FRONT);
    fwd(5.0)
    cuboid([11.0,10.5,MountOA.z],anchor=BOTTOM+FRONT);
    }
    down(Protrusion)
    for (j=[-1,1])
    fwd(j*(1.5 + 10.0)/2)
    cuboid([7.0,10.0,MountOA.z + 2*Protrusion],anchor=BOTTOM);
    up(3.1)
    back(7.5)
    cuboid([MountOA.x,25.0,MountOA.z],anchor=BOTTOM+FRONT);
    }
    }
    // Light guide plate
    module Plate() {
    xrot(PlateAngle)
    zrot(90) yrot(90)
    left(PlateOA.x/2)
    down(PlateM + PlateThick/2)
    intersection() {
    up(PlateRadius)
    difference() {
    spheroid(PlateRadius,style="icosa");
    spheroid(PlateRadius – PlateThick,style="icosa");
    }
    cuboid(PlateOA + [0,0,2*PlateThick],rounding=PlateRound,edges="Z",anchor=BOTTOM);
    }
    }
    // Light pipe between base & plate
    // Magic numbers to fit case opening
    module Pipe() {
    difference() {
    intersection() {
    fwd(3.0/2 – 0.2)
    cuboid([MountOA.x,MountOA.y,PipeThick],rounding=0.5,edges="Z",anchor=BOTTOM+FRONT);
    back(6.5)
    cyl(MountOA.z,r=MountRadius,anchor=BOTTOM+BACK);
    }
    down(Protrusion)
    back((1.5 + 10.0)/2)
    cuboid([7.0,10.0,1.0 + Protrusion],anchor=BOTTOM);
    }
    }
    module Assembly() {
    Base();
    up(MountOA.z)
    Pipe();
    up(MountOA.z + PipeThick)
    Plate();
    }
    //———-
    // Build things
    if (Layout == "Base")
    Base();
    if (Layout == "Plate")
    Plate();
    if (Layout == "Pipe")
    Pipe();
    if (Layout == "Show" || Layout == "Build")
    Assembly();
  • Translucent Soap Dishes

    Translucent Soap Dishes

    A SquidWrench meeting discussion about printing transparent objects prompted me to conjure a soap dish from the vasty digital deep:

    Shower Soap Dish - solid model
    Shower Soap Dish – solid model

    They’re all done in “natural” PETG with sufficient variations in speed, temperature, extrusion multiplier, and fill pattern to stock the shower & tub:

    Translucent soap dishes
    Translucent soap dishes

    The single-thread sidewalls came out reasonably translucent in all the variations, but the baseplate remained stubbornly white-ish, even at 20 mm/s and 250 °C with 100% infill. The seams where the extruder retracts and lifts to the next layer remain conspicuous, with a scarf joint forming the white slab in the left-rear dish.

    Quite a while ago, I’d considered making soap dishes with shattered-glass bottoms, but came to my senses. These have some key advantages:

    • Exactly the right size for narrow shower shelves
    • Light enough to not damage anything when it inevitably falls off
    • Reasonably unbreakable when that happens
    • Easily replaced

    They’re also test pieces for the whole transparency thing, so it’s all good.

    The OpenSCAD source code as a GitHub Gist:

    // Shower soap dish
    // Ed Nisley – KE4ZNU
    // 2026-01-13
    include <BOSL2/std.scad>
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 3*3*4;
    $fn=NumSides;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    WallThick = 0.6;
    BaseThick = 2.0;
    //DishOA = [80.0,40.0,20.0]; // standing used Dove
    DishOA = [90.0,50.0,30.0]; // standing Dove
    //DishOA = [100.0,65.0,30.0]; // half-bar
    DishTaper = [10.0,10.0];
    CornerRadius = 15.0;
    DrainOA = [10.0,DishOA.y,3.0];
    DrainOC = DishOA.x/3;
    //———-
    // Build it
    difference() {
    union() {
    linear_extrude(BaseThick)
    rect([DishOA.x,DishOA.y] – DishTaper,rounding=CornerRadius);
    rect_tube(DishOA.z,wall=WallThick,
    size1=[DishOA.x,DishOA.y] – DishTaper,size2=[DishOA.x,DishOA.y],
    rounding=CornerRadius,anchor=BOTTOM);
    }
    for (j=[-1,1])
    right(j*DrainOC/2)
    up(BaseThick)
    cuboid(DrainOA,rounding=1.0,anchor=BOTTOM+BACK);
    }
  • Delta 17 Series Temperature Knob Removal

    Delta 17 Series Temperature Knob Removal

    As a reminder for the next time in this rodeo, the latches holding the temperature adjustment knob on the Delta 17 Series dual-handle bath / shower faucet look like this:

    Delta bath faucet cap latches
    Delta bath faucet cap latches

    I am unable to apply enough force to the smooth edge of the knob opposite the handle to un-latch it, so I jammed a small prydriver into the gap and twisted enough to pop the latch, at the obvious risk of scarring the chrome plating.

    A better approach would involve a plastic prydriver intended for consumer electronics case cracking.

    For the record:

    • Unlike the other bath faucets, this one has shutoff valves inside the wall
    • The replacement cartridge is RP46463
    • A dab of silicone grease on the rotating valve surface in the back improves its performance

    Ideally, I won’t need any of that information again.

  • Inline Switch FAIL

    Inline Switch FAIL

    One of the inline switches I installed to replace the failed switches for the LED lights got unpleasantly warm enough to prompt an investigation:

    Inline lamp switch - heat damage
    Inline lamp switch – heat damage

    Yeah, that is not a nominal outcome, particularly in light of the claimed “10 A 250 V” rating.

    The overheated plastic pulled back enough to expose the terminal inside:

    Inline lamp switch - visible terminal
    Inline lamp switch – visible terminal

    There was a reason I’d wrapped those switches with known-good 3M electrical tape before deploying them.

    That crimp connector took some heat and its screw looks even more unhappy:

    Inline lamp switch - internal damage
    Inline lamp switch – internal damage

    It turned out the screw was an itsy too short to compress both the connector and the bent-metal conductor tab against the terminal block:

    Inline lamp switch - misfit screw terminal
    Inline lamp switch – misfit screw terminal

    A 6 mm brass screw with a brass washer did a better job of compressing all parties into one conductive lump.

    Although the switch now runs with the case at normal basement temperature, an allegedly UL listed replacement is on its way; it costs about five times more than that switch. If it behaves as it should, I’ll preemptively replace two other switches.

  • Ortur YRC-1: Petite Chuck Jaws

    Ortur YRC-1: Petite Chuck Jaws

    The standard jaws for the Ortur Rotary loom over small-diameter workpieces:

    Ortur Rotary Focus Pad - home offset adjustment
    Ortur Rotary Focus Pad – home offset adjustment

    Some measuring and modeling produced petite 3D printed jaws:

    Ortur Rotary - printed jaws
    Ortur Rotary – printed jaws

    Admittedly, those jaws aren’t doing much of anything, but they’re not nearly as much in the way. You (well, I) can screw them in closer to the center to overlap the chuck jaws or another hole outward for slightly larger cylinders.

    The solid model looks about the same:

    Ortur Rotary Jaws - 2-3 show view
    Ortur Rotary Jaws – 2-3 show view

    They build face-down with a little support under the screw recesses for a clean fit on the chuck:

    Ortur Rotary Jaws - Prusaslicer
    Ortur Rotary Jaws – Prusaslicer

    Teeny jaws might be handy:

    Ortur Rotary Jaws - 2-2 show view
    Ortur Rotary Jaws – 2-2 show view

    Screwing them in one hole outward lets them grip medium cylinders without sticking out from the chuck jaws:

    Ortur Rotary - small printed jaws
    Ortur Rotary – small printed jaws

    The OpenSCAD code lets you pick which screw holes you want, but it does not error-check the perverse choices.

    The OpenSCAD source code as a GitHub Gist:

    // Ortur Rotary Focus Pad
    // Ed Nisley – KE4ZNU
    // 2026-01-04
    include <BOSL2/std.scad>
    Style = "Show"; // [Build,Show,Chuck,ChuckJaw,Jaw]
    InnerScrew = 1; // [0:3]
    OuterScrew = 3; // [2:4]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    Gap = 5.0;
    NumSides = 8*3*4;
    $fn=NumSides;
    WallThick = 2.0;
    ScrewHead = [4.0 + HoleWindage,7.0 + HoleWindage,4.0];
    ChuckOD = 66.0;
    ChuckThick = 10.0;
    ChuckBCR = [3.5,7.5,15.0,22.5,30.0]; // M4 tapped in chuck jaws
    ChuckJawOA = [ChuckOD/2,8.0 + HoleWindage,3.5];
    JawBlock = [0,15.0,2*WallThick + ScrewHead[LENGTH]]; // .x will be variable
    JawRound = 1.0; // tip rounding
    //—–
    // Single chuck jaw with holes
    module ChuckJaw(Holes=true) {
    difference() {
    intersection() {
    cuboid(ChuckJawOA,anchor=BOTTOM+LEFT);
    cyl(ChuckJawOA.z,d=ChuckOD,anchor=BOTTOM);
    linear_extrude(h=ChuckJawOA.z)
    hexagon(od=ChuckOD,rounding=2.0,anchor=LEFT);
    }
    if (Holes)
    for (i = [0:len(ChuckBCR)-1])
    right(ChuckBCR[i])
    down(Protrusion)
    cyl(2*ChuckJawOA.z,d=ScrewHead[ID],anchor=BOTTOM);
    }
    }
    // Chuck layout
    module Chuck(Holes=true) {
    cyl(ChuckThick,d=ChuckOD,anchor=TOP) position(TOP)
    for (a = [0:120:360])
    zrot(a)
    ChuckJaw(Holes);
    }
    // Gripping jaw
    module Jaw(Screws=[1,3]) {
    HoleOC = ChuckBCR[Screws[1]] – ChuckBCR[Screws[0]];
    JawOAL = HoleOC + ScrewHead[OD] + 2*WallThick + (JawBlock.y/2)/cos(30);
    difference() {
    left(JawOAL/2)
    intersection() {
    cuboid(JawBlock + [JawOAL,0,0],anchor=BOTTOM+LEFT);
    linear_extrude(h=JawBlock.z)
    hexagon(od=ChuckOD,rounding=JawRound,anchor=LEFT);
    right(JawOAL)
    linear_extrude(h=JawBlock.z)
    hexagon(od=ChuckOD,rounding=JawRound,anchor=RIGHT);
    }
    right(0*JawOAL/2)
    for (i=[-1,1])
    right(i*HoleOC/2) {
    down(Protrusion)
    cyl(JawBlock.z,d=ScrewHead[ID],anchor=BOTTOM);
    up(2*WallThick)
    cyl(JawBlock.z,d=ScrewHead[OD],anchor=BOTTOM);
    }
    down(Protrusion)
    cuboid([JawOAL,ChuckJawOA.y,WallThick + Protrusion],anchor=BOTTOM);
    }
    }
    //—–
    // Build things
    if (Style == "Chuck") {
    Chuck();
    }
    if (Style == "Show") {
    xrot(180)
    yrot(90) {
    color("Gray",0.8)
    Chuck();
    up(ChuckJawOA.z – WallThick)
    for (a = [0:120:360])
    zrot(a)
    right((ChuckBCR[InnerScrew] + ChuckBCR[OuterScrew])/2)
    Jaw(Screws=[InnerScrew,OuterScrew]);
    }
    }
    if (Style == "ChuckJaw")
    ChuckJaw();
    if (Style == "Jaw") {
    Jaw(Screws=[InnerScrew,OuterScrew]);
    }
    if (Style == "Build")
    for (j=[-1:1])
    fwd(j*(JawBlock.y + Gap))
    up(JawBlock.z) xrot(180)
    Jaw(Screws=[InnerScrew,OuterScrew]);
  • Ortur YRC-1: Autofocus Pad

    Ortur YRC-1: Autofocus Pad

    Ruida laser controllers do not allow the platform to rise above the U=0 origin set by the autofocus pen = switch. While this isn’t a problem for flat surfaces, focusing on the exact top of a horizontal cylinder, particularly a small rod, may be overly difficult.

    So a focusing pad seems like a Good Idea™:

    Ortur Rotary Focus Pad - focus pen positioning
    Ortur Rotary Focus Pad – focus pen positioning

    The general idea:

    • Align a flat horizontal surface with the rotary chuck’s axis
    • Do the autofocus operation with a well-defined landing zone under the pen
    • The Focus Distance puts the laser head at the proper height for a focused spot on the pad
    • Jogging the head upward (= platform downward) by the workpiece radius puts the focused spot exactly at the right height
    • Remove the focus pad
    • Install the workpiece
    • Fire The Laser

    The solid model:

    Ortur Rotary Focus Pad - solid model
    Ortur Rotary Focus Pad – solid model

    Features of note:

    • The chuck jaws fit into the recesses on the left end for a firm grip with good alignment
    • The lengthwise notch lies on the rotary axis parallel to the laser’s X axis
    • The crosswise notch is juuust rightward of the chuck jaws, marking the leftmost end of whatever you’re engraving

    Because I added a home switch to the Ortur YRC-1 case, Jaw 1 automagically ends up on top after homing, thus automagically making the focus pad horizontal. Getting that right required fine-tuning the rotary’s home switch trip point, which turned out to be easier to do using the Home Offset configuration value after I replaced the cam I thought would work:

    Ortur Chuck Rotary home switch - pulley cam
    Ortur Chuck Rotary home switch – pulley cam

    Instead, a simple M4 setscrew (standing proud of the pulley surface in one of the tapped holes for the real setscrew securing the pulley to the shaft) trips the switch much more repeatably :

    Ortur Rotary Focus Pad - home trip setscrew
    Ortur Rotary Focus Pad – home trip setscrew

    The setscrew on the right sits flush with the surface to prevent the switch roller from falling into the hole. The real setscrew underneath it locks the pulley to the shaft’s flat.

    With that in place, a quick binary search settled on a Y axis Home Offset = 1.75 mm to put the pad level with the top of the rotary’s case, which is Level Enough™ due to my tweaking the machine’s foot elevations after jacking the whole machine up on risers:

    Ortur Rotary Focus Pad - home offset adjustment
    Ortur Rotary Focus Pad – home offset adjustment

    The Home Offset value:

    The speed and acceleration values are much lower than used with the linear Y axis, because apparently Ruida computes the corresponding step values using the workpiece diameter in the Rotary section. Small diameters produce impossibly fast motions, which suggests they expect you to set the optimum values based on back-calculations from the object diameter; ain’t nobody got time for that.

    Anyhow.

    After autofocusing, the red-dot pointer now indicates the laser spot position, so jog the X axis and drag the gantry to put the spot on the axis mark:

    Ortur Rotary Focus Pad - gantry positioning
    Ortur Rotary Focus Pad – gantry positioning

    The orange rim on the red-dot pointer cuts down the beam intensity to make a smaller dot and provides easier position tweaks.

    Then jog the X axis to put the dot at the transverse mark just beyond the chuck jaws:

    Ortur Rotary Focus Pad - red dot at origin
    Ortur Rotary Focus Pad – red dot at origin

    Hit the Ruida Origin button to set that as the user origin, so you can reference the LightBurn design to the hardware position.

    Move the platform down by the workpiece radius, jog the nozzle along the X axis to get it out of the way, remove the focus pad, install the workpiece, and you’re good to go. The checklist visible beyond the bubble level shows it’s not quite that simple, but we’re getting there.

    The OpenSCAD source code as a GitHub Gist:

    // Ortur Rotary Focus Pad
    // Ed Nisley – KE4ZNU
    // 2026-01-04
    include <BOSL2/std.scad>
    Style = "Show"; // [Build,Show]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 8*3*4;
    $fn=NumSides;
    // Magic numbers to fit Ortur jaws
    PadOAL = 60.0; // clear assist air fitting
    PadIR = 7.0; // jaw tip 35 mm above this point
    JawOAL = 14.0; // clear large jaws
    Reticle = [0.7,0.7,PadOAL];
    OriginOffset = 28.0; // X origin from chuck plate
    //—–
    // Pad to give autofocus probe a flat landing zone
    module FocusPad() {
    difference() {
    linear_extrude(PadOAL)
    hexagon(ir=PadIR,realign=true,rounding=3.0);
    up(JawOAL) {
    cube(PadOAL,anchor=BOTTOM+LEFT);
    cube(Reticle,spin=45,anchor=BOTTOM);
    }
    up(OriginOffset)
    cube(Reticle,spin=45,orient=FRONT,anchor=CENTER);
    for (a=[0:120:360])
    rotate(a)
    down(Protrusion)
    linear_extrude(JawOAL + 2*Protrusion)
    right(PadIR + 15 – 2) // eyeball fit
    hexagon(or=15,rounding=0.5);
    }
    }
    //—–
    // Build things
    if (Style == "Show")
    yrot(90)
    zrot(180)
    FocusPad();
    if (Style == "Build")
    FocusPad();