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

  • Mary’s Zucchini Bread Recipe

    Mary’s Zucchini Bread Recipe

    After grating the nutmeg, continue with this:

    Mary's Zucchini Bread Recipe
    Mary’s Zucchini Bread Recipe

    To end up with this:

    Zucchini bread - minus QC sample
    Zucchini bread – minus QC sample

    Mary omits the cloves.

    Applesauce is completely optional. Should you prefer a softer & sweeter loaf, give it a try.

    Conversely, reduce the sugar by about half if you’ve accustomed yourself to a keto-oid diet; the raisins carry enough sweetness for us. You can use brown sugar if you like.

    She derived it from the Garden Way’s Zucchini Cookbook by Ralston & Jordan (© 1977):

    Zucchini Bread Recipe - Garden Way Zucchini Cookbook
    Zucchini Bread Recipe – Garden Way Zucchini Cookbook

    Obviously, cooking is not an exact science; a recipe is just where you start …

    Algorithmic pricing / money laundering is a thing:

    Garden Way Zucchini Cookbook - Amazon listing
    Garden Way Zucchini Cookbook – Amazon listing

    Ya can’t make this stuff up …

  • Keyboard Tray Raising

    Keyboard Tray Raising

    Long ago and far away, I moved the keyboards off our desk surfaces to a more convenient location on a tray under the middle drawer. Mary’s desk recently gained a somewhat thinner keyboard with a thumbwheel volume control, so she wanted the tray moved up:

    Keyboard Tray Relocation - in place
    Keyboard Tray Relocation – in place

    The supports on either side started out as 2×4 lumber with a slot cut (using the radial arm saw I no longer have) for the aluminum sheet:

    Keyboard Tray Relocation - support view
    Keyboard Tray Relocation – support view

    For the record, a pair of screws hold each support to the drawer:

    Keyboard Tray Relocation - support screw
    Keyboard Tray Relocation – support screw

    Not elegant. Works fine. Good enough!

    Tiny Bandsaw™ wasn’t designed for ripsawing lumber, but the same Proxxon 10/14 TPI blade I use for aluminum worked better than I expected to lop a 1-¼ inch strip from the wood slats:

    Keyboard Tray Relocation - bandsaw fixture
    Keyboard Tray Relocation – bandsaw fixture

    That’s a reenactment based on a true story. The wood scraps clamped on the bandsaw table leave enough clearance for the 2×4 slide to freely, yet not enough for the blade to wander off track.

    You can tell how long ago I built the original trays: nary a trace of 3D printing!

  • Nutmeg Season

    Nutmeg Season

    Well, it’s really zucchini bread season, with grated nutmeg among the spices (*):

    Zucchini bread - minus QC sample
    Zucchini bread – minus QC sample

    Having recently bought a very sharp grater, I hauled out a small vise to save my fingertips:

    Nutmeg grating - mini-vise
    Nutmeg grating – mini-vise

    The dark lunette comes from a previous clamping attempt; it takes a while to find the most secure pin arrangement.

    Grate a flat:

    Nutmeg grating - first flat
    Nutmeg grating – first flat

    I’ve always enjoyed the surprisingly intricate patterns inside what looks like a bland nut.

    Flip it over, flatten the other side, and grab it in an even smaller vise:

    Nutmeg grating - flat clamping
    Nutmeg grating – flat clamping

    In truth, that vise is intended for small cylinders, not flattened nuts, but I figured it’d suffice for light-duty use. Grate parallel to the vise screw, reclamp as needed, and it worked out reasonably well.

    Eventually, you have a pile of powder and one cubic nutmeg:

    Nutmeg grating - results
    Nutmeg grating – results

    I’m sure there’s a way to grate the remaining cube, but I’m unwilling to shred my fingertips.

    Tip the powder into a small jar and repeat as needed. Each nutmeg produces about 5 grams and I did three of the things this time.

    Yummy!

    (*) We omit the cloves and knock the sugar down by half. Your tastes will surely differ.

    Update: Mary’s recipe!

  • Bike Helmet Mirror: Ball Mount

    Bike Helmet Mirror: Ball Mount

    Nine years ago, I didn’t know how enough to design a bike helmet mirror with a ball mount, but even an old dog can learn a new trick:

    Helmet Mirror Ball Mount - on helmet
    Helmet Mirror Ball Mount – on helmet

    However, it’s worth noting my original, butt-ugly Az-El mounts lasted for all of those nine years, admittedly with adjustments along the way, which is far more than the commercial mounts making me unhappy enough to scratch my itch.

    The mount adapts the split spherical clamp from the daytime running light:

    Helmet Mirror Mount - Ball
    Helmet Mirror Mount – Ball

    Scaling it down for a 10 mm polypropylene ball around the base of the 30 mm inspection mirror’s shaft simplified everything:

    Helmet Mirror Ball Mount - drilled ball test
    Helmet Mirror Ball Mount – drilled ball test

    I’m reasonably sure I couldn’t have bought 100 polypro balls for eight bucks a decade ago, but we’ll never know. Drilling the hole was a complete botch job, about which more later. The shaft came from a spare mirror mount I made up a while ago; a new shaft appears below.

    The solid model, like Gaul, is in three parts divided:

    Helmet Mirror Ball Mount - Slic3r
    Helmet Mirror Ball Mount – Slic3r

    The helmet plate (on the right) has a slight indent more-or-less matching the helmet curvature and gets a layer of good double-stick foam tape. The clamp base (on the left) has a pair of brass inserts epoxied into matching recesses below the M3 clearance holes:

    Helmet Mirror Ball Mount - inserts
    Helmet Mirror Ball Mount – inserts

    A layer of epoxy then sticks the helmet plate in place, with the inserts providing positive alignment:

    Helmet Mirror Ball Mount - plates
    Helmet Mirror Ball Mount – plates

    The clamp screws pull the inserts against the plastic in the clamp base, so they can’t pull out or through, and the plates give the epoxy enough bonding surface that (I’m pretty sure) they won’t ever come apart.

    I turned down a 2 mm brass insert to fit inside the butt end of the mirror shaft and topped it off with a random screw harvested from a dead hard drive:

    Helmet Mirror Ball Mount - assembled - rear view
    Helmet Mirror Ball Mount – assembled – rear view

    At the start, it wasn’t obvious the shaft would stay stuck in the ball, so I figured making it impossible to pull out would eliminate the need to find it by the side of the road. As things turned out, the clamp exerts enough force to ensure the shaft ain’t goin’ nowhere, so I’ll plug future shafts with epoxy.

    The front side of the clamp looks downright sleek:

    Helmet Mirror Ball Mount - assembled - front view
    Helmet Mirror Ball Mount – assembled – front view

    Well, how about “chunky”?

    The weird gray-black highlights are optical effects from clear / natural PETG, rather than embedded grunge; it looks better in person. I should have used retina-burn orange or stylin’ black.

    This mount is much smaller than the old one and should, in the event of a crash, not cause much injury. Based on how the running light clamp fractures, I expect the clamp will simply tear out of the base on impact. In the last decade, neither of us has crashed, so I don’t know what the old mount would do.

    The clamp is 7 mm thick (front-to-back), set by the M3 washer diameter, with 1.5 mm of ball sticking out on each side. The model has a kerf one thread high (0.25 mm) between the pieces to add clamping force and, with the screws tightened down, moving the ball requires a disturbingly large effort. I added a touch of rosin and that ball straight-up won’t move, which probably means the shaft will bend upon droppage; I have several spare mirrors in stock.

    On the other paw, the ball turns smoothly in the clamp and it’s easy to position the shaft as needed: much better than the old Az-El mount!

    The inspection mirror hangs from a double ball joint which arrives with a crappy screw + nut. I epoxied the old mirror mount nut in place, but this time around I drilled the plates for a 3 mm stainless SHCS, used a wave washer for a bit of flexible force, and topped it off with a nyloc nut:

    Helmet Mirror Ball Mount - mirror joint
    Helmet Mirror Ball Mount – mirror joint

    I’m unhappy with how it looks and don’t like how the washer hangs in free space between those bumps, so I may eventually turn little brass fittings to even things out. It’s either that or more epoxy.

    So far, though, it’s working pretty well and both units meet customer requirements.

    The OpenSCAD source code as a GitHub Gist:

    // Bike helmet mirror mount – ball joint
    // Ed Nisley KE4ZNU 2020-09
    /* [Layout options] */
    Layout = "Build"; // [Build, Show, Plate, Base, Clamp]
    //– Extrusion parameters
    // 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;
    //- Basic dimensions
    MountDia = 30.0; // footprint on helmet
    BallDia = 10.0;
    BallRad = BallDia / 2;
    WallThick = IntegerMultiple(2.0,ThreadWidth);
    FloorThick = IntegerMultiple(2.0,ThreadThick);
    CornerRound = 2.0;
    Insert = [3.0,4.0,4.0]; // threaded brass insert
    Screw = [3.0,5.5,25.0]; // clamp screw
    Washer = [3.7,7.0,0.7]; // washer
    ShowGap = 2.0;
    BuildGap = 5.0;
    //– Helmet Interface Plate
    ScrewOC = BallDia + 2*WallThick + Screw[ID];
    echo(str("Screw OC: ",ScrewOC));
    Clamp = [ceil(Washer[OD]), // barely holds washer under screw
    ScrewOC + Washer[OD], // minimal clearance for washer
    BallDia +2*FloorThick // screw fits through insert
    ];
    Kerf = ThreadThick;
    echo(str("Clamp: ",Clamp));
    HelmetCX = 60.0; // empirical helmet side curve
    HelmetMX = 3.0;
    HelmetRX = (pow(HelmetMX,2) + pow(HelmetCX,2)/4)/(2*HelmetMX);
    HelmetPlateC = MountDia;
    HelmetPlateTheta = atan(HelmetPlateC/HelmetRX);
    HelmetPlateM = 2*HelmetRX*pow(sin(HelmetPlateTheta/4),2);
    echo(str("Plate indent: ",HelmetPlateM));
    HelmetPlateThick = max(FloorThick,0.6*Insert[LENGTH]) + HelmetPlateM;
    echo(str("Screw length: ",Clamp.z + Insert[LENGTH]));
    MountSides = 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);
    }
    //———————-
    // Clamp frame around ball
    module ClampFrame() {
    difference() {
    union() {
    hull()
    for (i=[-1,1], j=[-1,1]) {
    translate([i*(Clamp.x/2 – CornerRound),j*(Clamp.y/2 – CornerRound),Clamp.z/2 – CornerRound])
    sphere(r=CornerRound,$fn=24);
    translate([i*(Clamp.x/2 – CornerRound),j*(Clamp.y/2 – CornerRound),-Clamp.z/2])
    cylinder(r=CornerRound,$fn=24);
    }
    for (j=[-1,1])
    translate([0,j*ScrewOC/2,0])
    rotate(180/12)
    cylinder(d=Washer[OD],h=Clamp.z/2,$fn=12);
    }
    sphere(d=BallDia + HoleWindage,$fn=48);
    cube([2*MountDia,2*MountDia,Kerf],center=true);
    for (j=[-1,1])
    translate([0,j*ScrewOC/2,-Screw[LENGTH]])
    rotate(180/6)
    PolyCyl(Screw[ID],2*Screw[LENGTH],6);
    }
    }
    module ClampSelect(Section) {
    XlateZ = (Section == "Top") ? Clamp.z/2 :
    (Section == "Bottom") ? -Clamp.z/2 :
    0;
    intersection(convexity=5) {
    ClampFrame();
    translate([0,0,XlateZ])
    cube([2*Clamp.x,2*Clamp.y,Clamp.z + 2*Protrusion],center=true);
    }
    }
    //———————-
    // Concave plate fitting helmet shell
    module HelmetPlate() {
    render()
    difference() {
    cylinder(d=MountDia,h=HelmetPlateThick,$fn=MountSides);
    translate([0,0,HelmetPlateThick – HelmetPlateM + HelmetRX])
    sphere(r=HelmetRX,$fn=128);
    for (j=[-1,1])
    translate([0,j*ScrewOC/2,-Protrusion]) {
    PolyCyl(Insert[OD],0.6*Insert[LENGTH] + Protrusion,6);
    PolyCyl(Screw[ID],2*HelmetPlateThick,6);
    }
    }
    }
    //———————-
    // Base of clamp ring
    module MountBase() {
    difference() {
    union() {
    cylinder(d=MountDia,h=FloorThick,$fn=MountSides);
    translate([0,0,FloorThick + Clamp.z/2])
    ClampSelect("Bottom");
    }
    for (j=[-1,1])
    translate([0,j*ScrewOC/2,-Protrusion])
    rotate(180/6)
    PolyCyl(Insert[OD],0.6*Insert[LENGTH] + Protrusion,6);
    }
    }
    //———————-
    // Lash it together
    if (Layout == "Plate") {
    HelmetPlate();
    }
    if (Layout == "Base") {
    MountBase();
    }
    if (Layout == "Clamp") {
    ClampFrame();
    }
    if (Layout == "Show") {
    rotate([180,0,0])
    HelmetPlate();
    translate([0,0,ShowGap]) {
    MountBase();
    color("Ivory",0.3)
    translate([0,0,Clamp.z/2 + FloorThick + ShowGap/2])
    sphere(d=BallDia);
    translate([0,0,Clamp.z/2 + FloorThick + ShowGap])
    ClampSelect("Top");
    }
    }
    if (Layout == "Build") {
    translate([MountDia/2 + BuildGap,0,0])
    HelmetPlate();
    translate([-(MountDia/2 + BuildGap),0,0])
    MountBase();
    translate([0,MountDia/2 + BuildGap,Clamp.z/2])
    rotate([0,180,0])
    rotate(90)
    ClampSelect("Top");
    }

    The original doodles include a bit of dress-up fairing that didn’t make the cut:

    Helmet Mirror Ball Mount - doodles
    Helmet Mirror Ball Mount – doodles
  • Discrete LM3909: Blue LED Waveforms

    Discrete LM3909: Blue LED Waveforms

    The circuitry and instrumentation is essentially the same discrete LM3909 as before:

    LM3909 - blue - test setup
    LM3909 – blue – test setup

    With a few minor tweaks:

    • Blue LED, forward voltage 2.56 to 2.97 V
    • 24 Ω R1
    • One Q2 current mirror transistor driving Q3

    With a pair of fresh AA alkaline cells producing 3.1 V (not the NiMH Duracells you see in the picture), the blue LED blinks brightly.

    The 610 mV peak voltage across R1 shows the LED starts at 25.4 mA:

    LM3909 blue - 3.1 V - R1 24 ohm
    LM3909 blue – 3.1 V – R1 24 ohm

    The capacitor reaches 1 V, then goes about 150 mV into reverse charge during the flash (note the different horizontal scales):

    LM3909 blue - 3.1 V - C1 V
    LM3909 blue – 3.1 V – C1 V

    The Darlington version of Q1 seems to do a decent job of keeping the cap out of reverse charge. A Shottky diode would add a few hundred mV, but I doubt there’s anything nasty going on inside the cap as it stands.

    The blue LED has a forward drop of 2.97 V at 20 mA, so I’m surprised the voltage across it hits 3.1 V at 25 mA:

    LM3909 blue - 3.1 V - LED V
    LM3909 blue – 3.1 V – LED V

    Very little of the voltage appears across Q3, the driver transistor:

    LM3909 blue - 3.1 V - Q3 coll
    LM3909 blue – 3.1 V – Q3 coll

    With a pair of nearly dead alkaline cells for a 2.0 V supply, the LED current peak drops to 4.6 mA:

    LM3909 blue - 2.0 V - R1 24 ohm
    LM3909 blue – 2.0 V – R1 24 ohm

    The LED lights brightly, then fades away exactly like you’d expect from that waveform.

    The cap still charges to about 1 V and stays well above 0 V during the (much longer) flash:

    LM3909 blue - 2.0 V - C1 voltage
    LM3909 blue – 2.0 V – C1 voltage

    The voltage across the LED now reaches only 2.7 V, which is substantially higher than the 2.0 V battery supply and exactly why the LM3909 existed:

    LM3909 blue - 2.0 V - LED voltage
    LM3909 blue – 2.0 V – LED voltage

    Q3 continues to saturate, although you can see the effect of the decreased base drive during the flash:

    LM3909 blue - 2.0 V - Q3 coll
    LM3909 blue – 2.0 V – Q3 coll

    The blue LED won’t light at 1.3 V, but still gives out a weak flash at 1.7 V, so I’d say the tweaked LM3909 circuitry works reasonably well.

  • DSO150: USB Serial Output

    DSO150: USB Serial Output

    Taking all those pictures of the DSO150 screen reminded me it has a data dump function: press the V/Div and ADJ buttons to squirt configuration, measurements, and trace data from the TX pad on the main board, just in front of the red-black power wires hot-melt glued in place:

    DSO150 USB serial adapter - interior
    DSO150 USB serial adapter – interior

    The picture shows the “before” stage, while I was figuring out where to carve another hole in the case.

    NB: The 113-15001-111 DSO150 firmware version includes the serial output option, so you won’t need third-party firmware. Similarly, current PCBs bring the serial pins to neatly labeled header pads. You should refer to the JYETech DSO150 / DSO Shell product page for the details.

    After all the cuttin’ and filin’ was done, it looked like this:

    DSO150 USB serial adapter - exterior
    DSO150 USB serial adapter – exterior

    The power switch on the back of the case (top of the picture) disconnects the lithium cell from the charge controller board (now tucked behind the battery) to eliminate any trickle current discharge. Charging the battery thus requires turning that switch on and turning the scope off with its own power switch (along its front edge). Capturing trace data requires having both switches on (duh), whereupon the scope’s normal operating current convinces the charge controller that the cell hasn’t reached full charge. Turn the scope off and, most likely, the controller will tell you the cell is fully charged.

    An intro blurb squirts from the port at 115200 in good old 8N1 format when you turn the scope on:

    DSO Shell
    JYE Tech Ltd.
    WWW.JYETECH.COM
    FW: 113-15001-111

    Pressing the V/Div and ADJ buttons dumps the trace data:

    VSen,0.5V
    Couple,DC
    VPos, -2.02V
    Timebase,0.2s
    HPos,00362
    TriggerMode,NORM
    TriggerSlope,Rising
    TriggerLevel,  2.02V
    RecordLength,01024
    Vmax,  2.85V
    Vmin,  0.24V
    Vavr,  0.87V
    Vpp,  2.61V
    Vrms,  1.03V
    Freq, 0.441Hz
    Cycl, 2.266s
    PW, 0.231s
    Duty, 10.2 %
    SampleInterval,00008ms
    00000,0000000000, 0.8518688
    00001,0000000008, 0.5273474
    00002,0000000016, 0.5273474
    00003,0000000024, 0.5476300
    00004,0000000032, 0.5476300
    00005,0000000040, 0.5476300
    << snippage >>
    01015,0000008120, 0.8113037
    01016,0000008128, 0.8315863
    01017,0000008136, 0.8315863
    01018,0000008144, 0.8315863
    01019,0000008152, 0.8315863
    01020,0000008160, 0.8315863
    01021,0000008168, 0.8315863
    01022,0000008176, 0.8518688
    01023,0000008184, 0.8518688

    It’s all in neatly comma-separated-value format, so you can slam it into a spreadsheet and have your way with it. Utilities also exist to capture the data, extract the values, and send them directly to GNUplot, etc.

    Like so:

    DSO150 test image
    DSO150 test image

    If I expected to do a lot of that, I’d boldify the traces and embiggen the text, all of which is in the nature of fine tuning.

    It’s hard to reproduce the beauty of the DSO150’s display, though:

    DSO150 test image
    DSO150 test image

    The DSO150 remains pretty good for being the worst oscilloscope I’m willing to use …

  • Step2 Garden Seat: Replacement Seat2

    Step2 Garden Seat: Replacement Seat2

    As expected, the plywood seat I put on the Step2 Garden Seat for Mary’s Vassar Farms plot lasted about a year before the wood rotted away around the screws. In the meantime, we’d acquired a stack of SiLite cafeteria trays, so we applied one to the cause of better seating:

    Step2 Seat - tray variant
    Step2 Seat – tray variant

    Various eBay listings value that slab of Bakelite Melamine up to $20, which is far more than Mary paid for the entire stack at a local tag sale. They also call that color “rich brown”, which is certainly better than what immediately came to mind when I saw them.

    The stylin’ asymmetric design happened when I realized the squared-off handle end of the cart didn’t demand a rounded-off end of the seat. I cut off the raised tray rim before sketching the rounded outline using the rotted seat as a template; some of the sketch remains over on the right-front corner. A session with Mr Belt Sander put the remaining rim edges flush with the surface, no matter what the picture suggests.

    The tray being 2 mm thinner than the plywood, I tried printing the hinges in a different orientation with different built-in support:

    Rolling Cart Hinges - solid model - build
    Rolling Cart Hinges – solid model – build

    The perimeter threads pulled up far too much and, although fiddling with cooling would likely help, I think the original orientation was better:

    Rolling Cart Hinges - solid model - bottom
    Rolling Cart Hinges – solid model – bottom

    Given that the post-apocalypse breakfast will be served on similar trays, the seat should survive for quite a while in the garden. We think the sun will convert the brown surface into a bun warmer; a coat of white paint may be in its future.

    The original OpenSCAD code is still out there as a GitHub Gist.