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

  • MTD Snowthrower: Replacement Throttle Knob

    MTD Snowthrower: Replacement Throttle Knob

    The throttle knob on our MTD snowthrower (a.k.a. snowblower) cracked apart around its metal shaft when I pulled it upward. A temporary fix involving duct tape and cable ties sufficed to start the engine, although the usual intense vibration shook the knob loose somewhere along the driveway during the next hour.

    Update: Found it!

    Although I have no photographic evidence, I did make a few quick measurements:

    Throttle Knob Dimension Doodles
    Throttle Knob Dimension Doodles

    It fits an MTD model E6A4E, but I suspect nearly all their engines have identical throttle shafts:

    Snowthrower Throttle Knob - stem end - solid model
    Snowthrower Throttle Knob – stem end – solid model

    The only practical way to build the thing has it standing on the shaft end, surrounded by a brim to improve adhesion, so I added (actually, subtracted) a pair of holes for music-wire reinforcements:

    Snowthrower throttle knob - reinforcing wires
    Snowthrower throttle knob – reinforcing wires

    It definitely has a stylin’ look, next to the original choke control knob:

    Snowthrower throttle knob - installed
    Snowthrower throttle knob – installed

    I omitted the finger grip grooves for obvious reasons.

    The slot-and-hole came out slightly smaller than the metal shaft and, rather than wait for epoxy to cure, I deployed a 230 W soldering gun (not a piddly temperature-controlled iron suitable for electronics) on the shaft and melted it into the knob.

    More snow may arrive this week and I printed another knob just in case …

    The OpenSCAD source code as a GitHub Gist:

    // MTD Snowthrower Throttle Knob
    // Ed Nisley KE4ZNU 2020-12-18
    /* [Options] */
    Layout = "Show"; // [Build, Show]
    // Extrusion parameters
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    Protrusion = 0.1; // make holes end cleanly
    inch = 25.4;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    //———————-
    // Dimensions
    Throttle = [17.0,1.85,6.5]; // blade insertion, thickness, width
    PaddleSize = [25,30,9];
    PaddleRound = 4.0;
    PaddleThick = 8.5;
    StemDia = 13.0;
    StemLength = 20.0;
    PinDia = 1.6;
    PinLength = PaddleSize.x + StemLength/2;
    echo(str("Pin: ",PinLength," x ",PinDia," mm"));
    //———————-
    // Useful routines
    module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
    Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    FixDia = Dia / cos(180/Sides);
    cylinder(r=(FixDia + HoleWindage)/2,
    h=Height,
    $fn=Sides);
    }
    //———————-
    // Pieces
    module Paddle() {
    difference() {
    hull() {
    translate([PaddleSize.x/2,0,0]) {
    for (i=[-1,1], j=[-1,1])
    translate([i*(PaddleSize.x – PaddleRound)/2,j*(PaddleSize.y – PaddleRound)/2,0])
    sphere(d=PaddleRound,$fn=12);
    rotate([0,90,0]) rotate(180/12)
    cylinder(d=PaddleThick,h=PaddleSize.x,,center=true,$fn=12);
    }
    translate([-StemLength,0,0])
    rotate([0,90,0]) rotate(180/12)
    cylinder(d=StemDia,h=Throttle.x,center=false,$fn=12);
    }
    translate([-StemLength,0,0])
    cube([2*Throttle.x,Throttle.y,Throttle.z],center=true);
    translate([-(StemLength + Protrusion),0,0])
    rotate([0,90,0]) rotate(0*180/6)
    PolyCyl(2*Throttle.y,Throttle.x,6);
    for (j=[-1,1])
    translate([-StemLength/2,j*PaddleSize.y/6,0])
    rotate([0,90,0]) rotate(180/4)
    PolyCyl(PinDia,PinLength,4);
    }
    }
    //———————-
    // Build it
    if (Layout == "Show")
    Paddle();
    if (Layout == "Build") {
    translate([0,0,StemLength])
    rotate([0,-90,0])
    Paddle();
    }

  • Makergear M2: Platform Z=0 and Alignment Check

    Makergear M2: Platform Z=0 and Alignment Check

    After replacing the nozzle and filament drive on the M2, it’s definitely time to verify that the Z=0 point remains at the platform surface and the whole affair is properly aligned.

    Distribute five thinwall open squares across the platform:

    Calibration Boxes - platform alignment - 2020-12-11
    Calibration Boxes – platform alignment – 2020-12-11

    Because they’re well separated and only 3 mm tall, I set Slic3r to print them sequentially to eliminate a whole bunch of back-and-forth travel for each layer.

    Print and measure the results:

    Calibration Boxes - initial M206 Z-2.50 - 2020-12-11
    Calibration Boxes – initial M206 Z-2.50 – 2020-12-11

    The outer numbers come from the skirt around the whole platform in units of 0.01 mm: 22 → 0.22 mm. The five inner numbers are the eyeballometric average of four measurements across each square.

    They came short enough that adding 0.25 mm to their height would improve the outcome. The scribbles in the upper right corner show the initial Z offset was -2.50 mm, which means -2.75 mm should do the trick; remember to save the new value in EEPROM with M500.

    Print the same G-Code file with the new offset and measure:

    Calibration Boxes - M206 Z-2.75 - 2020-12-11
    Calibration Boxes – M206 Z-2.75 – 2020-12-11

    Can’t get much closer than that!

    The skirt gains only 0.1 mm for reasons unknown to me. It’s a good diagnostic tool for keeping an eye on the overall alignment without having to run more calibration squares, though.

    Comparing the center squares (bottom layers facing each other in the middle) from the two sets shows the difference:

    Test Squares 2.73 3.01 mm - 2020-12-11
    Test Squares 2.73 3.01 mm – 2020-12-11

    The bottom three layers got pretty well squashed with the previous offset. It’s missing about a full layer, although the nozzle wasn’t mashed flat / blocked against the platform. All the layers in the post-adjustment square look identical, as they should.

    The wall thickness on the latter squares runs from 0.40 to 0.44 mm, with an eyeballometric average around 0.43, so tweaking the Extrusion Multiplier down by maybe 5% would be in order if I were being fussy.

    Overall, not bad for a new setup!

  • Turkey Baster FAIL

    Turkey Baster FAIL

    We bought a generic Walmart-grade baster perhaps two years ago to replace a much older one with a failed rubber bulb. We use it intermittently throughout the year and had a turkey in the oven when we discovered this:

    Cracked Baster - overview
    Cracked Baster – overview

    A closer look at the business end:

    Cracked Baster - tip detail
    Cracked Baster – tip detail

    Yes, those cracks go all the way through, there’s a loose spear running the length of the thing, and it definitely doesn’t work as a baster.

    Contrary to what you might think from the general fogging and stress cracking, I haven’t used it for gasoline or brake fluid, nor do we put it away without washing it.

    The rubber bulb still works fine, though, so there’s that.

    We’ll up our spend for an OXO baster and see what happens.

  • Makergear M2: New Filament Drive and Guide Tube Adapter

    Makergear M2: New Filament Drive and Guide Tube Adapter

    After replacing the M2’s nozzle, I also installed a spare filament drive:

    Makergear M2 filament drive R3 - installed
    Makergear M2 filament drive R3 – installed

    That’s the V4 R3 version, although I bought it from Makergear rather than fight with all the support required to get a proper bearing opening.

    The long M4 screw and spring apply a constant force to the filament against the drive gear, rather than the constant position from the default (and much shorter) stock screw. The lever arm does have some springiness, but not much travel, so IMO the spring works better with the fine teeth in the drive gear.

    This drive has a 5 mm hole at the top for the stock PTFE guide tube, which I long ago replaced with ¼ inch OD HDPE tubing to reduce the friction required to get the filament off the spool and into the hot end. The rather hideous hot-melt glue blob holding a ¼ inch ID tube onto the previous drive never failed enough to bother me, but a little lathe action produced a much better adapter:

    Makergear M2 filament drive R3 - guide adapter
    Makergear M2 filament drive R3 – guide adapter

    It’s a chunk of ⅜ inch = 9.5 mm Delrin rod with a 2.4 mm hole through that 5 mm spigot for easy extraction of a gear-mashed 1.75 mm filament. The other end has a 6.5 mm hole drilled 20 mm deep to hold the guide tube.

    Looks downright dressy, it does!

  • Makergear M2: New Nozzle

    Makergear M2: New Nozzle

    A second clog in the M2’s hot end prompted me to dismantle the hot end:

    Makergear M2 V4 hot end - eroded silicone coat
    Makergear M2 V4 hot end – eroded silicone coat

    That’s what half a year of use does to a nice, shiny coat of high-temperature silicone rubber.

    This being the first time I’ve dismantled the hot end, here’s what lies inside:

    Makergear M2 V4 hot end - tapered inner guide
    Makergear M2 V4 hot end – tapered inner guide

    The tighter you make the nozzle, the closer the fit inside the hot end, and the more heat gets transferred to the plastic. The bright ring just to the right of the plastic drool shows where it fits into the brass nozzle.

    Peeling the remaining silicone off the nozzle, scraping off the black PETG around the tip, and scraping the gunk out left the inside a bit scuffed:

    Makergear 0.35 mm nozzle - interior
    Makergear 0.35 mm nozzle – interior

    The orifice still looks good and is still as close to 0.35 mm as I can measure eyeballometrically:

    Makergear 0.35 mm nozzle - exterior
    Makergear 0.35 mm nozzle – exterior

    Despite what it looks like, that’s actually a very thin PETG layer.

    Having a spare nozzle on the shelf, I decided to install it and leave the old nozzle as a backup. I’ve probably wrecked the snug seal required to keep the plastic out of the hot end.

    A fresh coat of silicone, reset the position with the platform at Z=0, and it’s back in action:

    Makergear M2 V4 hot end - Z zero set
    Makergear M2 V4 hot end – Z zero set

    The PETG remnants show I didn’t get the nozzle quite tight enough on the first attempt, but it’s all good now. The rubbery fiberglass insulator will conceal the mess.

    Protip: Always remove the hot end from the printer and clamp it securely before unscrewing the nozzle, because the very thin heat break (over on the right in the second picture) will snap under less torque than you need to break the nozzle free.

    You should unscrew the nozzle with the hot end warm enough to soften whatever plastic you’re using, lest it have glued everything inside into a solid lump.

  • Drive Wheelchair Brake Knob

    Drive Wheelchair Brake Knob

    The bent-steel brake levers on our Drive Blue Streak wheelchair present themselves edge-on to the rider:

    Drive Wheelchair Brake
    Drive Wheelchair Brake

    There are good mechanical reasons for shaping and orienting the steel like that, but the handle concentrates the considerable force required to push the brake tab into the rubberoid tire on your (well, my) palms. After a couple of weeks, I decided I didn’t need two more sore spots and conjured a palm-filling knob from the vasty digital deep:

    Wheelchair Brake Knob - installed
    Wheelchair Brake Knob – installed

    Bonus part: the little octagon near the wheel prevents the leg rest (seen in the first picture) from smashing into the end of the brake tab and chipping the lovely blue powder coat. The brown fuzzy felt foot seemed like a good idea at the time, but isn’t strictly necessary.

    A cylindrical handle on Thingiverse apparently fits on the bare steel underneath the rubberish “cushion”, but cutting a perfectly good, albeit uncomfortable, cushion off seemed like a step in the wrong direction. My knob thus descends from a doodle of the OEM dimensions:

    Drive Wheelchair Brake Handle - dimensions
    Drive Wheelchair Brake Handle – dimensions

    The knob builds in two halves adjoining the bonus octagon, which stands on edge to eliminate support inside its slot:

    Wheelchair Brake Mods - solid model - build layout
    Wheelchair Brake Mods – solid model – build layout

    You (probably) need two of all those shapes, a job your slicer is ready to perform. At three hours for each knob, I just printed the same G-Code twice.

    You can customize the knob width to fit your palm, with the other two dimensions fitting themselves around the cushion. Mary and I settled on a knob size that fits both our hands reasonably well, so it’s probably not critical.

    I tried building the knob halves without support for the first prototype, but the sloped upper surface produced awful bridging:

    Wheelchair Brake Knob - unsupported interior
    Wheelchair Brake Knob – unsupported interior

    It’s easy enough to design a customized support structure:

    Wheelchair Brake Mods - cross section
    Wheelchair Brake Mods – cross section

    I oriented the knob to put the split on the narrow sides of the brake handle in order to not have a seam facing my palm:

    Wheelchair Brake Knob - rear half installed
    Wheelchair Brake Knob – rear half installed

    The quartet of M3×20 mm socket-head cap screws thread into brass inserts epoxied into the rear half. I recessed their heads deeply into the front half and avoided thinking too hard about plugs matching the surface curvature:

    Wheelchair Brake Knob - front view
    Wheelchair Brake Knob – front view

    The low-vertex-count polygonal shape is a stylin’ thing and produces a nice feel during a firm shove, at least to my paws. Although I’d rather not need a wheelchair at all, setting the brakes now seems authoritative instead of annoying.

    The OpenSCAD source code as a GitHub gist:

    // Pride wheelchair brake lever mods
    // Ed Nisley KE4ZNU 2020-11
    /* [Layout options] */
    Layout = "Build"; // [Build, Show, Fit, TabCap, Handle, Knob, Support]
    // Hold up the knob's inside
    Support = true;
    /* [Extrusion parameters] */
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    function IntegerLessMultiple(Size,Unit) = Unit * floor(Size / Unit);
    Protrusion = 0.1; // make holes end cleanly
    inch = 25.4;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    //———————-
    // Useful routines
    module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
    Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    FixDia = Dia / cos(180/Sides);
    cylinder(r=(FixDia + HoleWindage)/2,h=Height,$fn=Sides);
    }
    //* [Basic dimensions] */
    WallThick = 4.0; // min wall thickness
    Screw = [3.0,5.5,20.0]; // thread, head, length under head
    Insert = [3.0,4.1,8.0]; // thread, knurl, length
    //———————-
    // Brake tab cap
    BrakeTab = [15,21,3.1]; // length to wheel, width, thickness
    BrakeTabSagitta = 8.0; // height of curved endcap
    CapOAL = [BrakeTab.y + 2*WallThick,BrakeTab.y + 2*WallThick,BrakeTab.z + 2*WallThick];
    module TabCap() {
    difference() {
    rotate(180/8)
    cylinder(d=CapOAL.y,h=CapOAL.z,center=true,$fn=8);
    translate([BrakeTab.x/2,0,0])
    cube(BrakeTab,center=true);
    rotate(180/8)
    cylinder(d=BrakeTab.y/cos(180/8),h=BrakeTab.z,center=true,$fn=8);
    }
    }
    //———————-
    // Brake lever handle
    // Soft covering with rounded sides that we square off for simplicity
    HandleRibs = [15,34,14]; // ignoring slight taper from end
    HandleCore = [50.0,24.0,12.0]; // straight section of lever to top of ribs
    HandleTipWidth = 30.0; // ignoring actual sector height
    module Handle() {
    union() {
    hull() {
    rotate(180/8)
    cylinder(d=HandleTipWidth/cos(180/8),h=HandleCore.z,center=true,$fn=8);
    translate([-HandleCore.x/2,0,0])
    cube(HandleCore,center=true);
    }
    translate([-(3*HandleCore.x/2 – Protrusion),0,0]) // extend base for ball trimming
    cube(HandleCore,center=true);
    translate([-HandleRibs.x/2,0,0])
    cube(HandleRibs,center=true);
    }
    }
    //———————-
    // Support structure for handle cavity inside knob
    // Totally ad-hoc tweakage
    // Remember it's lying on its side to match the handle
    NumRibs = 2 + 1; // must be odd
    RibSpace = floor(HandleCore.z/(NumRibs + 1));
    module KnobSupport() {
    color("Yellow") { // support overlaps in the middle
    render(convexity=3)
    intersection() {
    for (k=[-1,1])
    translate([0,k*ThreadThick,0]) // shrink inward to break adhesion
    Handle();
    translate([(HandleCore.x – HandleRibs.x)/2 – HandleCore.x – Protrusion,0,0])
    cube([HandleCore.x – HandleRibs.x,HandleRibs.y,HandleCore.z],center=true);
    union()
    for (k=[-floor(NumRibs/2):floor(NumRibs/2)])
    translate([0,0,k* RibSpace])
    cube([2*HandleCore.x,HandleRibs.y,2*ThreadWidth],center=true);
    }
    translate([(HandleCore.x – HandleRibs.x)/2 – HandleCore.x,0,0])
    cube([HandleCore.x – HandleRibs.x,4*ThreadWidth,NumRibs*RibSpace],center=true);
    }
    }
    //———————-
    // Brake handle knob
    // Largely built with magic numbers
    // Includes support because it's not really optional
    KnobOD = 55.0;
    KnobOffset = HandleRibs.x/1;
    KnobSides = 2*4*3;
    module Knob() {
    difference() {
    hull() {
    resize([0,HandleRibs.y + 4*WallThick,HandleCore.x + HandleTipWidth/2 + WallThick])
    sphere(d=KnobOD,$fn=KnobSides);
    }
    translate([0,0,KnobOffset])
    rotate([0,-90,0])
    Handle();
    for (i=[-1,1],k=[-1,1])
    translate([i*KnobOD/4,0,k*KnobOD/4]) {
    rotate([90,0,0])
    PolyCyl(Insert[OD],1.5*Insert[LENGTH],6);
    translate([0,-Screw[LENGTH]/2,0])
    rotate([-90,0,0])
    PolyCyl(Screw[ID],KnobOD,6);
    translate([0,Screw[LENGTH] – Insert[LENGTH],0])
    rotate([-90,0,0])
    PolyCyl(Screw[OD],KnobOD,6);
    }
    }
    if (Support)
    translate([0,0,KnobOffset])
    rotate([0,-90,0])
    KnobSupport();
    }
    //———————-
    // Lash it together
    if (Layout == "TabCap") {
    TabCap();
    }
    if (Layout == "Handle") {
    Handle();
    }
    if (Layout == "Support") {
    KnobSupport();
    }
    if (Layout == "Knob") {
    Knob();
    }
    if (Layout == "Show") {
    translate([60,0,0])
    TabCap();
    Knob();
    }
    if (Layout == "Fit") {
    translate([60,0,0])
    difference() {
    TabCap();
    translate([0,0,CapOAL.z/2])
    cube(CapOAL,center=true);
    }
    difference() {
    Knob();
    translate([KnobOD + KnobOD/4,0*KnobOD,0])
    cube(2*KnobOD,center=true);
    translate([-KnobOD,-KnobOD,0])
    cube(2*KnobOD,center=true);
    }
    }
    if (Layout == "Build") {
    translate([KnobOD/2,0,(CapOAL.y*cos(180/8))/2])
    rotate([0,-90,90])
    TabCap();
    for (j=[-1,1])
    translate([0,-j*0.75*HandleCore.x,0])
    difference() {
    rotate([j*90,0,0])
    Knob();
    translate([0,0,-KnobOD])
    cube(2*KnobOD,center=true);
    }
    }

    A doodle with dimensions of other parts:

    Drive Wheelchair - brake footrest tab dimensions
    Drive Wheelchair – brake footrest tab dimensions

    The angled tab on the middle left is for the leg rest release latch, but I decided not to silk-purse-ize the thing.

  • Hiatus

    Posts will appear intermittently over the next week or two.

    I’m still spending an inordinate amount of time studying the back of my eyelids while horizontally polarized in the lift chair. I can highly recommend not doing whatever it is that triggers a pinched lumbar nerve, but as nearly as I can tell, the proximate cause (shredding leaves) isn’t anything close to whatever the root cause might be.

    It does provide plenty of time to conjure solid models from the vasty digital deep:

    Wheelchair Brake Mods - solid model - build layout
    Wheelchair Brake Mods – solid model – build layout

    The wheelchair brake lever seems to have been designed by somebody who never actually had to shove it very often:

    Drive Wheelchair Brake
    Drive Wheelchair Brake

    At least I can fix that