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: MK4

Prusa Mk 4 3D printer with MMU3 feeder

  • 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();
  • Silica Gel Beads: Regeneration Damage

    Silica Gel Beads: Regeneration Damage

    The silica gel beads I’ve been using in the PolyDryer boxes start out a uniform yellow / light brown:

    Polydryer Box desiccant tray - top view
    Polydryer Box desiccant tray – top view

    The humidity indicating chemical seems to be methyl violet, described as changing from yellow to green when saturated, which has never happened here. For example, these beads, retrieved from random corners of the workbench, have been sitting in 40-ish %RH basement air for weeks:

    Silica gel beads - 36pctRH ambient
    Silica gel beads – 36pctRH ambient

    The fragment just left of center looks greenish, but the rest are, at best, various shades of brown. This may be due to the (relatively) low humidity in the basement, but putting them under a damp sponge for a few hours didn’t change their color.

    The most recent regeneration session started with an open cast-iron pan on an induction cooktop:

    Silica gel beads - drying
    Silica gel beads – drying

    The variety of browns comes from various amounts of adsorbed water in the PolyDryer boxes, but AFAICT there really isn’t much correlation between the humidity level and the amount of adsorbed water.

    The drying process went like this:

    • 650 g at start
    • 50% power for 2 hr → 200 °F
    • Covered the pan & turned it off overnight
    • 623 g at start
    • 50% power for 2 hr → 220 °F
    • 612 g
    • 50% power for 1 hr → 236 °F
    • 610 g
    • 30% power for 30 min → 205 °F
    • 35% power for 30 min → 200 °F
    • 609 g

    So about four hours at 50% power would get all but the laser few grams of water out of the silica gel.

    After all that, the beads looked about the same in a white bowl for cooling:

    Silica gel beads - damaged indicator dye
    Silica gel beads – damaged indicator dye

    Each regeneration cycle leaves more dark brown beads in the mix, which may be due to poor temperature control, and they do not return to their original yellow / pale brown shade.

    Apparently cooking silica gel beads over 120 °C = 250 °F (various sources give various temperatures) can damage their structure or the methyl violet indicator; for sure some of those beads have been abused.

    Unsurprisingly, the bead temperature rises as they dry out. Although the induction cooktop has a temperature control, we’ve found the setting doesn’t match the pan temperature and the overall control is poor. I could set the gas oven to 200 °F, but I’m certain it doesn’t control the temperature all that closely, either.

    The original jug held 2 pounds = 907 g of beads. Add the 609 g from this session to the 350 g of allegedly dry beads in seven of the PolyDryer boxes: my regeneration hand is weak.

  • PolyDryer Humidity: December

    PolyDryer Humidity: December

    The measurements:

    2025-12-29
    Filament%RHWeight – gWt gain – gGain %
    PETG White1853.83.87.6%
    PETG Black1853.83.87.6%
    PETG Orange2252.32.34.6%
    PETG Natural2253.43.46.8%
    PETG-CF Blue1854.14.18.2%
    PETG-CF Gray2354.14.18.2%
    PETG-CF Black1853.83.87.6%
    PETG Blue1052.92.95.8%
    TPU Clear1854.44.48.8%
    TPU Black1855.15.110.2%

    I used to think there was some correlation between the indicated humidity and the amount of water adsorbed by the silica gel, with the humidity rising as the gel absorbed more water. That is obviously not the case.

    AFAICT, I’d been reading the chart wrong:

    Desiccant adsorption vs humidity
    Desiccant adsorption vs humidity

    Instead of the adsorption being a function of the equilibrium humidity, it’s the other way around. With the humidity held constant (by adding water vapor), the silica gel will adsorb thus-and-so percentage of its weight and equilibrate at that humidity. If the filament was an infinite reservoir of dampness, then the equilibrium humidity would indicate how much the silica gel had coped with.

    At least I think that’s how it goes. I have been wrong before.

    Anyhow, IMO the right way to proceed is to just replace the silica gel every month and be done with it.

    Also true: the humidity meters aren’t particularly accurate at the low humidity values in those boxes.

  • Ortur YRC-1: Conical Tailstock Centers

    Ortur YRC-1: Conical Tailstock Centers

    A conical (a.k.a. bullnose) center in the tailstock simplifies supporting cylindrical objects:

    Ortur Chuck Rotary conical center - installed
    Ortur Chuck Rotary conical center – installed

    The spring-loaded tailstock bearing has a 5 mm bore. The bullnose rests against a small spacer on its 5 mm shaft to hold it away from the bearing’s mounting screws with some bearing spring compression. I turned the spacer from aluminum rod because lathe work is satisfying, but a printed spacer would work fine.

    The bullnose is a cone with steps encouraging the cylinder to sit properly:

    Ortur Rotary Conical Center - 10-50mm
    Ortur Rotary Conical Center – 10-50mm

    With both ends centered, the cylinder sits concentric with the chuck axis:

    Ortur Chuck Rotary home switch - jaw position
    Ortur Chuck Rotary home switch – jaw position

    The chuck grabs the OD and the bullnose supports the ID, so removing crud from both ends is in order.

    The bullnose won’t work for a solid rod, so a negative cone = cup center may come in handy:

    Ortur Chuck Rotary cup center - installed
    Ortur Chuck Rotary cup center – installed

    Stipulated: A CO₂ laser will bounce right off a solid aluminum rod. Imagine I chucked up a wood dowel, OK?

    A cup center is what remains afteryoinking a bullnose out of a cylinder:

    Ortur Rotary Conical Centers - cup
    Ortur Rotary Conical Centers – cup

    Looks like I did exactly that:

    Ortur Chuck Rotary conical centers
    Ortur Chuck Rotary conical centers

    Somewhat surprisingly, the two parts nest perfectly:

    Ortur Chuck Rotary conical centers - nested
    Ortur Chuck Rotary conical centers – nested

    That’s without the shaft installed on the cup, so they won’t sit quite so neatly on the shelf.

    Aligning the rotary axis along the laser’s X axis and setting the focus requires attention to detail, but a decent tailstock center makes that effort meaningful.

    The OpenSCAD code as a GitHub Gist:

    // Ortur Rotary Conical centers
    // Ed Nisley – KE4ZNU
    // 2025-12-27
    include <BOSL2/std.scad>
    Style = "Bullnose"; // [Build,Cone,Bullnose,Cup,Cone]
    MinDia = 10.0;
    MaxDia = 50.0;
    /* [Hidden] */
    LayerThick = 0.2; // should match slicer thickness
    Ramp = 1.0;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 8*3*4;
    $fn=NumSides;
    Gap = 5.0;
    WallThick = 2.0;
    TailBearing = [5.0,7.0,10.0]; // tailstock shaft, LENGTH = insert depth
    StepHeight = 2*LayerThick;
    NumSteps = (((MaxDia – MinDia)/2) / Ramp);
    ConeOAH = NumSteps * (Ramp + StepHeight);
    //—–
    // Bullnose shape
    module Bullnose() {
    difference() {
    union()
    for (i = [0:NumSteps – 1])
    up(i*(Ramp + StepHeight)) hull()
    cyl(StepHeight + Protrusion,r=(MaxDia/2 – i*Ramp),anchor=BOTTOM) position(TOP)
    cyl(Ramp,r1=(MaxDia/2 – i*Ramp),r2=(MaxDia/2 – (i+1)*Ramp),anchor=BOTTOM);
    }
    }
    module Cone() {
    difference() {
    Bullnose();
    down(Protrusion)
    cyl(TailBearing[LENGTH] + Protrusion,d=TailBearing[ID],circum=true,anchor=BOTTOM);
    }
    }
    module Cup() {
    difference() {
    cyl(ConeOAH + TailBearing[LENGTH],d=MaxDia + 2*WallThick,anchor=BOTTOM);
    up(ConeOAH + TailBearing[LENGTH] + Protrusion)
    yrot(180)
    Bullnose();
    down(Protrusion)
    cyl(TailBearing[LENGTH] + 2*Protrusion,d=TailBearing[ID],circum=true,anchor=BOTTOM);
    }
    }
    //—–
    // Build things
    if (Style == "Bullnose")
    Bullnose();
    if (Style == "Cone")
    Cone();
    if (Style == "Cup")
    Cup();
    if (Style == "Build") {
    right(MaxDia/2 + Gap)
    Cone();
    left(MaxDia/2 + WallThick + Gap)
    Cup();
    }
  • Ortur YRC-1: Adding a Home Switch

    Ortur YRC-1: Adding a Home Switch

    Stipulated: A chuck rotary doesn’t need a home switch.

    With that in mind, a home switch seemed like it might come in handy and this is the simplest workable design:

    Ortur Chuck Rotary home switch - installed
    Ortur Chuck Rotary home switch – installed

    The cover mimics the size & shape of the Ortur cover, minus the stylin’ rounding & chamfering along the edges:

    Ortur Rotary Belt Cover - exterior - solid model
    Ortur Rotary Belt Cover – exterior – solid model

    It has a certain Cybertruck aspect, doesn’t it?

    Two beads of hot melt glue hold the switch flush along the cover’s inside surface:

    Ortur Chuck Rotary home switch - case exterior
    Ortur Chuck Rotary home switch – case exterior

    One might argue for a tidy cover over those terminals.

    While contemplating the layout by holding the switch here & there, seeing the switch roller neatly centered on the pulley hub told me the Lords of Cosmic Jest favored this plan:

    Ortur Chuck Rotary home switch - case interior
    Ortur Chuck Rotary home switch – case interior

    A simple cam lifts the roller:

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

    That’s obviously laser-cut acrylic sitting on double-sided tape. Some finicky repositioning put the #1 chuck jaw on top after homing:

    Ortur Chuck Rotary home switch - jaw position
    Ortur Chuck Rotary home switch – jaw position

    A more permanent adhesive under the cam may be in order.

    Update: The switch triggers more reliably with a simple setscrew standing proud of the pulley hub:

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

    Wiring the normally open switch contacts in parallel with the existing Y axis home switch lets both the gantry and the rotary trigger the controller. The front-panel switch ensures only one of those two can move:

    Laser Rotary - control switch
    Laser Rotary – control switch

    With all that in place and the switch flipped, the chuck rotates happily and homes properly with the controller in normal linear mode.

    Spoiler: A Ruida-ish KT332N controller ignores the Y-axis Home enable setting with Rotary mode enabled, because everybody knows a rotary has no need for a home switch.

    The OpenSCAD code as a GitHub Gist:

    // Ortur Rotary belt cover
    // Ed Nisley – KE4ZNU
    // 2025-12-23
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Block,Shell]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 2*3*4;
    $fn=NumSides;
    Gap = 5.0;
    WallThick = 1.6; // OEM wall
    CoverOA = [81.5,50.5,23.0]; // open side down
    CoverRadius = 4.0;
    CoverTrimZ = 6.0;
    CoverTrimAngle = 45;
    BreakX = (CoverOA.z – CoverTrimZ)/tan(CoverTrimAngle);
    ScrewOC = [51.0,38.0];
    ScrewHoleID = 3.5;
    ScrewHeadRecess = [ScrewHoleID,7.0,1.8];
    ScrewOffset = 8.0; // cover edge to hole centerline
    SwitchOA = [21.0,20.0,6.5]; // X = body + roller, excludes terminals
    SwitchOffset = [0,0,17.0]; // nominal end = roller at centerline
    //—–
    // Overall cover shape
    module CoverBlock() {
    cuboid([CoverOA.x,CoverOA.y,CoverTrimZ],anchor=BOTTOM) position(TOP+LEFT)
    prismoid(size1=[CoverOA.x,CoverOA.y],size2=[CoverOA.x – BreakX,CoverOA.y],
    height=CoverOA.z – CoverTrimZ,shift=[-BreakX/2,0],anchor=BOTTOM+LEFT);
    }
    // Cover shell
    module CoverShell() {
    difference() {
    CoverBlock();
    down(Protrusion)
    resize(CoverOA – [2*WallThick,2*WallThick,WallThick – Protrusion])
    CoverBlock();
    }
    }
    // The complete cover
    module Cover() {
    difference() {
    union() {
    CoverShell();
    left((CoverOA.x – ScrewOC.x)/2 – ScrewOffset)
    for (i = [-1,1], j=[-1,1])
    translate([i*ScrewOC.x/2,j*ScrewOC.y/2,0])
    cyl(CoverOA.z,d=ScrewHoleID + 2*WallThick,anchor=BOTTOM);
    }
    left((CoverOA.x – ScrewOC.x)/2 – ScrewOffset) down(Protrusion)
    for (i = [-1,1], j=[-1,1])
    translate([i*ScrewOC.x/2,j*ScrewOC.y/2,0]) {
    cyl(CoverOA.z + 2*Protrusion,d=ScrewHoleID + HoleWindage,anchor=BOTTOM);
    up(CoverOA.z – ScrewHeadRecess[LENGTH])
    cyl(ScrewHeadRecess[LENGTH] + 2*Protrusion,
    d1=ScrewHeadRecess[ID] + HoleWindage,d2=ScrewHeadRecess[OD] + HoleWindage,
    anchor=BOTTOM);
    }
    translate(SwitchOffset) left(CoverOA.x/2 – WallThick – Protrusion)
    cuboid(SwitchOA,anchor=RIGHT+FWD);
    }
    }
    //—–
    // Build things
    if (Layout == "Block") {
    CoverBlock();
    }
    if (Layout == "Shell") {
    CoverShell();
    }
    if (Layout == "Show") {
    Cover();
    }
    if (Layout == "Build") {
    up(CoverOA.z)
    xrot(180)
    Cover();
    }
  • Garden Step2 Seat: Hinge Replacement

    Garden Step2 Seat: Hinge Replacement

    As fate would have it, the Step2 rolling garden seat took an untimely fall while standing in the garage and broke both its hinges:

    Garden Step2 Seat - broken hinge
    Garden Step2 Seat – broken hinge

    It’s been out in the garden for maybe six years, so those chunks of plastic are fully depreciated.

    Two hours after loading the solid model into PrusaSlicer:

    Garden Step2 Seat - new hinges installed
    Garden Step2 Seat – new hinges installed

    The SiLite tray is well-weathered, but remains structurally sound: still ready for service in the D-Hall breakfast line on the morning after the Apocalypse.

    Living in the future works out pretty well.

  • Laser Cutter: New 24 V Power Supply

    Laser Cutter: New 24 V Power Supply

    Unlike the OEM 24 V supply in the laser, the “new” supply from my heap does not have mounting flanges; it’s intended to be attached to a mounting plate from the back side. It turns out the laser does have a mounting plate with All The Things screwed onto it, but there is no way I am going to disconnect all the wiring just to drill four more holes in that plate.

    So I made a pair of brackets to screw into the back of the supply and then into suitable holes in the mounting plate:

    Laser 24V Power Supply Mount - solid model
    Laser 24V Power Supply Mount – solid model

    Which look like this in real life:

    Laser 24V Power Suppy - mounts installed
    Laser 24V Power Suppy – mounts installed

    Those M4 rivnuts just beg for 6 mm holes in the mounting plate.

    However, it turns out that their unsquished length exceeds the distance behind the panel, which means there’s no way to install them flush to the panel with the proper backside squish.

    So:

    • Loosen the four nuts holding the panel to the bolts welded to the machine frame
    • Ease it forward a bit
    • Tuck 6 mm acrylic scraps behind all four corners
    • Snug the nuts again to hold the plate against the acrylic with plenty of room behind it

    The OpenSCAD code generates a simpleminded drill template:

    Laser 24V Power Suppy - drill template
    Laser 24V Power Suppy – drill template

    Press a scrap of rubber firmly against the plate to dampen vibrations and thwack each hole with an automatic center punch set to stun. Deploy a succession of drills up through 6 mm, catching most of the swarf in tape strips:

    Laser 24V Power Suppy - drill chip catchers
    Laser 24V Power Suppy – drill chip catchers

    Squish the rivnuts in place:

    Laser 24V Power Suppy - rivnuts in place
    Laser 24V Power Suppy – rivnuts in place

    The small, vaguely tapped hole on the lower right was the “good” screw for the OEM power supply; the “bad” screw hole is invisible to the upper left, just under the raceway.

    Remove the plastic spacers, snug the nuts holding the plate again, install the power supply, and it looks like it grew there:

    Laser 24V Power Suppy - installed
    Laser 24V Power Suppy – installed

    The wires and Wago connectors scrunched underneath aren’t anything to be proud of, but longer wires didn’t seem likely to improve the outcome.

    The OpenSCAD source code as a GitHub Gist:

    // Mount for 24 V laser power supply
    // Ed Nisley – KE4ZNU
    // 2025-12-07
    include <BOSL2/std.scad>
    Layout = "Show"; // [Show,Build,Guide,Block]
    /* [Hidden] */
    ID = 0;
    OD = 1;
    LENGTH = 2;
    HoleWindage = 0.2;
    Protrusion = 0.1;
    NumSides = 2*3*4;
    $fn=NumSides;
    Gap = 5.0;
    Rivnut = [4.0,6.0,9.0]; // body + head OD
    RivnutHead = [6.0,10.0,1.0]; // flat head
    WallThick = 6.0; // a bit more than half rivnut head OD
    SupplyCase = [50.0,215.0,112.0]; // power supply case size
    SupplyOC = [25.0,150.0,0]; // power supply mounting screw centers
    SupplyOffset = -1.0; // the screws are not centered on the case!
    SupplyScrew = [4.0,9.0,4.0]; // … LENGTH outside supply case
    MountOC = SupplyCase.x + 2*WallThick;
    MountScrewLength = 8.0; // … head-to-baseplate
    MountRadius = 0.5;
    BlockOA = [MountOC + 2*WallThick, 2*WallThick, MountScrewLength];
    GuideOD = 2.0;
    //—–
    // Single mounting block
    module MountBlock() {
    difference() {
    cuboid(BlockOA,chamfer=MountRadius,except=BOTTOM,anchor=BOTTOM);
    for (i = [-1,1]) {
    right(i*MountOC/2) {
    cyl(2*RivnutHead[LENGTH],d=RivnutHead[OD],circum=true,anchor=CENTER);
    cyl(2*BlockOA.z,d=Rivnut[ID] + HoleWindage,circum=true,anchor=BOTTOM);
    }
    right(i*SupplyOC.x/2 + SupplyOffset) {
    down(SupplyScrew[LENGTH])
    cyl(BlockOA.z,d=SupplyScrew[OD] + HoleWindage,circum=true,anchor=BOTTOM);
    cyl(2*BlockOA.z,d=SupplyScrew[ID] + HoleWindage,circum=true,anchor=BOTTOM);
    }
    }
    }
    }
    //—–
    // Guide holes in a 2D layout
    module DrillGuide() {
    difference() {
    square([BlockOA.x,SupplyOC.y + BlockOA.y],center=true);
    for (j=[-1,1])
    fwd(j*SupplyOC.y/2)
    for (i = [-1,1]) {
    right(i*MountOC/2) {
    circle(d=GuideOD);
    }
    }
    }
    }
    //—–
    // Build things
    if (Layout == "Block")
    MountBlock();
    if (Layout == "Guide")
    DrillGuide();
    if (Layout == "Show") {
    for (j=[-1,1])
    fwd(j*SupplyOC.y/2)
    MountBlock();
    color("Gray",0.5)
    up(BlockOA.z)
    cuboid(SupplyCase,anchor=BOTTOM);
    }
    if (Layout == "Build") {
    for (j=[-1,1])
    fwd(j*(BlockOA.y/2 + Gap/2))
    up(BlockOA.z) zflip()
    MountBlock();
    }