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

General-purpose computers doing something specific

  • OMTech 60 W Laser: Adjustable Honeycomb Stops

    OMTech 60 W Laser: Adjustable Honeycomb Stops

    When you (well, I) get fussy about angular alignment on the laser cutter’s honeycomb platform, an adjustable stop or two may come in handy:

    Laser Honeycomb - Adjustable Pins
    Laser Honeycomb – Adjustable Pins

    That’s a serving suggestion based on a true story, because I really wasn’t all that fussy about precise engraving alignment on those signs.

    A more typical situation on a smaller scale:

    Laser Honeycomb - Adjustable Pins - engraving
    Laser Honeycomb – Adjustable Pins – engraving

    The scrap of MDF with three holes provides angular alignment for the little two-color acrylic test coupon, so you can tuck successive squares into the corner, hammer them with slightly different patterns, then compare the results.

    The stops are an off-center hole (the ±3 text gives the offset) in an MDF disk with an acetal post:

    Laser Honeycomb - Adjustable Pins - detail
    Laser Honeycomb – Adjustable Pins – detail

    The 3 mm SHCS provides a convenient way to turn the post and disk, so the threading isn’t critical. Sufficiently snug threading will let you turn the screw counterclockwise without loosening it, but that surely depends on how tightly the 8 mm section fits into the honeycomb. The larger top section is 9mm, cleaned up from the rod’s nominal 3/8 inch OD, for a jam fit into the 8.8 mm + 0.1 mm kerf hole.

    The SVG images 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.

    The ±5 mm offset disk may be more useful with larger items and now you know where those three holes came from.

  • OMTech 60 W Laser: Laser Power Indicator

    OMTech 60 W Laser: Laser Power Indicator

    Although the OMTech laser controls the laser power supply with a key-lock switch, there’s little visible difference between the OFF and ON positions. Having occasionally mistaken it in both directions, this seemed like a useful addition:

    Laser Power Lock Indicator - installed
    Laser Power Lock Indicator – installed

    The strip of black duct tape below the lock muffles the rattle of the triangle hatch key against the metal cabinet.

    Two snippets of foam tape hold the knob to the lock cylinder, making an admittedly tenuous connection, but the knob fits around the outside of the switch housing with minimal clearance and doesn’t shouldn’t suffer any torque or pulling, so it might work.

    The solid model looks about like you’d expect:

    Laser Power Lock Indicator - solid model
    Laser Power Lock Indicator – solid model

    Unfortunately, it has no good orientation for printing, so I let PrusaSlicer generate support material inside the knob:

    Laser Power Lock Indicator - Support structures
    Laser Power Lock Indicator – Support structures

    Suffice it to say: removing all that plastic did not go well.

    I eventually grabbed the knob in the lathe and bored the interior out to its more-or-less proper dimensions, figuring nobody would ever notice the carnage, and it worked reasonably well. In the unlikely event I need another pointer, I’ll add a support spider to hold up the interior with minimal contact and less plastic.

    Yeah, the laser really needs a stack light showing its condition and safety status …

    The OpenSCAD source code as a GitHub Gist:

    // Indicator for OMTech laser power lock
    // Ed Nisley KE4ZNU 2022-04-09
    KnobOD = 35.0;
    KnobHeight = 22.0;
    KnobTaper = 4.0;
    PointerLength = 45.0;
    PointerThick = 3.0;
    TipOD = 2.0;
    /* [Hidden] */
    //——
    Protrusion = 0.1; // make holes end cleanly
    HoleWindage = 0.2;
    module PolyCyl(Dia,Height,ForceSides=0) { // based on nophead's polyholes
    Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);
    FixDia = Dia / cos(180/Sides);
    cylinder(d=(FixDia + HoleWindage),h=Height,$fn=Sides);
    }
    //———-
    // Create part
    // Plenty of magic numbers from actual measurements
    module Pointer() {
    difference() {
    union() {
    linear_extrude(height=PointerThick)
    hull() {
    circle(d=KnobOD,$fn=24);
    translate([PointerLength – TipOD/2,0])
    circle(d=TipOD,$fn=12);
    }
    cylinder(d=KnobOD,h=KnobHeight – KnobTaper,$fn=24);
    translate([0,0,KnobHeight – KnobTaper – Protrusion])
    cylinder(d1=KnobOD,d2=KnobOD – 3.0,h=KnobTaper + Protrusion,$fn=24);
    }
    translate([0,0,-Protrusion]) {
    PolyCyl(29.0,14.0 + Protrusion,24);
    PolyCyl(24.0,14.0 + 5.0 + Protrusion,24); // leaves clearance under pointer
    }
    translate([0,0,KnobHeight])
    cube([12.0,2.0,2*KnobHeight],center=true);
    }
    }
    //———-
    // Build it
    Pointer();

    And doodles giving the dimensions of the key lock, not all of which can be true at the same time:

    Laser Power Lock Indicator - Dimension Doodles
    Laser Power Lock Indicator – Dimension Doodles
  • OMTech 60 W Laser: COB LED Shades

    OMTech 60 W Laser: COB LED Shades

    Adding LED strips around the interior of the laser platform definitely improved the visibility of things on the honeycomb platform:

    OMTech 60W laser - COB LED strips
    OMTech 60W laser – COB LED strips

    However, all that upward-directed light goes directly into my glare-sensitive eyeballs, so I added shades above the strips:

    COB LED Shade - installed
    COB LED Shade – installed

    They’re cut from corrugated cardboard because I have an essentially infinite supply and I’m still working out speeds and intensities. Eventually they’ll become something like black acrylic.

    The brackets emerged from the vasty digital deep through the miracle of 3D printing:

    COB LED Shade Brackets - slice preview
    COB LED Shade Brackets – slice preview

    They’re stuck to the laser cabinet and the cardboard with double-sided duct tape. If you’re careful, they will line up along one edge of the tape, roll over neatly to stick their other face, then a single razor knife cut can separate each pair of neighbors.

    The underside sports an aluminized mylar strip to redirect the wasted light in a more useful direction:

    COB LED Shade - aluminized Mylar reflector
    COB LED Shade – aluminized Mylar reflector

    The tapeless sticky shipped with the laser holds the reflector in place, while its 20 mm width sets the 21 mm shade dimension. Although you want a reasonably smooth layer, it need not be mirror-flat.

    Now it’s really bright in there:

    COB LED Shade - overview
    COB LED Shade – overview

    While I had my head under the hood, I stuck a fourth strip of COB LEDs on the lip along the rear edge of the opening; it’s bright enough to cast the shadow just forward of the laser head despite the OEM under-gantry LED strip. Because the rear strip is aimed downward, it didn’t need a shade.

    The perforated cardboard sheet on the left is a spike plate: more about that later.

    The SVG drawings 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.

    The OpenSCAD source code as a GitHub Gist:

    // Bracket for COB LED shade
    // Ed Nisley KE4ZNU 2022-03-24
    BaseLength = 20.0;
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    Protrusion = 0.1; // make holes end cleanly
    WebThick = 4*ThreadWidth;
    BasePlate = [BaseLength,5*WebThick,WebThick];
    //———-
    // Create parts
    module Bracket() {
    R = BaseLength/3;
    N = 36;
    union() {
    rotate([90,0,0])
    translate([0,0,-WebThick/2])
    linear_extrude(height=WebThick,convexity=2)
    difference() {
    intersection() {
    union () {
    square(2*R,center=false);
    translate([0,2*R])
    rotate(180/N)
    circle(r=R,$fn=N);
    translate([2*R,0])
    rotate(180/N)
    circle(r=R,$fn=N);
    }
    square(3*R,center=false);
    }
    translate([2*R*cos(180/N),2*R*cos(180/N)])
    rotate(180/N)
    circle(r=R,$fn=N);
    }
    rotate([0,-90,0])
    translate([0,-BasePlate.y/2,-BasePlate.z])
    cube(BasePlate,center=false);
    translate([0,-BasePlate.y/2,0])
    cube(BasePlate,center=false);
    }
    }
    //———-
    // Build them
    Bracket();

  • B4-size Light Pad: Stabilizing the USB Connector

    B4-size Light Pad: Stabilizing the USB Connector

    What used to be a “light box” had become a “light pad” powered through a USB Micro-B connector on the side. Unfortunately, the pad’s 5 mm thickness allows for very little mechanical reinforcement around the USB jack, while providing infinite opportunity to apply bending force. Over the course of the last half-dozen years (during which the price has dropped dramatically, despite recent events), the slightest motion flickered the LEDs.

    So I squished the jack’s metal shell back into shape, found a short right-angle USB cable, and conjured a reinforcing fixture from the vasty digital deep:

    LitUp LED Light Pad
    LitUp LED Light Pad

    The plate fits under the light pad, where a strip of super-sticky duct tape holds it in place:

    LitUp Light Pad USB jack reinforcement - bottom
    LitUp Light Pad USB jack reinforcement – bottom

    The USB plug fits between the two blocks with hot-melt glue holding it in place and filling the gap between the plug and the pad.

    I’d like to say it’s more elegant than the cable redirection for my tablet, but anything involving black electrical tape and hot-melt glue just isn’t in the running for elegant:

    LitUp Light Pad USB jack reinforcement - top
    LitUp Light Pad USB jack reinforcement – top

    On the other paw, that socket ought to last pretty nearly forever, which counts for a whole lot more around here.

    The retina-burn orange tape patches on the connector eliminate all the fumbling inherent to an asymmetric connector with invisible surface features. The USB wall wart on the other end of the cable sports similar markings.

    The OpenSCAD source code as a GitHub Gist:

    // Bracket to protect USB jack on LitUp LED Pad
    // Ed Nisley KE4ZNU 2022-03-28
    Protrusion = 0.1; // make holes end cleanly
    Pad = [10.0,30.0,1.2];
    Plug = [8.0,10.5 + 0.5,8.0];
    BasePlate = [Pad.x + Plug.x,Pad.y,Pad.z];
    //———-
    // Create parts
    module Stiffener() {
    difference() {
    union() {
    translate([-Pad.x,-BasePlate.y/2,0])
    cube(BasePlate,center=false);
    translate([0,-Pad.y/2,0])
    cube([Plug.x,Pad.y,Plug.z],center=false);
    }
    translate([-Protrusion,-Plug.y/2,-Protrusion])
    cube(Plug + [2*Protrusion,0,Plug.z],center=false);
    }
    }
    //———-
    // Build them
    Stiffener();

  • Angel Food Cake Pan Liner

    Angel Food Cake Pan Liner

    Laser cut from parchment paper, no less:

    Angel Food Cake Pan liner
    Angel Food Cake Pan liner

    Radial slits around the middle let it bend upward over the folded aluminum joint around the pillar:

    Angel Food Cake Pan liner - detail
    Angel Food Cake Pan liner – detail

    Ours claims to be a 10×4-½ inch pan, roughly the diameter at the top and the overall height. Your pan will surely be different: this one is, as the saying goes, old enough to know better.

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

    Made in anticipation of the next time Mary bakes a special carrot cake with cream cheese frosting for my birthday …

  • CNC-3018XL X-Axis Recalibration

    CNC-3018XL X-Axis Recalibration

    Plotting the backlash / calibration target on both the CNC-3018XL and the MPCNC quickly showed, contrary to what I expected, the MPCNC was dead-on accurate, albeit with some wobbulation and a trace of backlash:

    MPCNC - Backlash test - detail
    MPCNC – Backlash test – detail

    Although it looks ug-u-lee, the (lower speed) drag knife cuts come out nice and, because the entry and exit moves match the main cut, the minimal backlash wasn’t a problem.

    Turns out only the X axis on the 3018XL had a problem:

    Cal Target - 400 step-mm - merged
    Cal Target – 400 step-mm – merged

    Apparently the longer leadscrew I installed as part of the “XL” conversion has a small thread pitch error: about 1 mm short in every 250 mm of travel. I don’t have any (definite, non-handwavy) method to measure the pitch directly, other than by running the follower nut and measuring the results, but it’s consistently short.

    Quite some time ago (after blowing up the OEM controller board), I set up the Protoneer CNC board in 1:8 microstep mode, making the GRBL $100 setting a nice, round 400 step/mm for a two-start leadscrew with 2 mm pitch and 4 mm lead:

    400 step/mm = (200 step/rev * 8 µstep/step) / 4 mm 

    After a few more measurements suggesting the leadscrew actually traveled 249.2 mm, the correct value will be:

    401.28 step/mm = 400 step/mm × 250 mm / 249.2 mm

    To verify I understood the problem and solution, I set $100 to a few integer values around the goal:

    Cal Target - stacked - 399-402 step-mm
    Cal Target – stacked – 399-402 step-mm

    The top image shows the leftmost line at the 10 mm mark on the scale, because it’s easier for me to match the ink line with an engraved line, rather than the non-line at the end of the ruler.

    The other images show the results for $100 set to 399, 400, 401, and 402 step/mm, respectively. The results last two results bracket the desired 250 mm outcome, with 401 step/mm being Close Enough™. GRBL accepts a floating point step/mm value, so I set $100 to 401.28, but I was unable to convince myself the result came out consistently different than 401.00.

    Plotting both the tick marks (green) and the knife path (red) on the 3018XL, then cutting the bare paper on the MPCNC, showed the two machines now agree on where the knife should fall. The outer end of the tick marks extends 1 mm beyond the cut line to ensure small misalignments do not produce an obvious white gap around the edge of the deck.

    The Y axis continues to match:

    Tek CC - 2022-02-14 - Y detail
    Tek CC – 2022-02-14 – Y detail

    And now the X axis looks just as good:

    Tek CC - 2022-02-14 - X detail
    Tek CC – 2022-02-14 – X detail

    The drag knife corners are rounded, as you’d expect. The cut seems slightly offset from a small origin touch-off error, but the scales now match.

  • GCMC XY Axis Calibration Target

    GCMC XY Axis Calibration Target

    The CNC-3018XL drawing the scales on a Tek Circuit Computer disagreed with the MPCNC cutting the perimeter. The Y axis edges looked OK:

    Tek CC - 2021-11 - Y detail
    Tek CC – 2021-11 – Y detail

    But the cut on the X axis edges went too close to the tips:

    Tek CC - 2021-11 - X detail
    Tek CC – 2021-11 – X detail

    I conjured a calibration target to help measure the two machines:

    Cal Target - CNC3018XL
    Cal Target – CNC3018XL

    The X- side of the plot gives the general idea:

    CNC-3018XL - Backlash Test - 400step-mm
    CNC-3018XL – Backlash Test – 400step-mm

    The vertical lines consist of two halves, drawn in order from left to right on the top and right to left on the bottom, meeting in the middle at the Y=0 axis. If they do, in fact, meet in the middle, then there’s no problem with backlash.

    The 25 mm distance between adjacent lines verifies the linear calibration; the total distance along the X and Y axes provides more travel for more error accumulation.

    The circles provide some reassurance the machine can draw a smooth circle, because they come from GRBL’s (or whatever) G2 G-Code commands, not a linear approximation.

    Spoiler: after a considerable amount of drawing, measuring, and muttering, the problem emerged from the CNC-3018XL’s X-axis leadscrew:

    Cal Target - 400 step-mm - merged
    Cal Target – 400 step-mm – merged

    It’s half a millimeter short on each end!

    More on this tomorrow …

    The GCMC source code as a GitHub Gist:

    (epilog begins)
    (bCNC may regard plot as done before this returns)
    M2
    (epilog ends)
    view raw epilog.gcmc hosted with ❤ by GitHub
    (prolog begins)
    G17 (XY plane)
    G21 (mm)
    G40 (no cutter comp)
    G49 (no tool length comp)
    G80 (no motion mode)
    G90 (abs distance)
    G94 (units per minute)
    (prolog ends)
    view raw prolog.gcmc hosted with ❤ by GitHub
    // Grid pattern to check XY scaling
    // Ed Nisley KE4ZNU – 2021-11
    // gcmc -P 4 –pedantic –prolog prolog.gcmc –epilog epilog.gcmc –output 'Scale Grid.ngc' 'Scale Grid.gcmc'
    include("engrave.inc.gcmc");
    FALSE = 0;
    TRUE = !FALSE;
    //—–
    // Define useful constants
    SafeZ = [-,-,10.0mm]; // above all obstructions
    TravelZ = [-,-,2.0mm]; // within engraving / milling area
    PenZ = [-,-,-1.0mm]; // depth for good inking
    PenSpeed = 2000mm;
    //—–
    // Overall values
    PlotSize = [250mm,200mm,-];
    comment("PlotSize: ",PlotSize);
    GridSize = [25mm,25mm,-];
    Margins = [5mm,5mm,-];
    CenterOD = 5.0mm;
    TextFont = FONT_HSANS_1_RS; // single stroke stick font
    TextSize = 3.0 * [1.0mm,1.0mm];
    //—–
    // Draw it
    feedrate(PenSpeed);
    comment("Draw title info");
    tp = scale(typeset("Scale & Backlash Test Pattern",TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 – GridSize.y/2,-];
    engrave(tp,TravelZ.z,PenZ.z);
    tp = scale(typeset("Grid " + GridSize,TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 – GridSize.y/2 – 1.5*TextSize.y,-];
    engrave(tp,TravelZ.z,PenZ.z);
    tp = scale(typeset("F " + PenSpeed + "/min",TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2,PlotSize.y/2 – GridSize.y/2 – 3.0*TextSize.y,-];
    engrave(tp,TravelZ.z,PenZ.z);
    tp = scale(typeset("Ed Nisley – KE4ZNU",TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2,-(PlotSize.y/2 – GridSize.y/2),-];
    engrave(tp,TravelZ.z,PenZ.z);
    tp = scale(typeset("softsolder.com",TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2,-(PlotSize.y/2 – GridSize.y/2 + 1.5*TextSize.y),-];
    engrave(tp,TravelZ.z,PenZ.z);
    comment("Mark center point");
    goto(SafeZ);
    goto([CenterOD/2,0,-]);
    move(PenZ);
    circle_cw([0,0]);
    comment("Label axes");
    tp = scale(typeset("X+",TextFont),TextSize);
    tp += [GridSize.x + 0.5*TextSize.x,-TextSize.y/2,-];
    engrave(tp,TravelZ.z,PenZ.z);
    tp = scale(typeset("Y+",TextFont),TextSize);
    tp += [-TextSize.x/2,GridSize.y + 0.5*TextSize.y,-];
    engrave(tp,TravelZ.z,PenZ.z);
    comment("Draw left-to-right");
    tp = scale(typeset("L to R →",TextFont),TextSize);
    tp += [-PlotSize.x/2 + GridSize.x/2 – tp[-1].x/2,GridSize.y/2,-];
    engrave(tp,TravelZ.z,PenZ.z);
    goto([-(PlotSize.x/2 + Margins.x),GridSize.y,-]);
    for (p=[-PlotSize.x/2,GridSize.y,-] ; p.x <= PlotSize.x/2 ; p.x += GridSize.x ) {
    comment(" p: ",p);
    goto(p);
    move(PenZ);
    move_r([-,-GridSize.y,-]);
    goto(TravelZ);
    }
    comment("Draw right-to-left");
    tp = scale(typeset("R to L ←",TextFont),TextSize);
    tp += [PlotSize.x/2 – GridSize.x/2 – tp[-1].x/2,-GridSize.y/2,-];
    engrave(tp,TravelZ.z,PenZ.z);
    goto([(PlotSize.x/2 + Margins.x),-GridSize.y,-]);
    for (p=[PlotSize.x/2,-GridSize.y,-] ; p.x >= -PlotSize.x/2 ; p.x -= GridSize.x ) {
    comment(" p: ",p);
    goto(p);
    move(PenZ);
    move_r([-,GridSize.y,-]);
    goto(TravelZ);
    }
    comment("Draw bottom-to-top");
    tp = scale(typeset("B to T ↑",TextFont),TextSize);
    tp += [-GridSize.x/2 – tp[-1].x/2,-(PlotSize.y/2 – TextSize.y),-];
    engrave(tp,TravelZ.z,PenZ.z);
    goto([-GridSize.x,-(PlotSize.y/2 + Margins.y),-]);
    for (p=[-GridSize.x,-PlotSize.y/2,-] ; p.y <= PlotSize.y/2 ; p.y += GridSize.y ) {
    comment(" p: ",p);
    goto(p);
    move(PenZ);
    move_r([GridSize.x,-,-]);
    goto(TravelZ);
    }
    comment("Draw top-to-bottom");
    tp = scale(typeset("T to B ↓",TextFont),TextSize);
    tp += [GridSize.x/2 – tp[-1].x/2,(PlotSize.y/2 – 1.5*TextSize.y),-];
    engrave(tp,TravelZ.z,PenZ.z);
    goto([GridSize.x,(PlotSize.y/2 + Margins.y),-]);
    for (p=[GridSize.x,PlotSize.y/2,-] ; p.y >= -PlotSize.y/2 ; p.y -= GridSize.y ) {
    comment(" p: ",p);
    goto(p);
    move(PenZ);
    move_r([-GridSize.x,-,-]);
    goto(TravelZ);
    }
    comment("Draw circles");
    maxr = (PlotSize.x < PlotSize.y) ? PlotSize.x/2 : PlotSize.y/2;
    for (r=GridSize.x/2 ; r <= maxr ; r += GridSize.x) {
    comment(" r: ",r);
    goto([-r,0,-]);
    move(PenZ);
    circle_cw([0,0,-]);
    goto(TravelZ);
    }
    goto(SafeZ);
    goto([0,0,-]);
    view raw Scale Grid.gcmc hosted with ❤ by GitHub