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

  • Sticky Trap Screen Frames

    Sticky Trap Screen Frames

    The objective being to reduce the number of onion maggots in Mary’s Vassar Farm plot without chemical agents, I conjured sticky trap screen frames from the vasty digital deep:

    Sticky Trap - first production run
    Sticky Trap – first production run

    Each one contains half a sheet of yellow sticky plastic, which is easy enough to cut before peeling off the protective covering sheets. The cage is half-inch galvanized hardware cloth snipped with hardened diagonal cutters. A bead of acrylic adhesive around the base holds the cage in place

    Although you can deploy sticky sheets without cages, they tend to attract and affix beneficial critters: butterflies, small birds, furry critters, toads, gardeners, and the like. We don’t know how effective the cages will be, but they seemed better than nothing.

    They mount on ski poles cut in half:

    Sticky Trap - ski pole installed
    Sticky Trap – ski pole installed

    And on fence posts around the perimeter:

    Sticky Trap - angle bracket installed
    Sticky Trap – angle bracket installed

    To my untrained eye, some of those doomed critters are, indeed, onion maggot flies. The rest seem to be gnats and other nuisances, so IMO we’re applying population pressure in the right direction.

    Each base-and-cap frame takes about three hours to print, so I did them one at a time over the course of a few days while applying continuous product improvement.

    The sheets rest on small V blocks intended to keep them centered within the cage:

    Sticky Sheet Cage - angle bracket - solid model
    Sticky Sheet Cage – angle bracket – solid model

    The ski pole attachment must build with the cap on top, but it bridges well enough for the purpose:

    Sticky Sheet Cage - ski pole - solid model
    Sticky Sheet Cage – ski pole – solid model

    The overhanging hooks on the blocks (just barely) engage the grid to keep the lid in place, while remaining short enough to not droop too badly. You could probably delete the hooks from the bottom plate, but they align the cage while the adhesive cures.

    The sheets tend to bend in the middle, so I’ll stick a thin slat or two vertically to keep them straight.

    The OpenSCAD source code as a GitHub Gist:

    // Sticky Sheet Cage
    // Ed Nisley KE4ZNU May 2021
    Layout = "Build"; // [Build, Show, Cap, Attachment]
    Bracket = "Ski"; // [Angle, Ski, Post]
    //- Extrusion parameters must match reality!
    /* [Hidden] */
    ThreadThick = 0.25;
    ThreadWidth = 0.40;
    HoleWindage = 0.2;
    Protrusion = 0.1; // make holes end cleanly
    inch = 25.4;
    ID = 0;
    OD = 1;
    LENGTH = 2;
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    //———————-
    // Dimensions
    Sheet = [1,100,150]; // sticky sheet
    Grid = 0.5*inch;
    Cage = [2*Grid + 5.0, 8*Grid + 5.0, 12*Grid + 2.0]; // grid wire cage bent around sheet
    CageRad = 2.5; // wire bending radius
    CageThick = 2.0; // grid thickness
    WallThick = 3.0; // min wall and bottom thickness
    Recess = 5.0; // inset to capture cage edge
    Plate = [Cage.x,Cage.y,Recess] + [2*WallThick,2*WallThick,WallThick];
    PlateRad = 5.0;
    SkiPole = [20.0,20.0 + 2*WallThick,50];
    AnglePlate = [30,30,50];
    ScrewClear = 5.0;
    BuildGap = 5.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);
    }
    //———————-
    // Pieces
    module Cap() {
    union() {
    difference() {
    hull()
    for (i=[-1,1], j=[-1,1])
    translate([i*(Plate.x/2 – PlateRad),j*(Plate.y/2 – PlateRad),0])
    cylinder(r=PlateRad,h=Plate.z,$fn=12);
    translate([0,0,Plate.z – Recess])
    hull()
    for (i=[-1,1], j=[-1,1])
    translate([i*(Cage.x/2 – CageRad),j*(Cage.y/2 – CageRad),0])
    cylinder(r=CageRad,h=Plate.z,$fn=12);
    }
    difference() {
    Strut = Cage.x – 2*CageThick;
    Latch = [Cage.x,WallThick,0.75*Plate.z];
    union() {
    for (j=[-1,1])
    translate([0,j*2.5*Grid,Plate.z])
    cube([Strut,WallThick,2*Plate.z],center=true);
    for (j=[-1,1])
    translate([0,j*2.5*Grid,2*Plate.z – Latch.z/2])
    cube(Latch,center=true);
    }
    translate([0,0,2*Plate.z + (Cage.z – Sheet.z)/4])
    rotate([0,45,0])
    cube([Strut/sqrt(2),Plate.y,Strut/sqrt(2)],center=true);
    }
    }
    }
    module Attachment() {
    if (Bracket == "Angle") {
    translate([0,Plate.y/2,0])
    rotate(45)
    difference() {
    union() {
    cube(AnglePlate,center=false);
    rotate(-45)
    translate([0,WallThick,Plate.z/2])
    cube([Plate.x – 2*PlateRad,4*WallThick,Plate.z],center=true);
    }
    translate([WallThick,WallThick,-Protrusion])
    cube(AnglePlate + [0,0,2*Protrusion],center=false);
    translate([AnglePlate.x/2,-Protrusion,2*AnglePlate.z/3])
    rotate([-90,0,0])
    PolyCyl(ScrewClear,2*AnglePlate.x,6);
    translate([-Protrusion,AnglePlate.x/2,1*AnglePlate.z/3])
    rotate([90,0,90])
    PolyCyl(ScrewClear,2*AnglePlate.x,6);
    }
    }
    else if (Bracket == "Ski") {
    translate([0,Plate.y/2 + SkiPole[OD]/2,0])
    difference() {
    union() {
    PolyCyl(SkiPole[OD],SkiPole[LENGTH],24);
    translate([0,-3*WallThick,Plate.z/2])
    cube([Plate.x – 2*PlateRad,4*WallThick,Plate.z],center=true);
    }
    translate([0,0,-2*WallThick])
    PolyCyl(SkiPole[ID],SkiPole[LENGTH],24);
    }
    }
    }
    //———————-
    // Build it
    if (Layout == "Cap")
    Cap();
    if (Layout == "Attachment") {
    Attachment();
    }
    if (Layout == "Show") {
    translate([0,0,Sheet.z/2 + Plate.z])
    color("Yellow")
    cube(Sheet,center=true);
    Cap();
    Attachment();
    translate([0,0,Sheet.z + 2*Plate.z])
    rotate([180,0,0])
    Cap();
    }
    if (Layout == "Build") {
    translate([-(Plate.x/2 + BuildGap),0,0]) {
    Cap();
    Attachment();
    }
    translate([(Plate.x/2 + BuildGap),0,0])
    Cap();
    }
  • Bafang Brake Sensor Magnet Realignment

    Bafang Brake Sensor Magnet Realignment

    As mentioned earlier, the Bafang brake sensors on Mary’s Tour Easy require a magnet on the brake levers to activate the switches. They arrived with disk magnets that did not suit the levers, so I used neodymium “bar magnets”:

    Tour Easy Bafang BBS02 - brake sensor - installed
    Tour Easy Bafang BBS02 – brake sensor – installed

    That worked for a few rides, but the alignment turned out to be entirely too critical, because the magnetization is through the bar’s thin dimension, rather than along its length, making the field weakest in the direction of the switch.

    Magnetic field visualization film shows the field null along the thin edge of the bar:

    Neodymium bar magnet - edge field
    Neodymium bar magnet – edge field

    That’s a slightly shorter magnet from a different toothbrush head, cemented edgewise into a holder conjured from the vasty digital deep:

    Brake Magnet Mount - PrusaSlicer prevew
    Brake Magnet Mount – PrusaSlicer prevew

    The field is much more uniform on the flat side of the bar:

    Neodymium bar magnet - side field
    Neodymium bar magnet – side field

    Some double-sided foam tape snuggles the sensor and the magnet together on the brake lever:

    Bafang Brake Sensor - released detail
    Bafang Brake Sensor – released detail

    I coated the magnet with JB Plastic Bonder urethane adhesive in the hope of filling any gaps in its nickel coating caused while extricating it from the toothbrush head.

    The rusty screw head in the upper right positions the lever at the proper distance from the grip to suit Mary’s hand. An earlier version of the holder shows the alignment:

    Bafang Brake Sensor - released position
    Bafang Brake Sensor – released position

    The switch trips (opens) with the lever roughly parallel to the grip, again with the earlier holder:

    Bafang Brake Sensor - activated position
    Bafang Brake Sensor – activated position

    A detailed view of the gap with the lever at the tripped position:

    Bafang Brake Sensor - activated detail
    Bafang Brake Sensor – activated detail

    The levers have enough travel to prevent accidental trips due to light finger pressure, which turned out to be a problem with the original end-on alignment.

    The brake pads don’t quite touch the rim when the switch trips, so the motor has plenty of time to shut off before the brakes take effect. It also stops when the pedals stop turning, so we should not see any disagreement between motor and brakes as to the bike’s momentum.

    The wider base on the new mounts makes them much more stable on the levers, although I don’t like having them stick up so far. Mounting everything underneath the levers would look better, but any problems will be more obvious with everything in plain sight.

    I may affix the magnets directly to the levers with Plastic Bonder if the foam tape doesn’t live up to its reputation. Removing them would be more challenging; a shot with a small chisel should suffice.

  • Tour Easy: Another Rear Fender Bracket

    Tour Easy: Another Rear Fender Bracket

    All the work on Mary’s bike reminded me of the rear fender bracket I meant to install on mine, with more clearance for the strut stabilizing the under-seat packs:

    Tour Easy Rear Fender Bracket - long setback - solid model - show
    Tour Easy Rear Fender Bracket – long setback – solid model – show

    Rather than glue a PETG filament snippet into a screw, I turned a little Delrin plug:

    Tour Easy Rear Fender Bracket - screw insert
    Tour Easy Rear Fender Bracket – screw insert

    It’s ready for installation when I’m willing to put the bike up on the rack and pull the rear wheel:

    Tour Easy Rear Fender Bracket - screw detail
    Tour Easy Rear Fender Bracket – screw detail

    That’s actually the second iteration for the screw, as the first suffered a lethal encounter with the Greater Shopvac. I know exactly where it is, but I’m not going there …

  • Tour Easy: Bafang BBS02 Pedal Offset Fix

    Tour Easy: Bafang BBS02 Pedal Offset Fix

    For unknown reasons, the Bafang BBS02 motor puts the left pedal 15.5 mm closer to the frame than the right pedal:

    Bafang BBS02 dimensions
    Bafang BBS02 dimensions

    The diagram presents the motor assembly as seen from the bottom, lying on the ground looking upward with your feet forward around the front wheel.

    That much offset may be acceptable for some (upright?) bikes and some riders, but this seemed better for Mary:

    Tour Easy - Lekkie 160mm offset crank - installed
    Tour Easy – Lekkie 160mm offset crank – installed

    Lekkie Buzz Bars have a matching 15.5 mm offset in the left crank to center both pedals on the frame. She’s been pushing 165 mm cranks for long enough to know standard 170 mm cranks require too much leg travel, so that’s a 160 mm Lekkie crank.

    With cranks installed in the BBS02, measured from the frame tube to the inside of the crank at the pedal axis:

    • Bafang 170 mm: L 42, R 62
    • Shimano 105 triple 170 mm: L 46, R 67
    • Lekkie 160 mm: both sides 60

    For comparison, the Shimano 105 cranks on my Tour Easy measure 35 mm on both sides with an ordinary Shimano UM-BB72 bottom bracket cartridge, so the BBS02 + Lekkie cranks put each pedal 25-ish mm farther out. However,my pedals screw into 20 mm Kneesavers, putting them pretty close to the Lekkie spacing.

    We hope the additional space won’t make much difference to Mary; it’s certainly better than sitting offset to the right to match the pedals, as she’s found herself doing with both the Bafang and Shimano cranks on the BBS02. Her right shoe just barely tapped the crank, so we moved the cleat a few millimeters inboard and it’s all good again.

    The Cateye cadence sensor now has a rakish tilt to match the crank offset and looks scarily exposed. More riding is in order.

    The Lekkie cranks have a hollow cross-section that’s concave on the frame side, so the magnet sits on a simple riser to get it out where the sensor can experience it:

    Cateye Cadence Magnet mount - PS preview

    It’s held in place with good foam tape; the cable tie makes me feel better.

    The OpenSCAD code for the riser fits into the GitHub Gist:

    module CateyeMagnet() {
    
    OAL = 24.0;
    D1 = 14.0;
    D2 = 8.0;
    
        linear_extrude(height = 15.0)
            hull() {
                rotate(180/12)
                    circle(d=D1,$fn=12);
                translate([OAL - D1/2 - D2/2,0])
                    rotate(180/12)
                        circle(d=D2,$fn=12);
            }
    }
    
    … snippage …
    
        translate([0,-4*Block.x,0]) {
            rotate(-90)
                CateyeSensor();
            CateyeMagnet();
        }
    

    The build plate is getting crowded:

    Bafang Battery Mount - build view - cadence magnet
    Bafang Battery Mount – build view – cadence magnet

    In point of fact, that array pretty much fills the M2’s platform and would require over 11 hours of print time, which is just crazy talk. Have the slicer break it into separate parts, delete whatever you don’t want at the moment, print what’s left, and iterate until you have everything you need to finish the job.

  • Tour Easy: Bafang Mid-drive vs. Cateye Cadence Sensor

    Tour Easy: Bafang Mid-drive vs. Cateye Cadence Sensor

    For inscrutable reasons, the Bafang 500C display includes all stopped time in its average trip speed. While that is, in fact, the average speed over the entire trip, the Cateye cyclocomputers we’ve been using forever stop averaging after a few seconds at 0 mph.

    Bonus: Although the Bafang BBS02 motor knows the pedal cadence, it’s not part of the display.

    The Bafang BBS02 bottom bracket shaft put its pedal cranks much farther from the Tour Easy’s frame than the Shimano cranks, to the extent that the existing Cateye cadence sensor position just wasn’t going to work, so I printed a simple clip to fit over the motor’s “fixing plate”:

    Tour Easy Bafang BBS02 motor
    Tour Easy Bafang BBS02 motor

    It turns out putting a magnetic sensor immediately next to the winding end of a high-current three-phase motor isn’t the brightest idea I’ve ever had. The Cateye cadence display spent most of its time maxed out at 199 rpm, far faster than Mary can spin for, well, a single revolution.

    A somewhat more complex mount put the sensor roughly where it used to be:

    Cateye Cadence Sensor mount - installed
    Cateye Cadence Sensor mount – installed

    It looks precarious, but it spent nigh onto two decades there without incident, so we have precedent.

    Those are the original 165 mm Shimano cranks, because the 170 mm Bafung cranks threatened to lock out her knees. More on this in a while, as it’s a more complex issue than it may appear.

    The solid model looks about like you’d expect:

    Cateye Cadence Sensor mount - solid model
    Cateye Cadence Sensor mount – solid model

    The OpenSCAD code replaces the simple clip in the original GitHub Gist:

    // Cateye cadence sensor bracket
    
    LockRingDia = [44.0,46.0];
    LockRingLen = [4.0,6.5];
    LockRingOAD = LockRingDia[1] + 2*WallThick;
    LockRingOAL = LockRingLen[0] + LockRingLen[1];
    
    Notches = 16;
    SensorAngle = 3*360/Notches;
    SensorBase = 10.0;
    
    module Cateye() {
    
        difference() {
            union() {
                cylinder(d=LockRingOAD,h=LockRingOAL,$fn=Notches);
                translate([LockRingOAD/2 + LockRingOAL/2 - WallThick/2,0,LockRingOAL/2])
                    cube([LockRingOAL + WallThick,2*WallThick + Kerf,LockRingOAL],center=true);
          rotate(SensorAngle)
                    translate([LockRingOAD/2 + SensorBase - WallThick/2,0,LockRingOAL/2])
                        cube([2*SensorBase + WallThick,2*WallThick,LockRingOAL],center=true);
            }
            translate([0,0,LockRingLen[0]])
                PolyCyl(LockRingDia[1],LockRingOAL,Notches);
            translate([0,0,-Protrusion])
                PolyCyl(LockRingDia[0],2*LockRingOAL,Notches);
    
            translate([LockRingDia[0],0,0])
                cube([2*LockRingDia[0],Kerf,4*LockRingOAL],center=true);
            translate([LockRingOAD/2 + LockRingOAL/2,2*WallThick,LockRingOAL/2])
                rotate([90,0,0])
                    PolyCyl(3.0,4*WallThick,6);
    
            rotate(SensorAngle)
                translate([LockRingOAD/2 + 2*SensorBase - SensorBase/2,2*WallThick,LockRingOAL/2])
                    rotate([90,0,0])
                        PolyCyl(3.0,4*WallThick,6);
        }
    
    }
    
  • Tour Easy: Asymmetric Handlebar Grips

    Tour Easy: Asymmetric Handlebar Grips

    Installing the Bafang BBS02 motor on Mary’s Tour Easy replaced the triple chainring, so I removed the front derailleur and SRAM grip shifter. This produced enough room for the thumb throttle and a full-length handgrip on the left side:

    Tour Easy grips - left installed
    Tour Easy grips – left installed

    The round button is the PTT switch for the HT.

    The right handlebar still has the rear shifter, so it requires a shorter grip:

    Tour Easy grips - right installed
    Tour Easy grips – right installed

    Although it may be possible to buy such a grip and, thereby, get a backup pair of mismatched grips, it seemed easier straightforward to just shorten the grip to the correct length and be done with it.

    Saw off a convenient length of aluminum rod:

    Tour Easy grips - mandrel sawing
    Tour Easy grips – mandrel sawing

    Although I actually used a steady rest to produce this, it happened during a remote Squidwrench meeting and I have no proof:

    Tour Easy grips - lathe mandrel
    Tour Easy grips – lathe mandrel

    The 22.2 mm = 7/8 inch end matches the more-or-less standard handlebar diameter, so the grip clamp can get a good hold:

    Tour Easy grips - right peeled
    Tour Easy grips – right peeled

    A live center supports the right end of the grip.

    The red coating seems to be gooey silicone rubber molded atop a PVC tube. Rather than (try to) use a lathe bit to cut through the silicone, I cut two slits with a utility knife and the spindle turning slowly in reverse, then peeled off the rubber between the slits.

    With the silicone out of the way, an ordinary cutoff tool made short work of the PVC:

    Tour Easy grips - right trimming
    Tour Easy grips – right trimming

    That was a cleanup pass with the utility knife, as the cutoff tool left a slight flange around part of the circumference. If I had the courage of my convictions, I could probably have cut the PVC with the knife.

    Chamfer the end of the cut, slide it on the handlebar, tighten the clamp, and it’s all good.

    The alert reader will note the clamp should go on first, but that would produce an inconvenient lump against the right shifter. Sliding them on backwards puts the clamp at the end of the handlebar and works out better in this admittedly unusual situation.

  • Bafang USB Programming Adapter

    Bafang USB Programming Adapter

    Changing (“programming”) the Bafang BBS02 motor controller parameters requires a USB-to-serial adapter with a connector matching the end of the cable from the motor to the display. While you can buy such things directly from the usual randomly named Amazon sellers, I happen to have a wide variety of bare adapter boards, so I just bought a display extender cable and cut it in half to get the connector; you can apparently buy pigtailed connectors (for more than the price of an extender) if you dislike cutting cables in half.

    Various documents provide versions of the canonical illustration of the motor end of the display cable, as ripped from Penoff’s original documentation:

    Bafang BBS02 display cable pinout
    Bafang BBS02 display cable pinout

    The pin colors correspond to the wiring inside the motor cable, but the extender uses different colors, because nobody will ever know:

    Bafang programmer - wire colors
    Bafang programmer – wire colors

    A bit of work with a continuity meter gave the pinout:

    Bafang BBS02 display extender - wire colors
    Bafang BBS02 display extender – wire colors

    Don’t trust stuff you read on the Intertubes: make your own measurements and draw your own diagrams!

    You want the cable end carrying the sockets to mate with the pins on the motor cable (coming in from the left):

    Bafang programmer - cable ends
    Bafang programmer – cable ends

    Soldering the cable to a known-counterfeit FTDI USB adapter went swimmingly:

    Bafang programmer - USB adapter wiring
    Bafang programmer – USB adapter wiring

    Note that the yellow-blue connection carries the full 48 V from the battery and may or may not have any current limiting / fusing / protection, so be a little more careful than usual in your wiring layout.

    The red jumper from DTR to CTS, shown in all the Amazon and eBay listIngs, turns out to be unnecessary.

    A quick and dirty case (eventually held together with generous hot-melt glue blobs) protects the PCB and armors the cables:

    Bafang USB-serial adapter interior
    Bafang USB-serial adapter interior

    The solid model over on the right looks about like you’d expect:

    Bafang Battery Mount - complete build view
    Bafang Battery Mount – complete build view

    Most of the instructions will tell you to hot-plug the cable to the motor with the battery connected, which strikes me as foolhardy; not all of those pins make contact in the right order, which means you will slap 50-odd volts across the wrong parts of the circuitry.

    Instead:

    • Disconnect the battery
    • Unplug the display
    • Plug the adapter cable into the motor connector
    • Plug the USB cable into the Token Windows Laptop
    • Reconnect the battery
    • Fire up the “programming” routine
    • Send the new configuration to the motor controller
    • Disconnect the battery
    • Unplug the adapter cable
    • Reconnect the display cable
    • Reconnect the battery

    Makes more sense to me, even if it’s more tedious.

    Tuck this OpenSCAD source code for the case into the original program that produces the battery mounts:

    Layout = "Build";               // [Frame,Block,Show,Build,Bushing,Cateye,Case]
    
    … snippage …
    
    // Programming cable case
    
    ProgCavity = [70.0,19.0,10.0];
    ProgBlock = [85.0,25.0,15.0];
    ProgCableOD = 4.0;
    
    module ProgrammerCase() {
    
        difference() {
            hull() {
                for (i=[-1,1], j=[-1,1])
                    translate([i*(ProgBlock.x/2 - CornerRadius),j*i*(ProgBlock.y/2 - CornerRadius),-ProgBlock.z/2])
                        cylinder(r=CornerRadius,h=ProgBlock.z,$fn=12);
                }
            translate([-ProgBlock.x,0,0])
                rotate([0,90,0])
                    PolyCyl(ProgCableOD,3*ProgBlock.x,6);
            cube(ProgCavity,center=true);
        }
    }
    
    // Half case sections for printing
    
    module HalfCase(Section = "Upper") {
    
        intersection() {
           translate([0,0,ProgBlock.z/4])
                cube([2*ProgBlock.x,2*ProgBlock.y,ProgBlock.z/2],center=true);
            if (Section == "Upper")
                translate([0,0,-Kerf/2])
                    ProgrammerCase();
            else
                translate([0,0,ProgBlock.z/2])
                    ProgrammerCase();
        }
    }
    
    … snippage …
    
    // tuck this into the Build conditional
    
        translate([0,3*Block.x,0]) {
    
            translate([gap*ProgBlock.x/2,0,ProgBlock.z/2])
                rotate([180,0,0])
                    HalfCase("Upper");
            translate([-gap*ProgBlock.x/2,0,0])
                HalfCase("Lower");