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: Electronics Workbench

Electrical & Electronic gadgets

  • Streaming Radio Player: OLED Garble

    Even in the dim light of dawn, it’s obvious slowing the SPI clock to 1 MHz didn’t quite solve the problem:

    RPi OLED display - garbled
    RPi OLED display – garbled

    The display started up fine, became encrypted during the next few hours, and remained garbled as the track information changed. This is almost certainly a bad SPI transfer trashing the OLED module’s control registers.

    Dropping the clock to the absolute minimum of 0.5 MHz didn’t help, either:

    serial = spi(device=0,port=0,bus_speed_hz=500000)
    device = sh1106(serial)
    

    This particular display woke up blank after loading the new code, then worked OK after another reset. The other streamers lit up as expected on the first try, so the slower SPI isn’t making the situation instantly worse.

    Running the clock at 1 MHz definitely reduced the failure rate, which suggests it’s a glitchy thing.

    Good embedded systems practice suggests resetting the entire display from scratch every now and again, but my streamer code has no concept of elapsed time. Opening that particular can o’ worms would almost certainly result in an on-screen clock and I do not want to go there.

    I suppose I must get a new oscilloscope with SPI bus decoding to verify all the SPI setup and hold times …

  • Stepper Motor Current Measurement Setup

    As part of installing the bar clamps, I packed away the Tek Hall effect current probes measuring the stepper winding currents:

    MPCNC Z Axis AB current probe - overview
    MPCNC Z Axis AB current probe – overview

    The hulking pistol is a Tektronix A6203 100 A probe, the little black pencil is a Tek A6302 20 A probe:

    MPCNC Z Axis AB current probe - detail
    MPCNC Z Axis AB current probe – detail

    The absurdity of measuring a 600 mA (peak!) current with a 100 A probe isn’t lost on me, but those things have become genuine eBay collectibles over the last few years.

    For low-frequency signals, you could probably get by with a Fluke i410 Hall effect current clamp.

    Yo, Eks, babes, remember me in your will … [grin]

  • Wouxun KG-UV3D: Enemy Action

    Once is happenstance, twice is coincidence, three times is enemy action:

    Wouxun KG-UV3D - failure 3
    Wouxun KG-UV3D – failure 3

    All of the (surviving) battery packs produce 9.0 to 9.2 V, a bit hotter than the pair of fully charged lithium cells the radio expects to see, but the first two radios lasted for six years under that abuse.

    This one failed after a few hours. It’s a new radio, but I’m willing to assume I killed the thing and will just eat the cost.

    I have no theories about what’s going on, but I must tweak my APRS interface to work with a Baofeng radio I have on the shelf.

    From now on, though, both radios will run from their stock battery packs.

    Maybe I’m just a slow learner.

  • M2 Thermistor Rebuild

    The MAXTEMP error killing the M2 while printing the bar clamp mounts (probably) came from a short in the thermistor pellet that lowered the thermistor resistance and raised the calculated temperature. I manually heated the extruder and, although the temperature stabilized at 250 °C, the history plot showed irregular downward jogs from increasing resistance. Whenever this constellation of symptoms appears on the M2 forums, I always recommend ordering another thermistor or two, so …

    Start by turning a 1/8 inch OD brass tube down to 3.00 mm, parting off a suitable length, facing the ends:

    M2 - thermistor brass tube turning
    M2 – thermistor brass tube turning

    Countersink the ends just for pretty.

    The tube should be a slip fit in the hot end:

    M2 - hot end thermistor - turned brass tube
    M2 – hot end thermistor – turned brass tube

    While I had the hot end on the bench, I scuffed the nozzle to remove (most of) the baked-on crud:

    M2 - nozzle silicone - cleaned nozzle
    M2 – nozzle silicone – cleaned nozzle

    The plan is to seal the thermistor bead inside the tube with JB Weld epoxy, which I’ve verified (!) to work at extrusion temperatures, depending on the epoxy to insulate the wiring and immobilize all the pieces.

    Harvest the original wire harness from the defunct thermistor, solder to the bead, lay out guide lines:

    M2 - thermistor - assembly 1 layout
    M2 – thermistor – assembly 1 layout

    Slobber epoxy over everytyhing, fill the tube, insert bead into tube, stabilize with tape:

    M2 - thermistor - assembly 1 curing
    M2 – thermistor – assembly 1 curing

    Verify connectivity through the thermistor and isolation from the brass tube, then return upstairs to warm up thaw out while the epoxy cures.

    At this point, the observant reader should be thinking “Uh, Ed, that bead looked a tad large. Are you absolutely sure  … ?”

    Halfway up the basement stairs I realized I’d meticulously entombed a 10 kΩ thermistor, not the 100 kΩ thermistor used in the M2’s hot end. You can easily verify the resistance, as I did, with a quick web search; I have hella-good SEO for some specific topics.

    Back to the lab …

    Fortunately, JB Weld has a pot life over an hour, so extract the wrong bead, unsolder, install the right thermistor using snippets of insulation harvested from the original wiring, realign components:

    M2 - thermistor - assembly 2 layout
    M2 – thermistor – assembly 2 layout

    Reapply epoxy:

    M2 - thermistor - assembly 2
    M2 – thermistor – assembly 2

    Re-verify resistances, return upstairs, fast-forward through the night, have another good idea …

  • MPCNC: Bar Clamp Mounts

    Rather than attach a spoil board directly to the bench top under the MPCNC, one can grab it in bar clamps anchored to the bench, which requires suitable mounts. Because bar clamps are all the same, one must be flipped over to point the other way, soooo the mounts come in mirror-image sets.

    Holding the clamp on the left side of the table:

    Bar Clamp Mounts - Left - solid model
    Bar Clamp Mounts – Left – solid model

    For the right-side clamp:

    Bar Clamp Mounts - Right - solid model
    Bar Clamp Mounts – Right – solid model

    The chunky clamp prints on its end, with its bottom surface facing away from you, to let the block in the middle print without support. In that orientation, the bar slides in from the top.

    The fancy rounded corners happened while I iterated on getting the dimensions right.

    Actually printing and installing the things turned out to be separate challenges.

    The OpenSCAD source code as a GitHub Gist:

    // MPCNC Bar Clamp Mounts
    // Ed Nisley KE4ZNU – 2018-02-03
    Layout = "Build"; // BarEnd EndBlock ScrewBlock Build
    Chirality = "Right"; // bar handedness = side with opening
    /* [Extrusion] */
    ThreadThick = 0.25; // [0.20, 0.25]
    ThreadWidth = 0.40; // [0.40]
    /* [Hidden] */
    Protrusion = 0.1; // [0.01, 0.1]
    HoleWindage = 0.2;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    ID = 0;
    OD = 1;
    LENGTH = 2;
    //- Adjust hole diameter to make the size come out right
    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);
    }
    /* [Clamp] */
    BarEndOut = [34.5,21.0]; // outside dimensions
    BarEndIn = [28.0,18.0]; // … inside
    BarEndSlot = [2.8,11.5]; // slot on open side
    BarEndRadius = 1.5; // corner rounding
    NumSides = 3*4; // … and sides
    BarHeightOC = 22.0; // min height above bench
    Clearance = 0.2; // overall bar clearance
    PinOffset = [14.0,2.5]; // clamp hardware pin location
    PinOD = 6.5; // … pin OD
    WallThick = 5.0; // basic wall & floor thickness
    EndBlockSize = [2*PinOffset.x + WallThick,BarEndOut.x + 2*WallThick,BarHeightOC + BarEndOut.y/2];
    ScrewBlockSize = [2*PinOffset.x,BarEndOut.x + 2*WallThick,BarHeightOC + BarEndOut.y/2];
    //—–
    // Define shapes
    // Aluminum bar extrusion
    module BarEnd(Length = 2.0,Hollow=true) {
    linear_extrude(height=Length,convexity=3)
    offset(delta=Clearance)
    difference() {
    hull()
    for (i=[-1,1], j=[-1,1])
    translate([i*(BarEndOut.x/2 – BarEndRadius),j*(BarEndOut.y/2 – BarEndRadius)])
    circle(r=BarEndRadius,$fn=3*4); // not related to block corner rounding
    if (Hollow) {
    translate([BarEndOut.x/2 – BarEndIn.x/2 – BarEndSlot.x,0])
    square(BarEndIn,center=true);
    translate([BarEndOut.x/2,0])
    square([BarEndOut.x,BarEndSlot.y],center=true);
    }
    }
    }
    // Block supporting open end of Bar
    module EndBlock() {
    Normal = (Chirality == "Left") ? [0,0,0] : [0,1,0];
    Radius = WallThick;
    mirror(Normal)
    difference() {
    if (true)
    hull() {
    dx = EndBlockSize.x/2 – Radius;
    dy = EndBlockSize.y/2 – Radius;
    for (i=[-1,1],j=[-1,1])
    translate([i*dx,j*dy,EndBlockSize.z – Radius]) {
    sphere(r=Radius,$fn=NumSides);
    cylinder(r=Radius,h=Protrusion,$fn=NumSides);
    }
    for (i=[-1,1],j=[-1,1])
    translate([i*dx,j*dy,0])
    cylinder(r=Radius,h=Protrusion,$fn=NumSides);
    }
    else
    translate([-EndBlockSize.x/2,-EndBlockSize.y/2,0])
    cube(EndBlockSize,center=false);
    translate([EndBlockSize.x/2 – PinOffset.x,0*PinOffset.y,-Protrusion])
    rotate(180/8)
    PolyCyl(PinOD,2*EndBlockSize.z,8);
    translate([EndBlockSize.x/2 – 2*PinOffset.x,0,BarHeightOC])
    rotate([0,90,0]) rotate(-90)
    BarEnd(Length=EndBlockSize.x);
    }
    }
    // Block supporting screw end of Bar
    // Ad-hoc chamfers to clear screw mount castings
    module ScrewBlock() {
    Normal = (Chirality == "Left") ? [0,0,0] : [0,1,0];
    Radius = WallThick;
    mirror(Normal)
    difference() {
    if (true)
    hull() {
    dx = ScrewBlockSize.x/2 – Radius;
    dy = ScrewBlockSize.y/2 – Radius;
    for (i=[-1,1],j=[-1,1])
    translate([i*dx,j*dy,ScrewBlockSize.z – Radius]) {
    sphere(r=Radius,$fn=NumSides);
    cylinder(r=Radius,h=Protrusion,$fn=NumSides);
    }
    for (i=[-1,1],j=[-1,1])
    translate([i*dx,j*dy,0])
    cylinder(r=Radius,h=Protrusion,$fn=NumSides);
    }
    else
    translate([0,0,ScrewBlockSize.z/2])
    cube(ScrewBlockSize,center=true);
    translate([0,PinOffset.y,-Protrusion])
    rotate(180/8)
    PolyCyl(PinOD,2*ScrewBlockSize.z,8);
    translate([-ScrewBlockSize.x/2 – Protrusion,0,BarHeightOC])
    rotate([0,90,0]) rotate(-90)
    BarEnd(Length=ScrewBlockSize.x + 2*Protrusion,Hollow=false);
    for (i=[-1,1])
    translate([i*ScrewBlockSize.x/2,ScrewBlockSize.y/2,ScrewBlockSize.z – Protrusion])
    rotate(45)
    cube([sqrt(2)*WallThick,sqrt(2)*WallThick,2*ScrewBlockSize.z],center=true);
    }
    }
    //—–
    // Build things
    if (Layout == "BarEnd")
    BarEnd();
    if (Layout == "EndBlock")
    EndBlock();
    if (Layout == "ScrewBlock")
    ScrewBlock();
    if (Layout == "Build") {
    translate([EndBlockSize.z/2,0.6*EndBlockSize.y,EndBlockSize.x/2])
    rotate([0,-90,0])
    EndBlock();
    translate([0,-0.6*ScrewBlockSize.y,0])
    ScrewBlock();
    }

    The original doodles, with initial dimensions & some bad ideas:

    Bar Clamp Mount - Dimension Doodles
    Bar Clamp Mount – Dimension Doodles

     

  • MPCNC: Stepper Drive vs. Back EMF at the Edge of Madness

    This is what the stepper current looks like when you run an MPCNC at 12000 mm/min = 200 mm/s from a 24 V supply:

    G0 X 25.6 - A drive - 200 mm-s - low I - 24V 200mA-div
    G0 X 25.6 – A drive – 200 mm-s – low I – 24V 200mA-div

    The vertical scale for the winding current in the top trace is 200 mA/div, so those flat sections run about 150 mA, well under the 600 mA peak found at lower speeds. This G0 move ramps up to 12000 mm/min and shows the current falling off and the sine wave deteriorating:

    G0 X 200 mm-s - 24V 200mA-div
    G0 X 200 mm-s – 24V 200mA-div

    The motor turns at 375 RPM, which means each stepper generates 12 Vpk back EMF, so the A4988 driver has absolutely no control authority near what should be the zero crossings of the current waveform.

    The taller waveform along the bottom of the first scope shot comes from the H bridge output tending to increase the current waveform, so it’s applying a solid +24  during the flat top section and not only gets no traction, but actually loses ground just after the middle of the screen. Eventually the back EMF drops and the current begins increasing, but long after what should be the 600 mA peak current where the driver flips the H bridge and begins trying to decrease the current.

    Here’s a detailed view of the section just after the left cursor:

    G0 X 25.6 - A drive - low I - detail - 24V 200mA-div
    G0 X 25.6 – A drive – low I – detail – 24V 200mA-div

    The step pulses tick along at 50 μs intervals, with only two driver PWM pulses for each one.

    A 2-flute carbide cutter spinning at 20000 RPM with a 0.25 mm chip load calls for a speed of 10000 mm/min. Alas, the stock 12 V supply stalls at 8000 mm/min:

    MPCNC G1X20F8000 - 500 mA-div 50 ms-div
    MPCNC G1X20F8000 – 500 mA-div 50 ms-div

    It’s facing something over 9 V of back EMF from the motors at that speed. The chaotic spikes near the middle of the current waveform show where the rotor dropped out of lock with the driver and begins shoving the current around.

    So that’s why you really can’t use a 12 V power supply with series stepper motors, at least if you want to run ’em at more than moderate speeds. It’s not at all clear the 24 V supply will provide enough motor torque to run at 10 k mm/min, so I gotta wrap an enclosure around the electronics and start making some chips to see how it behaves …

  • Monthly Science: Wearable LED vs. Dead CR2032 Lithium Cell

    Eight months later, the dead CR2032 cell driving the “ruby” wearable LED has dropped to 2.15 V:

    Wearable LED - on window
    Wearable LED – on window

    It’s not a true red LED with a 1.5-ish V forward drop, but a white / blue LED with red phosphor or a red filter, with a forward drop well over 3 V.

    Against the sunlit backdrop from our kitchen window, the LED looks dark:

    Wearable LED - daylight
    Wearable LED – daylight

    Seen in a dim room, it’s still glowing:

    Wearable LED - dim light
    Wearable LED – dim light

    The current is now far below the 1 mA/div of my Tek A6302 Hall effect probe, so I have no way to measure the few microamps lighting the junction.

    The coarse grid outside the window is a swatch of deer netting we put up during feeder season to keep the birds from killing themselves on the glass.