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

Making the world a better place, one piece at a time

  • CNC 3018-Pro: CAMTool V3.3 USB Power Diode

    The CAMTool V3.3 board dispenses with fancy USB power switching circuitry:

    CAMTOOL CNC-V3.3 schematic - USB Power Entry
    CAMTOOL CNC-V3.3 schematic – USB Power Entry

    The NUP2201 is an ESD clamp diode / suppressor IC, which is a nice touch, but FU1, a simple 300 mA polyfuse, is the only thing standing between the USB cable and the on-board +5 V regulator. In real life, it looks like this:

    CAMTool V3.3 - USB power fuse
    CAMTool V3.3 – USB power fuse

    It’s the little black rectangle between the USB jack and the CH340 USB-to-serial chip. The

    The far end of the USB cable plugs into a Raspberry Pi, a device known for unseemly fussiness about USB power, so I unsoldered the fuse and installed a diode:

    CAMTool V3.3 - USB power diode
    CAMTool V3.3 – USB power diode

    It’s a BAT54 Schottky diode, pointed toward the right to prevent current from the board getting to the Pi. Pin 2 (toward the bottom) isn’t connected to anything inside the package, either, so it’s all good.

    I suppose if one were a stickler for detail, one could gimmick the diode in series with the fuse, but I figured that’s a solution for a problem well down on the probability list …

  • DRV8825 Stepper Driver: Fast vs. Mixed Decay Current Waveforms

    Herewith, a look at CNC 3018-Pro stepper motor current waveforms as a function of supply voltage, PWM decay mode, and motor speed.

    The scope displays X and Y axis motor current at 1 A/div, with sensing through a pair of Tektronix Hall effect current probes:

    CNC 3018-Pro - XY axes - Tek current probes
    CNC 3018-Pro – XY axes – Tek current probes

    The X axis driver is an unmodified DRV8825 PCB operating in default mixed-decay mode. The Y axis DRV8825 has its DECAY pin pulled high, thereby putting it in fast decay mode.

    The scope timebase varies to match the programmed feed rate. Because the X and Y axes move simultaneously, each axis moves at 1/√2 the programmed speed:

    G1 X10 Y10 F100 → 71 mm/min on X and Y

    The motor generates minimal back EMF at slow speeds, so the winding sees nearly the full supply voltage. As described in the previous post, the basic problem arises when the current rises too fast during each PWM cycle:

    V = L di/dt
    di/dt = 24 V / 3 mH = 8 kA/s

    The first 1:32 microstep away from 0 calls for 5% of max current = 50 mA at a 1 A peak. The DRV8825 datasheet says the PWM typically runs at 30 kHz = 33 µs/cycle, during which the current will change by 270 mA:

    267 mA = 8 kA/s × 33.3 µs

    Notice how the current slams to a nearly constant, much-too-high value just after the first microstep. The incorrect current level decreases with lower supply voltage, because the rate-of-change decreases and the commanded current level reaches the actual (incorrect) current sooner.

    Varying the motor voltage at a constant 10 mm/min:

    3018 XY - Mixed Fast - 24V - 10mm-min 1A-div
    3018 XY – Mixed Fast – 24V – 10mm-min 1A-div
    3018 XY - Mixed Fast - 20V - 10mm-min 1A-div
    3018 XY – Mixed Fast – 20V – 10mm-min 1A-div
    3018 XY - Mixed Fast - 15V - 10mm-min 1A-div
    3018 XY – Mixed Fast – 15V – 10mm-min 1A-div
    3018 XY - Mixed Fast - 12V - 10mm-min 1A-div
    3018 XY – Mixed Fast – 12V – 10mm-min 1A-div
    3018 XY - Mixed Fast - 10V - 10mm-min 1A-div
    3018 XY – Mixed Fast – 10V – 10mm-min 1A-div

    Note that reducing the supply voltage doesn’t change the motor winding current, because the DRV8825 controls the current during each microstep, at least to the best of its ability.

    Also note that the current overshoots the target for those microsteps, even when the motor is stopped, because there’s no back EMF, so the power dissipation is too high even at rest.

    Enough back EMF appears at 100 mm/min to begin tamping down the current overshoot at 24 V:

    3018 XY - Mixed Fast - 24V - 100mm-min 1A-div
    3018 XY – Mixed Fast – 24V – 100mm-min 1A-div

    The current waveform looks good at 12 V:

    3018 XY - Mixed Fast - 12V - 100mm-min 1A-div
    3018 XY – Mixed Fast – 12V – 100mm-min 1A-div

    The back EMF at 1000 mm/min nearly eliminates the overshoot at 24 V, with fast decay in the Y axis causing some PWM ripple:

    3018 XY - Mixed Fast - 24V - 1000mm-min 1A-div
    3018 XY – Mixed Fast – 24V – 1000mm-min 1A-div

    Both decay modes look good at 12 V:

    3018 XY - Mixed Fast - 12V - 1000mm-min 1A-div
    3018 XY – Mixed Fast – 12V – 1000mm-min 1A-div

    At 1500 mm/min, the highest reasonable speed for the thing, and a 24 V supply, both waveforms still look good:

    3018 XY - Mixed Fast - 24V - 1500mm-min 1A-div
    3018 XY – Mixed Fast – 24V – 1500mm-min 1A-div

    However, the back EMF is now high enough to buck the 12 V supply, preventing the current from decreasing fast enough in mixed decay mode (top trace):

    3018 XY - Mixed Fast - 12V - 1500mm-min 1A-div
    3018 XY – Mixed Fast – 12V – 1500mm-min 1A-div

    Tweaking the GRBL config to allow 2000 mm/min feeds shows the waveforms starting to become triangular, even at 24 V:

    3018 XY - Mixed Fast - 24V - 2000mm-min 1A-div
    3018 XY – Mixed Fast – 24V – 2000mm-min 1A-div

    And a 12 V supply opposed by the back EMF simply can’t change the current fast enough to keep up with the DRV8825 microstep current levels:

    3018 XY - Mixed Fast - 12V - 2000mm-min 1A-div
    3018 XY – Mixed Fast – 12V – 2000mm-min 1A-div

    Bottom line: a +12 V motor supply and DRV8825 drivers modified to run in fast decay mode look like the best setup for the 3018-Pro: good current control at low speeds with enough moxie to handle higher speeds.

    I should hack the DRV8825 boards into 1:8 microstep mode to reduce the IRQ rate by a factor of four, then see what happens to the back EMF at absurd speeds.

  • Tour Easy: Ruggedized Zzipper Fairing Mount

    After nigh onto 18 years, the pipe straps holding the Zzipper fairing struts to the handlebars of our Tour Easy recumbents finally shrugged off their plastic wraps:

    Tour Easy Zzipper Fairing - OEM mount
    Tour Easy Zzipper Fairing – OEM mount

    Although they still worked, riding over broken pavement produced distinct rattles; alas, the roads around here feature plenty of broken pavement.

    The solution is a rugged plastic block capped with aluminum plates to spread the clamping load:

    Tour Easy Zzipper Fairing - block mount
    Tour Easy Zzipper Fairing – block mount

    The solid model is straightforward:

    Zzipper Fairing - Strut Mount - solid model - Show view
    Zzipper Fairing – Strut Mount – solid model – Show view

    A slight bit of tinkering made the stack exactly the right height for 45 mm screws secured with nyloc nuts. No washers on either end, although that’s definitely in the nature of fine tuning.

    The three sections print without support:

    Zzipper Fairing - Strut Mount - solid model
    Zzipper Fairing – Strut Mount – solid model

    I reamed the smaller hole with a 3/8 inch drill to match the fairing strut rod. The as-printed larger hole fit the handlebar perfectly, although the first picture shows the tubing isn’t exactly round on the near side of the block, where it starts the outward bend toward the grips.

    The cap plates cried out for CNC, but I simply traced two outlines of the block on 1/8 inch aluminum sheet, bandsawed near the line, introduced them to Mr Disk Sander for finishing & corner rounding, transfer-punched the holes from the plastic blocks, and drilled to suit:

    Tour Easy Zzipper Fairing - clamp plates
    Tour Easy Zzipper Fairing – clamp plates

    Making two pairs of plates by hand counts as Quality Shop Time around here.

    The first few rides confirm the fix: no rattles!

    The OpenSCAD source code as a GitHub Gist:

    // Fairing strut mount for Tour Easy handlebars
    // Ed Nisley – KE4ZNU – 2019-08
    Layout = "Show"; // [Show,Build,Block]
    Support = false;
    /* [Hidden] */
    ThreadThick = 0.20;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    Protrusion = 0.1; // make holes end cleanly
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    ID = 0;
    OD = 1;
    LENGTH = 2;
    inch = 25.4;
    //———————-
    // Dimensions
    // Handlebar along X axis, strut along Y, Z=0 at handlebar centerline
    HandlebarOD = 0.875 * inch + HoleWindage;
    StrutOD = 0.375 * inch + HoleWindage;
    PlateThick = 1.0 / 16.0 * inch;
    WallThick = 2.0;
    Screw = [3.0,6.8,4.0]; // M3 OD=washer, length=nut + washers
    RoundRadius = IntegerMultiple(Screw[OD]/2,0.5); // corner rounding
    ScrewOC = [IntegerMultiple(StrutOD + 2*WallThick + Screw[ID],0.5),
    IntegerMultiple(HandlebarOD + 2*WallThick + Screw[ID],0.5)];
    echo(str("Screw OC: ",ScrewOC));
    BlockSize = [ScrewOC.x + 2*RoundRadius,ScrewOC.y + 2*RoundRadius,HandlebarOD + StrutOD + 3*WallThick];
    echo(str("Block: ",BlockSize));
    HandleBarOffset = WallThick + HandlebarOD/2; // block bottom to centerline
    StrutOffset = HandlebarOD/2 + WallThick + StrutOD/2; // handlebar centerline to strut centerline
    echo(str("Screw length: ",BlockSize.z + 2*PlateThick + Screw[LENGTH]));
    NumSides = 2*3*4;
    //———————-
    // 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 shapes
    // Block with handlebar along X axis
    module Block() {
    difference() {
    hull()
    for (i=[-1,1], j=[-1,1])
    translate([i*ScrewOC.x/2,j*ScrewOC.y/2,-HandleBarOffset])
    cylinder(r=RoundRadius,h=BlockSize.z,$fn=NumSides);
    for (i=[-1,1], j=[-1,1])
    translate([i*ScrewOC.x/2,j*ScrewOC.y/2,-(HandleBarOffset + Protrusion)])
    PolyCyl(Screw[ID],BlockSize.z + 2*Protrusion,8);
    translate([-BlockSize.x,0,0])
    rotate([0,90,0])
    cylinder(d=HandlebarOD,h=2*BlockSize.x,$fn=NumSides);
    translate([0,BlockSize.y,StrutOffset])
    rotate([90,0,0])
    cylinder(d=StrutOD,h=2*BlockSize.y,$fn=NumSides);
    }
    if (Support) { // totally ad-hoc
    color("Yellow")
    cube(1,center=true);
    }
    }
    //- Build it
    if (Layout == "Block")
    Block();
    if (Layout == "Show") {
    Block();
    color("Green",0.25)
    translate([-BlockSize.x,0,0])
    rotate([0,90,0])
    cylinder(d=HandlebarOD,h=2*BlockSize.x,$fn=NumSides);
    color("Green",0.25)
    translate([0,BlockSize.y,StrutOffset])
    rotate([90,0,0])
    cylinder(d=StrutOD,h=2*BlockSize.y,$fn=NumSides);
    }
    if (Layout == "Build") {
    translate([-1.2*BlockSize.x,0,HandleBarOffset])
    difference() {
    Block();
    translate([0,0,BlockSize.z])
    cube(2*BlockSize,center=true);
    }
    translate([1.2*BlockSize.x,0,StrutOD/2 + WallThick])
    difference() {
    rotate([180,0,0])
    translate([0,0,-StrutOffset])
    Block();
    translate([0,0,BlockSize.z])
    cube(2*BlockSize,center=true);
    }
    translate([0,0,StrutOffset])
    rotate([180,0,0])
    intersection() {
    Block();
    translate([0,0,StrutOffset/2])
    cube([2*BlockSize.x,2*BlockSize.y,StrutOffset],center=true);
    }
    }
  • DRV8825 Stepper Driver: Forcing Fast Decay Mode in a (Likely) Counterfeit Chip

    The DRV8825 stepper driver chip defaults to mixed decay mode, which TI defines thusly:

    Mixed decay mode begins as fast decay, but at a fixed period of time (75% of the PWM cycle) switches to slow decay mode for the remainder of the fixed PWM period. This occurs only if the current through the winding is decreasing (per the indexer step table); if the current is increasing, then slow decay is used.

    The 24 V supply on the CNC 3018-Pro provides too much voltage for the motors, because slow decay mode can’t handle those rising slopes:

    3018 XY - Mixed Fast - 24V - 10mm-min 12V 1A-div
    3018 XY – Mixed Fast – 24V – 10mm-min 12V 1A-div

    Note that “rising” means the current increases with either polarity from 0 A at the midline. The DRV8825 uses a MOSFET H-bridge to drive winding current in either direction from the +24 V motor supply voltage.

    Both traces show motor winding current at 1 A/div, with the XY axes creeping along at 10 mm/min (thus, 7.1 mm/min each). The upper trace is the X axis, with a stock DRV8825 module in mixed decay mode. The lower trace is the Y axis, with its DRV8825 hacked into fast decay mode.

    The basic problem, about which more later, comes from the current rising too fast during each PWM cycle:

    V = L di/dt
    di/dt = 24 V / 3 mH = 8 kA/s

    The first 1:32 microstep away from 0 calls for 5% of max current = 50 mA at a 1 A peak. The DRV8825 datasheet says the PWM typically runs at 30 kHz = 33 µs/cycle, during which the current will change by 270 mA:

    267 mA = 8 kA/s × 33.3 µs

    Some preliminary measurements suggest these (probably counterfeit) DRV8825 chips actually run at 16 kHz = 66 µs/cycle:

    3018 X - ripple 1 step - 18V - A0 B-90 500mA-div
    3018 X – ripple 1 step – 18V – A0 B-90 500mA-div

    During those cycles the current can increase by more than 500 mA. The first scope picture shows an abrupt increase to maybe 700 mA, so, yeah, that’s about right.

    Having the wrong current in one winding means the motor isn’t positioned correctly during those microsteps. The 3018-Pro runs at (an absurd) 1600 µstep/mm, so being off by even a full step isn’t big deal in terms of positioning.

    The real problem comes from running nearly 1 A through both windings. Those little motors run really hot: they’re dissipating twice what they should be.

    Anyhow, the pin layout shows the DRV8825 DECAY mode selection on pin 19:

    DRV8825 pinout
    DRV8825 pinout

    Which sits on an inconveniently skinny little PCB pad, fifth from the left on the bottom:

    DRV8825 PCB - open Decay pin
    DRV8825 PCB – open Decay pin

    Memo to Self: Don’t make that mistake when you lay out a PCB. Always put a little pad or via on a disconnected pin, so as to have a hand-soldering target big enough to work with.

    The objective is to pull the pin high:

    DRV8825 DECAY pin settings
    DRV8825 DECAY pin settings

    Pin 15, in the lower left corner, provides the output of a 3.3 V linear regulator, with its PCB trace connected to the left side of the ceramic cap:

    DRV8825 PCB - Decay pin wired low
    DRV8825 PCB – Decay pin wired low

    On the scale of TSSOP packages, even 30 AWG Wire-Wrap wire looks like a bus bar!

    Those are two different PCBs. The crappy TI logos, not easily visible in those low-res pix, on both ICs suggest they’re by-now-typical counterfeits, so seeing a factor-of-two difference in PWM frequency isn’t surprising.

  • Alligator Clip Lead Refurbishing

    So this happened when I grabbed an alligator clip lead:

    Dual Alligator Clip Collection
    Dual Alligator Clip Collection

    My coax cable and clip lead collection includes everything from “I’ve had it forever” to “Recent cheap crap”, including much of Mad Phil’s collection. Some of the recent crap included Chinese clip leads with what can charitably be described as marginal connections:

    Alligator clips - bent wire
    Alligator clips – bent wire

    The insulation may provide some compliance in the crimp, but the alligator clip itself consists of cheap steel which won’t hold a crimp, even if it was crimped firmly to start with.

    As a rule, the crimps aren’t particularly good:

    Black Dual Alligator - as manufactured
    Black Dual Alligator – as manufactured

    The most obvious effect is high end-to-end resistance:

    Black Dual Alligator - before - A
    Black Dual Alligator – before – A

    Yes, yes, 122 Ω in an alligator clip lead is high.

    The test setup isn’t particularly intricate:

    Black Dual Alligator - test setup
    Black Dual Alligator – test setup

    The lackadaisical crimps also have unstable resistances:

    Black Dual Alligator - before - B
    Black Dual Alligator – before – B

    So I figured I may as well repair the lot of ’em.

    I stripped the lead back to expose fresh copper, soldered it to the clip, then re-crimped the clip around the insulation for some token strain relief:

    Black Dual Alligator - soldered
    Black Dual Alligator – soldered

    I won’t win any soldering awards, but the resistance is way better than before:

    Black Dual Alligator - after
    Black Dual Alligator – after

    If more than half an ohm seems a tad high for a foot of copper wire, you’re right. My slightly magnetized bench screwdriver shows it’s not copper wire:

    Copper-plated steel wire
    Copper-plated steel wire

    I’d say it’s copper-plated steel, wouldn’t you?

    Those of long memory will recall the non-standard ribbon cable I used as a 60 kHz loop antenna. In this case, the Chinese manufacturer figured nobody would notice or, likely, care. Given the crappy overall quality of the end product, it’s a fair assumption.

    I was mildly tempted to replace the wire with good silicone-insulated copper, but came to my senses; those “high voltage” silicone test leads will be Good Enough for higher-current connections.

    While I was at it, I pulled apart my entire collection just to see what was inside and fix the ailing ones. These clips date back to the dawn of time, with what started as excellent crimps:

    Crimped Alligator Clips - as manufactured
    Crimped Alligator Clips – as manufactured

    Alas, after I-don’t-know-how-many decades, they’re not longer gas-tight, so I soaked a dollop of solder into each one:

    Crimped Alligator Clips - soldered - Made In Japan
    Crimped Alligator Clips – soldered – Made In Japan

    Chekkitout: “Made In Japan”.

    Someone, perhaps me wearing a younger man’s clothes or, less likely, Mad Phil in a hurry, solved a similar problem with bigger blobs and no strain relief:

    Crimped Alligator Clips - cut and soldered
    Crimped Alligator Clips – cut and soldered

    So, now I have a slightly better collection of crappy alligator clip leads. The copper-plated steel wires will eventually fail, but it should become obvious when they do.

    Test your clip leads today!

  • Bathroom Drain Rod Status

    The bathroom drain rod slipped out of the pop-up stopper, giving me the opportunity to see how well it’s surviving:

    Bathroom drain lever - 2019-08-03
    Bathroom drain lever – 2019-08-03

    After not quite two years, it’s not obviously rotting away.

    Life is good …

  • CNC 3018-Pro: Home Switches

    The CNC 3018-Pro doesn’t absolutely need home switches, but (in principle) they let you install a workholding fixture at a known position, home the axes, pick a preset coordinate system for the fixture, and not have to touch off the axes before making parts.

    Having used Makerbot-style endstop switch PCBs for the MPCNC, this was straightforward:

    3018 CNC - Endstop switches - overview
    3018 CNC – Endstop switches – overview

    The X and Z axis switches simply press against the appropriate moving parts:

    3018 CNC - X and Z Endstops
    3018 CNC – X and Z Endstops

    The little tab stuck on the tool clamp provides a bit of clearance around the upper part of the X axis assembly.

    The Y axis switch needed a slightly tapered tab to extend the bearing holder:

    3018 CNC - Y axis endstop
    3018 CNC – Y axis endstop

    It’s made from a random scrap of clear plastic, hand-filed to suit, and stuck on the bearing to trigger the switch in exactly the right spot.

    You can find elaborate switch mounts on Thingiverse, but I’ve become a big fan of genuine 3M outdoor-rated foam tape for this sort of thing: aggressive stickiness, no deterioration, possible-but-not-easy removal.

    The switches need +5 V power, so add a small hack to the CAMTool V3.3 control board to let the connectors plug right in:

    3018 CNC CAMTool - Endstop power mod - installed
    3018 CNC CAMTool – Endstop power mod – installed

    The solid models borrow their central depression around the switch terminals from the MPCNC blocks:

    3018 Home Switch Mounts - Slic3r preview
    3018 Home Switch Mounts – Slic3r preview

    The OpenSCAD source code as a GitHub Gist:

    // 3018-Pro Mount for Makerbot Endstop PCB
    // Ed Nisley KE4ZNU – 2019-07
    /* [Build Options] */
    Layout = "Show"; // [Build, Show]
    /* [Hidden] */
    ThreadThick = 0.25; // [0.20, 0.25]
    ThreadWidth = 0.40; // [0.40]
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    Protrusion = 0.01; // [0.01, 0.1]
    HoleWindage = 0.2;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    //- Shapes
    // Basic PCB with hole for switch pins
    // origin at switch actuator corner, as seen looking at component side
    SwitchClear = [15.0,5.0,2.0]; // clearance around switch pins
    SwitchOffset = [12.5,9.0,0.0]; // center of switch pins from actuator corner
    PCB = [26.0,16.4,2*SwitchClear.z]; // switch PCB beyond connector, pin height
    XBlock = [PCB.x,PCB.y,5.0];
    module XMount() {
    difference() {
    cube(XBlock,center=false);
    translate(SwitchOffset + [0,0,XBlock.z – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    }
    YBlock = [PCB.x + 10.0,PCB.y,20.0];
    module YMount() {
    difference() {
    translate([-10.0,0,0])
    cube(YBlock,center=false);
    translate([0,-Protrusion,10.0])
    cube(YBlock + [0,2*Protrusion,0],center=false);
    translate(SwitchOffset + [0,0,10.0 – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    }
    ZBlock = [PCB.x,PCB.y,6.0];
    ZPin = [20.0,10.0,5.5];
    module ZMount() {
    difference() {
    cube(ZBlock,center=false);
    translate(SwitchOffset + [0,0,ZBlock.z – SwitchClear.z/2])
    cube(SwitchClear + [0,0,Protrusion],center=true);
    }
    translate([0,-ZBlock.y,0])
    difference() {
    cube(ZPin,center=false);
    translate([ZPin.x/2,-Protrusion,4.0])
    cube(ZPin + [0,2*Protrusion,0],center=false);
    }
    }
    //- Build things
    if (Layout == "Show") {
    translate([0,YBlock.y,0])
    XMount();
    translate([0,-YBlock.y/2])
    YMount();
    translate([0,-(ZBlock.y + YBlock.y)])
    ZMount();
    }

    The dimension doodles:

    3018 Home Switch Mounts - Dimension Doodles
    3018 Home Switch Mounts – Dimension Doodles