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

  • Bike Rack Tray Holder: Stretchy Tiedown Straps

    Bike Rack Tray Holder: Stretchy Tiedown Straps

    The tray holder on Mary’s bike worked well:

    Bike Rack Tray Holder - in use
    Bike Rack Tray Holder – in use

    Except for having the bungee cord run across the middle of the tray where it blocks access for larger trays and tends to bend the taller leaves.

    Well, I can fix that:

    Bike Rack Tray Holder - straps - rear
    Bike Rack Tray Holder – straps – rear

    The front tiedown is similar:

    Bike Rack Tray Holder - straps - front
    Bike Rack Tray Holder – straps – front

    They’re printed from TPU: rectangular blocks and chains, ending in wire hooks bashed from a coat hanger. The M4 button-head screws thread into (uncrushed) rivnuts, which seemed easier to manage than square nuts in this situation.

    The chains are just thick circles, with half of the top links sunk into the blocks:

    Stretchy Straps - build layout
    Stretchy Straps – build layout

    You’d (well, I’d) want to build them one at a time, because sometimes this happens:

    Bike Rack Tray Holder - bad platform adhesion
    Bike Rack Tray Holder – bad platform adhesion

    Based on those measurements, I raised the extruder by 0.1 mm, but apparently did a poor job of cleaning / flattening the cold TPU on the nozzle and got it wrong. As a result, the first layer didn’t get squooshed properly onto the BuildTak, came unstuck, and produced art . The track down the middle of the photo shows traces of a previous, badly over-squooshed test chain.

    The stretched TPU relaxes enough to leave very little tension after a day, as shown by the unhooked right chain:

    Bike Rack Tray Holder - straps - relaxing
    Bike Rack Tray Holder – straps – relaxing

    However, that make the chains exactly the right length, so they require even more force to get the hooks off the rack. After relaxing for another day, the stretched chains return to roughly their original lengths, so it’s all good.

    The OpenSCAD source code as a GitHub Gist:

    // TPU Tiedown Straps for bike rack tray holder
    // Ed Nisley – KE4ZNU
    // 2026-05-14
    include <BOSL2/std.scad>
    Layout = "Build"; // [Show,Build,Chain,Blocks,Front,Rear]
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.01;
    NumSides = 4*3*2*4;
    Gap = 5.0;
    $fn=NumSides;
    LinkID = 7.0;
    LinkOD = 10.0;
    LinkOC = 14.0;
    LinkHeight = 4.0;
    JointWidth = 2.0;
    FrontChainAngle = 30; // from vertical
    FrontChainLength = 80.0; // nominal length
    RearChainAngle = 20; // from vertical
    RearChainLength = 100.0; // nominal length
    BlockOA = [80.0,12.0,15.0];
    InsertOC = 30.0;
    //—–
    // Define things
    module Chain(n=2) {
    render()
    difference() {
    union() {
    hull() {
    cyl(LinkHeight,d=JointWidth,anchor=BOTTOM,rounding=0.0);
    back((n – 1)*LinkOC)
    cyl(LinkHeight,d=JointWidth,anchor=BOTTOM,rounding=0.0);
    }
    for (i = [0:n-1])
    back(i*LinkOC)
    cyl(LinkHeight,d=LinkOD,anchor=BOTTOM,rounding=0.0);
    }
    for (i = [0:n-1])
    back(i*LinkOC)
    down(Protrusion)
    cyl(LinkHeight + 2*Protrusion,d=(LinkID + HoleWindage),anchor=BOTTOM,rounding=-1.0);
    }
    }
    module FrontBlock() {
    difference() {
    cuboid(BlockOA,anchor=BOTTOM,chamfer=1.0,except=BACK);
    for (i = [-1:1])
    right(i*InsertOC) down(Protrusion) {
    cyl(BlockOA.z + 2*Protrusion,d=4.0 + HoleWindage,anchor=BOTTOM); // screw clearance
    cyl(1.5,d=9.0,anchor=BOTTOM); // insert head
    cyl(11.0,d=6.0,anchor=BOTTOM); // insert body
    }
    }
    }
    module RearBlock() {
    up(BlockOA.z/2) fwd(BlockOA.y/2)
    difference() {
    cuboid(BlockOA,anchor=FRONT,chamfer=1.0,except=BACK);
    for (i = [-1:1])
    right(i*InsertOC) fwd(Protrusion) {
    ycyl(BlockOA.z + 2*Protrusion,d=4.0 + HoleWindage,anchor=FRONT); // screw clearance
    ycyl(1.5,d=9.0,anchor=FRONT); // insert head
    ycyl(11.0,d=6.0,anchor=FRONT); // insert body
    }
    }
    }
    module FrontAssembly(cl=FrontChainLength,ca=FrontChainAngle) {
    Links = ceil(cl / LinkOC);
    union() {
    up(cl*cos(ca)) {
    FrontBlock();
    back(BlockOA.y/2)
    xrot(90)
    for (i = [-1,1])
    left(i*InsertOC/2)
    zrot(-i*ca + 180)
    Chain(Links);
    }
    }
    }
    module RearAssembly(cl=RearChainLength,ca=RearChainAngle) {
    Links = ceil(cl / LinkOC);
    union() {
    up(cl*cos(ca)) {
    RearBlock();
    back(BlockOA.y/2)
    xrot(90)
    for (i = [-1,1])
    left(i*InsertOC/2)
    zrot(-i*ca + 180)
    Chain(Links);
    }
    }
    }
    //—–
    // Build things
    if (Layout == "Chain")
    Chain();
    if (Layout == "Blocks") {
    fwd(BlockOA.y)
    FrontBlock();
    back(BlockOA.y)
    RearBlock();
    }
    if (Layout == "Front")
    FrontAssembly();
    if (Layout == "Rear")
    RearAssembly();
    if (Layout == "Show") {
    fwd(BlockOA.y)
    FrontAssembly();
    back(BlockOA.y)
    zrot(180)
    RearAssembly();
    }
    if (Layout == "Build") {
    fwd(BlockOA.z + Gap/2)
    up(BlockOA.y/2)
    xrot(-90)
    down(FrontChainLength*cos(FrontChainAngle))
    FrontAssembly();
    back(BlockOA.z + Gap/2)
    zrot(180)
    up(BlockOA.y/2)
    xrot(-90)
    down(RearChainLength*cos(RearChainAngle))
    RearAssembly();
    }
  • 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.

  • Prusa MK4 Camera Mount

    Prusa MK4 Camera Mount

    Combining the Articulating Raspberry Pi Camera Mount with the Standardized Links and a few more bits & pieces from Printables made this happen:

    Prusa MK4 - RPi camera installed
    Prusa MK4 – RPi camera installed

    The camera will benefit from better lighting, but it has a great view of the proceedings and gets the job done:

    RPi Camera Mount - image
    RPi Camera Mount – image

    The Standardized Link holes clear an M6 bolt, but the Thumb Remix models use M5×25 hex-head screws (the doc says M4) and they work fine. I printed the (turn-able) bolt knobs in blue PETG-CF to distinguish them from the (fixed) nut knobs, which really don’t need knurling.

    The camera ball mount has a threaded socket for the original plastic screws, but the stem isn’t quite thick enough for an M5 insert. Heat-setting an M4 brass insert into the hole and epoxying an M4×25 hex-head screw into one of the Remix knobs worked fine.

    One Snap Fit Cable Management Clip holds the ribbon cable to a link. I think the RPi can fit under the platform inside the MK4 frame, with another clip or two routing the cable below the mount and frame. Adding another layer to the foam foot pads may improve the clearance.

    The mount attaches to the MK4 frame with a 3030 adapter and a 45° link on the top. If I were in the mood, I’d make the 3030 adapter link longer for enough clearance beyond the M4 socket-head cap screws to get a ball-end hex wrench in there.

    The small figure on the platform is a Articulated Grim Reaper done in black and white as an MMU3 test.

    Now I can keep an eye on the proceedings from the Comfy Chair …

  • Prusa MK4 Headbed Insulation

    Prusa MK4 Headbed Insulation

    Over the winter, my Prusa MK4 printer occasionally coughed up a MINTEMP error when its platform heater cannot maintain the 90 °C called for by PETG. I finally added a cardboard insulating layer under the PCB heater:

    Prusa MK4 Headbed - cardboard insulation
    Prusa MK4 Headbed – cardboard insulation

    Yes, the blue tool layer rectangle marking the centers of the corner cutouts is offset 2.5 mm to the left:

    Heatbed Insulation - LightBurn layout
    Heatbed Insulation – LightBurn layout

    The layout is not symmetric, because Prusa wanted to prevent you from installing the PCB incorrectly, so I needed three tries to get it right.

    The alert reader will note the lack of the front-corner chamfers in the picture letting your fingers get under the corners to remove the steel sheet. I cut ’em off with a utility knife and you get the benefit of hindsight.

    Whether this minimal insulation will solve the problem shall remain unknown until the coldest days of next winter, but eliminating drafts around the thermistor taped to the bottom of the PCB can’t possibly be a Bad Thing™.

    The LightBurn layout exported to an SVG image as a GitHub Gist:

    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  • Work Sharp Precision Sharpener: Clamp Support

    Work Sharp Precision Sharpener: Clamp Support

    Another Work Sharp Precision Adjust sharpener improvement from Printables:

    WorkSharp - clamp support
    WorkSharp – clamp support

    Although the blade clamp is a snug fit in its socket, it has enough stick-out cantilever to move slightly even under minimal force from the diamond tools.

    I added a thin cardboard shim, cut with a utility knife (!) and stuck on with a craft adhesive sheet, as the block was about half a millimeter upward with the clamp turned this-a-way and half a millimeter downward the other way. Your mileage / setup will certainly differ.

    I like the sharpener, but it’s much fiddlier than I expected.

  • Window Mount for Bamboo Bee Tunnel Nests

    Window Mount for Bamboo Bee Tunnel Nests

    Mary suggested converting wild bamboo up the hill into tunnel nests (per a xerces.org paper) for native bees buzzing around flowers in the yard, so:

    Bee Tunnel Nest - downspout installation
    Bee Tunnel Nest – downspout installation

    I hung bundles of larger tubes in trees out back, in hopes of attracting huge carpenter bees.

    3D printed mounts hold smaller bundles on the windows to let us keep an eye on the proceedings:

    Bee Tunnel Nest Mount - installed-]
    Bee Tunnel Nest Mount – installed

    Which look better when not seen though two layers of glass in desperate need of Spring Cleaning:

    Bee Tunnel Nest Mounts
    Bee Tunnel Nest Mounts

    The tabs provide a bit of pressure to hold the mounts in place, although I don’t know if they have enough springiness or will survive contact with the elements:

    Bee Tunnel Nest Mount - tab section - solid model
    Bee Tunnel Nest Mount – tab section – solid model

    The key advantage of not building bigger bee motels: these little bundles don’t need annual cleaning / maintenance and will eventually fall apart.

    If the bees find them suitable, more power to ’em!

    And I realized the cut-off ends fit in the rotary. Witticisms engraved on bamboo could become the New Hotness:

    Laser engraved bamboo
    Laser engraved bamboo

    Stipulated: I’m barely half-right about being a wit …

    The OpenSCAD source code as a GitHub Gist:

    // Bee Tunnel Nest Mount
    // Ed Nisley – KE4ZNU
    // 2026-04-26
    include <BOSL2/std.scad>
    Layout = "Show"; // [Build,Show,Window,Bundle,Tabs]
    BundleOD = 35.0;
    BundleOffset = 0.0;
    SlotDepth = 18.0;
    SlotGap = 1.2;
    /* [Hidden] */
    HoleWindage = 0.2;
    Protrusion = 0.01;
    NumSides = 3*2*4;
    Clearance = 0.3;
    //$fn=NumSides;
    WallThick = 2.0;
    MountHeight = 1.5*BundleOD;
    MountWidth = 1.5*BundleOD + BundleOffset;
    ClipOA = [SlotDepth + WallThick,SlotGap + 2*WallThick,MountHeight];
    BundleCtr = [-WallThick/2,ClipOA.y + MountWidth/2 + BundleOffset/2,MountHeight/2];
    TabOA = [0.7*SlotDepth,5.0,0.7*WallThick];
    TabOffset = 0.2*SlotDepth;
    TabOC = MountHeight/2;
    TabClearance = [4*Clearance,0,Clearance];
    //—–
    // Define things
    module BundleMount() {
    difference() {
    cuboid([WallThick,MountWidth + ClipOA.y,MountHeight],
    rounding=3.0,edges=[TOP+BACK,BOTTOM+BACK],anchor=FRONT+RIGHT);
    back(BundleCtr.y)
    xcyl(3*WallThick,d=BundleOD);
    for (j=[-1,1],k=[-1,1])
    translate([BundleCtr.x,j*BundleOD/2 + BundleCtr.y,k*BundleOD/2])
    xcyl(3*WallThick,d=3.0,$fn=6);
    }
    }
    module WindowMount() {
    difference() {
    cuboid(ClipOA,rounding=3.0,edges=[TOP+LEFT,BOTTOM+LEFT],
    anchor=FRONT+RIGHT);
    left(WallThick) back(WallThick)
    cuboid([2*SlotDepth,SlotGap,2*MountHeight],anchor=FRONT+RIGHT);
    for (k=[-1,1])
    translate([-(ClipOA.x – TabOffset),-Protrusion,k*TabOC/2])
    cuboid([TabOA.x + TabClearance.x,WallThick + 2*Protrusion,TabOA.y + 2*TabClearance.z],anchor=FRONT+LEFT);
    }
    }
    module Tabs() {
    for (j=[-1,1])
    fwd(j*TabOC/2)
    cuboid(TabOA,anchor=BOTTOM+LEFT) position(LEFT+TOP)
    prismoid(size1=[3*SlotGap,TabOA.y],size2=[0,TabOA.y/2],
    h=(WallThick – TabOA.z) + SlotGap/3,anchor=BOTTOM+LEFT);
    }
    module Assembly() {
    union() {
    BundleMount();
    WindowMount();
    left(ClipOA.x – TabOffset – TabClearance.x)
    xrot(-90)
    Tabs();
    }
    }
    //—–
    // Build things
    if (Layout == "Bundle") {
    BundleMount();
    }
    if (Layout == "Window") {
    WindowMount();
    }
    if (Layout == "Tabs") {
    Tabs();
    }
    if (Layout == "Show") {
    Assembly();
    }
    if (Layout == "Build") {
    yrot(90)
    Assembly();
    }
  • PolyDryer Humidity: April-ish

    PolyDryer Humidity: April-ish

    After about five weeks:

    2026-04-16
    Filament%RHWeight – gWt gain – gGain %
    PETG White14
    PETG Black14
    PETG Orange2252.52.55.0%
    PETG Natural15
    PETG-CF Blue2355.45.410.8%
    PETG-CF Gray18
    PETG-CF Black14
    PETG Blue10
    TPU Clear14
    TPU Black14

    Most of the PolyDryer boxes had the same humidity as before, so I didn’t disturb them. When the humidity starts to rise, then we’ll see what’s going on in there.

    The PETG Orange meter continues to misbehave and has been glitching from 22% to 30%. The indicator card shows the humidity is around 10% inside and the relatively low weight gain suggests there’s not much water to be adsorbed.

    The PETG-CF Blue spool is new and, once again, shows filament does not arrive bone-dry in the factory wrapper.

    Those two boxes now have alumina beads.

    Dehydrating the jar of wet silica gel on the induction cooktop (set for 405 °F) sweated it down from 532 g to 503 g over the course of four hours, with nearly all of that change in the first two hours.

    Obligatory photo from a while ago, because it looks pretty much the same now:

    Silica gel beads - drying
    Silica gel beads – drying