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

  • JYE Tech DSO150 Oscilloscope: Build Notes

    I did a quick build of a JYE Tech DSO150 oscilloscope to see how it’d work in a proposed Squidwrench advanced soldering class / kit build session.

    The main board requires adding only a few switches and headers, then removing a 0 Ω jumper resistor:

    DSO150 - main board - bottom
    DSO150 – main board – bottom

    The analog board requires a handful of 1/8 W resistors, various capacitors, switches, and the BNC connector:

    DSO150 - main board - front
    DSO150 – main board – front

    Some (lightly edited) color commentary from my summary email:

    • Just finished assembling the kit, which required two hours; I’m admittedly fussy. The one joint I missed on the input coupling switch required a complete disassembly, but all the rest worked fine.
    • The UI is much better than the DSO138.
    • Soldering the BNC connector requires lots of heat. My ordinary Hakko iron had inadequate grunt, so I deployed the hulking Radio Shack 150 W gun and did the job in seconds.
    • The resistors require a meter to measure them during installation, because they’re 1% 1/8 W jobbies with many teeny color strips in Chinese tints you’ve never seen before. I could not sort them visually, even with a lighted headband magnifier, and I know what I’m looking for.
    • The caps are marked, but using a meter builds confidence.
    • And, yes, the kit had all the right parts and they all worked. The instructions call for powering up the main board before starting assembly, then again after removing a 0 Ω jumper resistor, but that’s the extent of the “testing” required.
    • They recommend a flush cutter and I’d say it’s pretty much required. An ordinary diagonal cutter won’t get close enough to the PCB.
    • I needed an angle-tip tweezer to lay the PCB screws in place.
    • Don’t install the knob until the very last step and maybe wait until you’ve verified all the functions. You have been warned.
    • The minimum power supply voltage really is 8.0 V, not the 7.4 V from a not-quite-fully-charged pair of lithium cells. A 9 V alkaline battery will last a few minutes. A noisy boost converter / crappy 9 V wall wart translates directly into noise on the display, particularly on the internal calibration signal.
    • The “0.1 V” calibration signal turned out to be 150 mV, as measured on a real scope, at 1 kHz. The 3.3 V signal is closer to reality. Both are noisy from a noisy supply.
    • All in all, it’s a pretty good scope for thirty bucks!
    • Newbies will find it a challenging three hour build, for sure.

    The next step involves adding a case and battery power:

    DSO150 battery hack - first light
    DSO150 battery hack – first light
  • Sony NP-BX1 Battery Holder: SMT Pogo Pin Contacts

    The original camera battery test fixtures used contact pins conjured from hulking gold-plated connector pins and coil springs:

    Canon NB-6L holder - contact pin detail
    Canon NB-6L holder – contact pin detail

    The Sony HDR-AS30V camera chewed up and spat out a handful of batteries, all tested in the NP-BX1 test fixture:

    NP-BX1 Holder - show layout
    NP-BX1 Holder – show layout

    Nowadays, SMT pogo pins produce a much more compact holder, so I figured I could put all those batteries to good use:

    NP-BX1 Holder - SMT pogo pins
    NP-BX1 Holder – SMT pogo pins

    That’s the long-suffering astable multivibrator, still soldered to its CR123A holder.

    Obviously, the battery holder should grow ears to anchor the 14 AWG copper posts and would look better in black PETG:

    NP-BX1 Battery Holder - 1.5mm pins - solid model
    NP-BX1 Battery Holder – 1.5mm pins – solid model

    The battery lead wires get soldered to the ends of the pogo pins and are recessed into the slot in the end of the fixture. I used clear epoxy to anchor everything in place.

    Fits perfectly and works fine!

    The OpenSCAD source code as a GitHub Gist:

    // Holder for Sony NP-BX1 Li-Ion battery
    // Ed Nisley KE4ZNU January 2013
    // 2018-11-15 Adapted for wire leads from 1.5 mm test pins, added upright wire bases
    // Layout options
    Layout = "Show"; // Show Build Fit Case Lid Pins
    //- Extrusion parameters – must match reality!
    // Print with +2 shells and 3 solid layers
    ThreadThick = 0.25;
    ThreadWidth = 0.35;
    HoleWindage = 0.2;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    Protrusion = 0.1; // make holes end cleanly
    inch = 25.4;
    BuildOffset = 3.0; // clearance for build layout
    Gap = 2.0; // separation for Fit parts
    //- Battery dimensions – rationalized from several samples
    // Coordinate origin at battery contact face with key openings below contacts
    Battery = [43.0,30.0,9.5]; // X = length, Y = width, Z = thickness
    Contacts = [[-0.75,6.0,6.2],[-0.75,16.0,6.2]]; // relative to battery edge, front, and bottom
    KeyBlocks = [[1.75,3.70,2.90],[1.75,3.60,2.90]]; // recesses in battery face set X position
    //- Pin dimensions
    ID = 0;
    OD = 1;
    LENGTH = 2;
    PinShank = [1.5,2.0,6.5]; // shank, flange, compressed length
    PinFlange = [1.5,2.0,0.5]; // flange, length included in PinShank
    PinTip = [0.9,0.9,2.5]; // extended spring-loaded tip
    PinChannel = PinFlange[LENGTH] + 0.5; // cut behind flange for solder overflow
    PinRecess = 3.0; // recess behind pin flange end for epoxy fill
    echo(str("Contact tip dia: ",PinTip[OD]));
    echo(str(" .. shank dia: ",PinShank[ID]));
    OverTravel = 0.5; // space beyond battery face at X origin
    //- Holder dimensions
    GuideRadius = ThreadWidth; // friction fit ridges
    GuideOffset = 7; // from compartment corners
    WallThick = 4*ThreadWidth; // holder sidewalls
    BaseThick = 6*ThreadThick; // bottom of holder to bottom of battery
    TopThick = 6*ThreadThick; // top of battery to top of holder
    ThumbRadius = 10.0; // thumb opening at end of battery
    CornerRadius = 3*ThreadThick; // nice corner rounding
    CaseSize = [Battery.x + PinShank[LENGTH] + OverTravel + PinRecess + GuideRadius + WallThick,
    Battery.y + 2*WallThick + 2*GuideRadius,
    Battery.z + BaseThick + TopThick];
    CaseOffset = [-(PinShank[LENGTH] + OverTravel + PinRecess),-(WallThick + GuideRadius),0]; // position around battery
    LidOverhang = 2.0; // over top of battery for retention
    LidSize = [-CaseOffset.x + LidOverhang,CaseSize.y,TopThick];
    LidOffset = [0.0,CaseOffset.y,0];
    //———————-
    // 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);
    }
    //——————-
    //– Guides for tighter friction fit
    module Guides() {
    translate([GuideOffset,-GuideRadius,0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    translate([GuideOffset,(Battery.y + GuideRadius),0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    translate([(Battery.x – GuideOffset),-GuideRadius,0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    translate([(Battery.x – GuideOffset),(Battery.y + GuideRadius),0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    translate([(Battery.x + GuideRadius),GuideOffset/2,0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    translate([(Battery.x + GuideRadius),(Battery.y – GuideOffset/2),0])
    PolyCyl(2*GuideRadius,(Battery.z – Protrusion),4);
    }
    //– Contact pins
    // Rotated to put them in their natural oriention
    // Aligned to put tip base / end of shank at Overtravel limit
    module PinShape() {
    translate([-(PinShank[LENGTH] + OverTravel),0,0])
    rotate([0,90,0])
    rotate(180/6)
    union() {
    PolyCyl(PinTip[OD],PinShank[LENGTH] + PinTip[LENGTH],6);
    PolyCyl(PinShank[ID],PinShank[LENGTH] + Protrusion,6); // slight extension for clean cuts
    PolyCyl(PinFlange[OD],PinFlange[LENGTH],6);
    }
    }
    // Position pins to put end of shank at battery face
    // Add wire exit channel between pins
    // Does not include recess access
    module PinAssembly() {
    union() {
    for (p = Contacts)
    translate([0,p.y,p.z])
    PinShape();
    translate([-(PinShank[LENGTH] + OverTravel) + PinChannel/2,
    (Contacts[1].y + Contacts[0].y)/2,
    Contacts[0].z])
    cube([PinChannel,(Contacts[1].y – Contacts[0].y),PinFlange[OD]],center=true);
    }
    }
    //– Case with origin at battery corner
    module Case() {
    difference() {
    union() {
    difference() {
    translate([(CaseSize.x/2 + CaseOffset.x), // basic case shape
    (CaseSize.y/2 + CaseOffset.y),
    (CaseSize.z/2 – BaseThick)])
    hull()
    for (i=[-1,1], j=[-1,1], k=[-1,1])
    translate([i*(CaseSize.x/2 – CornerRadius),
    j*(CaseSize.y/2 – CornerRadius),
    k*(CaseSize.z/2 – CornerRadius)])
    sphere(r=CornerRadius,$fn=8);
    translate([-OverTravel,-GuideRadius,0])
    cube([(Battery.x + GuideRadius + OverTravel),
    (Battery.y + 2*GuideRadius),
    (Battery.z + Protrusion)]); // battery space
    }
    Guides(); // improve friction fit
    translate([-OverTravel,-GuideRadius,0]) // battery keying blocks
    cube(KeyBlocks[0] + [OverTravel,GuideRadius,0],center=false);
    translate([-OverTravel,(Battery.y – KeyBlocks[1].y),0])
    cube(KeyBlocks[1] + [OverTravel,GuideRadius,0],center=false);
    }
    translate([(-OverTravel), // battery top access
    (CaseOffset.y – Protrusion),
    Battery.z])
    cube([CaseSize.x,(CaseSize.y + 2*Protrusion),(TopThick + Protrusion)]);
    translate([(CaseOffset.x – Protrusion), // battery insertion allowance
    (CaseOffset.y – Protrusion),
    Battery.z])
    cube([(CaseSize.x + 2*Protrusion),(CaseSize.y + 2*Protrusion),(TopThick + Protrusion)]);
    translate([(Battery.x – Protrusion), // remove thumb notch
    (CaseSize.y/2 + CaseOffset.y),
    (ThumbRadius)])
    rotate([90,0,0])
    rotate([0,90,0])
    cylinder(r=ThumbRadius,
    h=(WallThick + GuideRadius + 2*Protrusion),
    $fn=22);
    PinAssembly();
    translate([CaseOffset.x + PinRecess/2 + Protrusion/2,(Contacts[1].y + Contacts[0].y)/2,Contacts[0].z])
    cube([PinRecess + Protrusion,
    (Contacts[1].y – Contacts[0].y + PinFlange[OD]),
    2*PinFlange[OD]],center=true);
    }
    }
    // Lid position offset to match case
    module Lid() {
    translate([-LidSize.x/2 + LidOffset.x + LidOverhang,LidSize.y/2 + LidOffset.y,0])
    difference() {
    hull()
    for (i=[-1,1], j=[-1,1], k=[-1,1])
    translate([i*(LidSize.x/2 – CornerRadius),
    j*(LidSize.y/2 – CornerRadius),
    k*(LidSize.z – CornerRadius)]) // double thickness for flat bottom
    sphere(r=CornerRadius,$fn=8);
    translate([0,0,-LidSize.z/2])
    cube([(LidSize.x + 2*Protrusion),(LidSize.y + 2*Protrusion),LidSize.z],center=true);
    cube([LidSize.x/4,0.75*LidSize.y,4*ThreadThick],center=true); // epoxy recess
    }
    }
    //——————-
    // Build it!
    if (Layout == "Case")
    Case();
    if (Layout == "Lid")
    Lid();
    if (Layout == "Pins") {
    color("Silver",0.5)
    PinShape();
    PinAssembly();
    }
    if (Layout == "Show") { // reveal pin assembly
    difference() {
    Case();
    translate([(CaseOffset.x – Protrusion),
    Contacts[1].y,
    Contacts[1].z])
    cube([(-CaseOffset.x + Protrusion),
    CaseSize.y,
    (CaseSize.z – Contacts[0].z + Protrusion)]);
    translate([(CaseOffset.x – Protrusion),
    (CaseOffset.y – Protrusion),
    0])
    cube([(-CaseOffset.x + Protrusion),
    Contacts[0].y + Protrusion – CaseOffset.y,
    CaseSize.z]);
    }
    color("Silver",0.15)
    PinAssembly();
    translate([0,0,Battery.z + Gap])
    Lid();
    }
    if (Layout == "Build") {
    translate([-(CaseSize.x/2 + CaseOffset.x),-(CaseOffset.y – BuildOffset),BaseThick])
    Case();
    translate([CaseSize.y/2,(CaseOffset.x/2 – BuildOffset),0])
    rotate([0,0,90])
    Lid();
    }
    if (Layout == "Fit") {
    Case();
    translate([0,0,(Battery.z + Gap)])
    Lid();
    color("Silver",0.25)
    PinAssembly();
    }
  • Makergear M2 V4 Nozzle: More Silicone!

    A Makergear forum discussion on PETG hair and the prevention thereof prompted me to take a look at the silicone coating I’d applied to the nozzle:

    M2 - nozzle silicone - applied
    M2 – nozzle silicone – applied

    That was ten months ago. This is now:

    M2 Nozzle - worn silicone coat
    M2 Nozzle – worn silicone coat

    The camera sees the nozzle in a mirror laid flat on the platform, making the image less crisp than a direct view.

    So the silicone seems a bit worn around the tip, has acquired a few firmly adhered globs, and definitely isn’t as shiny.

    Rather than (try to) peel it off and reapply a new coating, I picked off the globs, cleaned around the nozzle, and slobbered a thin layer atop the existing silicone:

    M2 Nozzle - more silicone
    M2 Nozzle – more silicone

    Extruding a few millimeters of filament pushed the film off the nozzle opening and it now works as well as it ever did.

     

  • Electrolux Vacuum Cleaner: Cord Protection

    The ancient (Came With The House™) Electrolux canister vacuum cleaner long ago lost the plastic bushing around the opening passing its retractable cord, which I’d long sworn to replace.  A recent trip around the Basement Laboratory paused near the recently relocated Box o’ Wire Loom & Braid, whereupon I snipped off a few inches of split loom and tucked it in place:

    Electrolux Vacuum - cushioned cord cutout
    Electrolux Vacuum – cushioned cord cutout

    Looks and works better than before, anyhow.

    The blue flap dangling off the back should latch over the exhaust port, but failed long ago when the latch tab eroded. I attempted a repair, which never worked quite right, and won’t get around to attempting another for quite a while.

  • Badger Propel Air Fittings: DIY Rubber Washers

    Unlike ordinary bike tubes, Michelin ProTek tubes have a square-ish cross section:

    Michelin Protek Max Tube - carton
    Michelin Protek Max Tube – carton

    So, having a defunct Michelin ProTek tube in hand, I cut, cleaned, and dissected a few inches, then punched out a set of (flat!) washers for the Badger Propel air fittings:

    Badger 260 Propel fitting seals - inner-tube version
    Badger 260 Propel fitting seals – inner-tube version

    As with the cork version, they fit fine:

    Badger Propel fitting - DIY rubber seal
    Badger Propel fitting – DIY rubber seal

    The picture is slightly fuzzy, because zooming a Pixel photo doesn’t magically create any new mmmm pixels.

    I tested the washer with 45 psi air (the recommended maximum) and it holds the pressure fine. Better than a fouled ProTek valve, anyway.

    Flushed with success, I preemptively replaced both OEM cork washers, an action which will surely come back to haunt me.

     

     

  • Michelin ProTek Max Tube: Autopsy

    The Michelin ProTek Max tube I installed two years ago developed a slow leak this year, which I eventually ascribed to the valve stem, because the sealant should plug any other leak.

    Cutting it open reveals the perfectly good greenish-yellow sealant:

    Michelin ProTek tube - sealant
    Michelin ProTek tube – sealant

    The sealant also carries black rubbery grit / shavings / dust, perhaps intended to jam inside larger gashes while the sealant coagulates and binds it together.

    There’s a lot of rubber floating around in there:

    Michelin ProTek tube - rubber fragments
    Michelin ProTek tube – rubber fragments

    Dismantling the Presta valve stem show the rubbery crud on and around the valve seal and seat:

    Michelin ProTek tube - fouled valve seal
    Michelin ProTek tube – fouled valve seal

    Whenever I pumped up the tires, I finger-tightened the nut to ensure a good seal, as you do with all Presta valves. Obviously, finger-tight can’t handle that much crud between the sealing surfaces.

    I’m sorry to say I was right about the leaky valve stem, because I think all the ProTek tubes will fail in exactly the same way.

    The valve has small wrench flats making it easy to remove, so I can at least attempt to de-gunk them when they develop slow leaks.

    Color me unimpressed.

     

  • Vacuum Tube LEDs: 21HB5A on a Guilloche Platter

    With the Joggy Thing running in LinuxCNC 2.7, touching XY off on the fixture was trivially easy:

    LinuxCNC - Sherline Mill - Logitech Gamepad
    LinuxCNC – Sherline Mill – Logitech Gamepad

    The pips are 100 mm apart at (-50,-50) and (+50,50). Astonishingly, the laser aligner batteries are in fine shape.

    I should have protected the platter before drilling all those holes:

    Guilloche platter - drilling
    Guilloche platter – drilling

    All’s well that ends well:

    21HB5A - Guilloche platter
    21HB5A – Guilloche platter

    It looks even better in the dark, although you’d never know it from this picture:

    21HB5A - Guilloche platter - dark
    21HB5A – Guilloche platter – dark

    I wish I could engrave those patterns on already-drilled platters, but dragging a diamond point into a hole can’t possibly end well. I could deploy the Tiny Sandblaster with a vinyl mask, if I had enough artistic eptitude to lay out a good-looking mask.