Bafang BBS02 Programming Adapter: CP2102 Version

The last view before sticking the lid in place with hot melt glue:

Bafang BBS02 - CP2102 Programming Adapter
Bafang BBS02 – CP2102 Programming Adapter

The cable on the right goes to the motor controller through the display pigtail cable, sporting colors from a parallel universe.

A (possibly not counterfeit) CP2102 USB-to-serial adapter allows a slightly smaller case than one with the known-fake FTDI adapter and added some identification:

Bafang BBS02 - CP2102 Programming Adapter - case solid model
Bafang BBS02 – CP2102 Programming Adapter – case solid model

It splits along the midline for printing, of course.

The OpenSCAD source code replaces the previous version:

// Programming cable case

ProgCavity = [60.0,18.0,7.0];
ProgBlock = [70.0,24.0,13.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);

        translate([0,0,ProgBlock.z/2 + ProgCavity.z/2 - EmbossDepth])
            cube(ProgCavity,center=true);
        translate([0,0,-(ProgBlock.z/2 + ProgCavity.z/2 - EmbossDepth)])
            cube(ProgCavity,center=true);

    }

    translate([0,4,ProgBlock.z/2 - EmbossDepth])
        linear_extrude(height=EmbossDepth)
            text(text="Bafang BBS02",
                 size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold",
                 halign="center",valign="center");

    translate([0,-4,ProgBlock.z/2 - EmbossDepth])
        linear_extrude(height=EmbossDepth)
            text(text="Programmer",
                 size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold",
                 halign="center",valign="center");

    translate([0,4,-ProgBlock.z/2])
        linear_extrude(height=EmbossDepth)
            mirror([1,0])
                text(text="Ed Nisley",
                    size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold",
                    halign="center",valign="center");
    translate([0,-4,-ProgBlock.z/2])
        linear_extrude(height=EmbossDepth)
            mirror([1,0])
                text(text="softsolder.com",
                    size=5,spacing=1.00,font="Bitstream Vera Sans:style=Bold",
                    halign="center",valign="center");

}

// 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")
            ProgrammerCase();
        else
            translate([0,0,ProgBlock.z/2])
                ProgrammerCase();
    }
}

// .. snippage ..

        translate([0,2*Block.x/2 * gap,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");
        }

My friend rides about the same way we do, except from a much higher perch, so I’ll start her off with a configuration similar to the one we settled on for Mary’s Tour Easy.

Garden Sprayer Pivot Repair

A winning entry in the “The Bigger the Blob, the Better the Job” category:

Garden Sprayer - pivot repair
Garden Sprayer – pivot repair

Buried under the epoxy is the flimsy tab with the pivot around which the handle moves. Any sideways force will did snap the tab off flush with the body. I had previously repaired it with solvent adhesive, so something more substantial seemed appropriate.

A closer look shows the edges of the brass flange I formed around the tab to absorb the stress:

Garden Sprayer - pivot repair - detail
Garden Sprayer – pivot repair – detail

It’s pretty much fully depreciated, but if I don’t use the epoxy it will go bad on the shelf, so …

Bafang BBS02: Speed Sensor Nut Reshaping

A Bafang BBS02 (for a friend’s upright bike) arrived with a deformed speed sensor nut:

Bafang BBS02 - Deformed speed sensor nut - end view
Bafang BBS02 – Deformed speed sensor nut – end view

It traveled halfway around the planet while trapped underneath the motor and, if it rode in the top layer or two of containers, the combination of pressure and heat would be irresistible.

The plastic was stiff and I couldn’t force the nut over the connector using as much force as seemed reasonable:

Bafang BBS02 - Deformed speed sensor nut - test assembly
Bafang BBS02 – Deformed speed sensor nut – test assembly

On the upside, the nut just compresses the silicone washer between the connector and the sensor to make a waterproof joint, so it need not have perfect threads or a uniform shape. Once the nut is in place, it will likely never be removed and should never bother anyone else.

Being unwilling to apply a hot-air gun near the cable, I decided to try slowly cold-forming the nut inside a mold:

Sensor Nut mold - solid model
Sensor Nut mold – solid model

The gap isn’t a kerf: the two halves meet to form a cylindrical pocket. The smaller holes fit a pair of brass tubes keeping the halves lined up while I arrange things:

Bafang BBS02 - Deformed speed sensor nut - clamp detail
Bafang BBS02 – Deformed speed sensor nut – clamp detail

A pair of swivel-pad clamps apply the pressure:

Bafang BBS02 - Deformed speed sensor nut - compression clamp
Bafang BBS02 – Deformed speed sensor nut – compression clamp

A few days of squashing made it round-er, whereupon I applied the clamp directly against the remaining high point with the other side cradled in the mold. It still doesn’t slide over the connector body, but I’m not in a rush.

Bafang tech support generously sent a speed sensor extension cable from which I can extract a good nut, which will require cutting and splicing the cable from the motor.

I’m still hoping gentle suasion will prevail.

The OpenSCAD source code tucks into the overall file producing various useful bits:

// Mold to reshape speed sensor nut

SensorNut = [0,14.4,13.0];
SensorMold = [SensorNut[OD] + 2*WallThick,SensorNut[OD] + 2*WallThick,SensorNut[LENGTH] + WallThick];
MoldSides = 20;
RodOD = 1.6;

module NutMoldBlock() {

    difference() {

        translate([0,0,SensorMold.z/2])
            cube(SensorMold,center=true);

        translate([0,0,WallThick])
            rotate(180/MoldSides)
                PolyCyl(SensorNut[OD],2*SensorNut[LENGTH],MoldSides);
        translate([0,0,-Protrusion])
            rotate(180/8)
                PolyCyl(SpeedOD,2*SensorMold.z,8);

        for (i=[-1,1])
            translate([i*(SensorMold.x/2 - WallThick/2),SensorMold.y,SensorMold.z/2])
                rotate([90,0,0])
                    PolyCyl(RodOD,2*SensorMold.y,6);
    }
}

module NutMold() {
    gap = 1.0;

    for (j=[-1,1])
        translate([0,j*gap,0])
            intersection() {
                translate([0,j*SensorMold.y,0])
                    cube(2*SensorMold,center=true);
                NutMoldBlock();
            }
}

… snippage …

if (Layout == "NutMold")
    NutMold();

I haven’t worked on a safety bike in years!

Dripworks Mainline Pipe Clamp

This is laid in against a need I hope never occurs:

Dripworks 0.75 inch pipe clamp
Dripworks 0.75 inch pipe clamp

It’s intended to clamp around one of the Dripworks mainline pipes carrying water from the pressure regulator to the driplines in the raised beds, should an errant shovel or fork find the pipe.

It descends from a long line of soaker hose clamps, with a 25 mm ID allowing for a silicone tape wrap as a water barrier.

The solid model has no surprises:

Dripworks Mainline Clamp - build view
Dripworks Mainline Clamp – build view

The OpenSCAD source code as a GitHub Gist:

// Dripworks 3/4 inch mainline clamp
// Ed Nisley KE4ZNU 2021-06
Layout = "Build"; // [Hose,Block,Show,Build]
HoseOD = 25.0;
TestFit = false; // true to build test fit slice from center
//- 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;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
ID = 0;
OD = 1;
LENGTH = 2;
//----------
// Dimensions
// Hose lies along X axis
Hose = [200,HoseOD,HoseOD]; // X = longer than anything else
NumScrews = 2; // screws along each side of cable
WallThick = 3.0; // Thinnest printed wall
PlateThick = 1.5; // Stiffening plate thickness
// 8-32 stainless screws
Screw = [4.1,8.0,50.0]; // OD = head LENGTH = thread length
Washer = [4.4,9.5,1.0];
Nut = [4.1,9.7,3.3];
Block = [30.0,Hose.y + 2*Washer[OD],HoseOD + 2*WallThick]; // overall splice block size
echo(str("Block: ",Block));
ScrewMinLength = Block.z + 2*PlateThick + 2*Washer.z + Nut.z; // minimum screw length
echo(str("Screw min length: ",ScrewMinLength));
Kerf = 1.0; // cut through middle to apply compression
CornerRadius = Washer[OD]/2;
ScrewOC = [(Block.x - 2*CornerRadius) / (NumScrews - 1),
Block.y - 2*CornerRadius,
2*Block.z // ensure complete holes
];
echo(str("Screw OC: x=",ScrewOC.x," y=",ScrewOC.y));
//----------------------
// 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(d=(FixDia + HoleWindage),h=Height,$fn=Sides);
}
// Hose shape
// This includes magic numbers measured from reality
module HoseProfile() {
NumSides = 12*4;
rotate([0,-90,0])
translate([0,0,-Hose.x/2])
resize([Hose.z,Hose.y,0])
cylinder(d=Hose.z,h=Hose.x,$fn=NumSides);
}
// Outside shape of splice Block
// Z centered on hose rim circles, not overall thickness through center ridge
module SpliceBlock() {
difference() {
hull()
for (i=[-1,1], j=[-1,1]) // rounded block
translate([i*(Block.x/2 - CornerRadius),j*(Block.y/2 - CornerRadius),-Block.z/2])
cylinder(r=CornerRadius,h=Block.z,$fn=4*8);
for (i = [0:NumScrews - 1], j=[-1,1]) // screw holes
translate([-(Block.x/2 - CornerRadius) + i*ScrewOC.x,
j*ScrewOC.y/2,
-(Block.z/2 + Protrusion)])
PolyCyl(Screw[ID],Block.z + 2*Protrusion,6);
cube([2*Block.x,2*Block.y,Kerf],center=true); // slice through center
}
}
// Splice block less hose
module ShapedBlock() {
difference() {
SpliceBlock();
HoseProfile();
}
}
//----------
// Build them
if (Layout == "Hose")
HoseProfile();
if (Layout == "Block")
SpliceBlock();
if (Layout == "Show") {
difference() {
SpliceBlock();
HoseProfile();
}
color("Green",0.25)
HoseProfile();
}
if (Layout == "Build") {
SliceOffset = TestFit && !(NumScrews % 2) ? ScrewOC.x/2 : 0;
intersection() {
translate([SliceOffset,0,Block.z/4])
if (TestFit)
cube([ScrewOC.x/2,4*Block.y,Block.z/2],center=true);
else
cube([4*Block.x,4*Block.y,Block.z/2],center=true);
union() {
translate([0,0.6*Block.y,Block.z/2])
ShapedBlock();
translate([0,-0.6*Block.y,Block.z/2])
rotate([0,180,0])
ShapedBlock();
}
}
}

Microscope Stage Positioner: Rigid MakerBeam Edition

Rebuilding the XYZ stage positioner with MakerBeam aluminum struts, but without the steel brackets, produce a much more rigid result:

Microscope Stage Positioner - rigid Makerbeam
Microscope Stage Positioner – rigid Makerbeam

This requires drilling holes through the extrusions:

Microscope Stage Positioner - Makerbeam drilling
Microscope Stage Positioner – Makerbeam drilling

Running the center drill down until it just nicks the sides produces enough of a pilot hole through the center section to capture the 3 mm drill. If I had to drill enough holes to make a fixture worthwhile, I could probably eliminate the divots.

Two more holes + epoxied M3 brass inserts attached the 60 mm beam directly to the Z Axis stage, thereby eliminating the vertical beam and a steel bracket:

Microscope Stage Positioner - Makerbeam joints
Microscope Stage Positioner – Makerbeam joints

The M3 SHCS attaching the 100 mm beam goes through both beams. I think you could get the same result with a Tee Nut or a 12 mm Square Head bolt, should you have those lying around and don’t want to drill another hole. The Corner Cube screwed into both beams prevents rotation and helps ensure perpendicularity.

The Y stage now attaches directly to the beam, rather than through a pair of Corner Cubes, because I realized I wasn’t ever going to adjust its position.

The Z Axis stage stands on the plastic plate through a hellish mixture of metric and USA-ian screws. Basically, the 6-40 screws into the stage were long enough, the 6-32 screws through the plate fit the existing holes, and M3 screws are for MakerBeam:

Microscope Stage Positioner - Z Axis base
Microscope Stage Positioner – Z Axis base

To my utter astonishment, the threads in the end of the vertical beam had the proper alignment to let a Square Head bolt snug the beam against the 40 mm beam on the plate. As a result, the L Bracket just prevents the vertical beam from turning on the screw and the combination is as rigid as you (well, I) could want.

The 40 mm beam has two spurious holes, because I thought I could avoid drilling another hole in the baseplate. Nobody will ever notice.

After squaring and tightening everything, the 100 mm beam along the Y Axis is now horizontal within 0.2 mm and the X Axis is horizontal to better than I can measure.

It’s definitely Good Enough™ for me:

Microscope Stage Positioner - in use
Microscope Stage Positioner – in use

Remember, nothing exceeds like excess …

Microscope Stage Positioner: MakerBeam Rebuild MVP

Over the course of half a decade (!), the 3D printed arm on the XYZ positioner I use with the stereo zoom microscope sagged:

Microscope Stage Positioner - PETG creep angle
Microscope Stage Positioner – PETG creep angle

It’s about what you’d expect from a plastic beam carrying a big lump of brass and steel:

Microscope Stage Positioner
Microscope Stage Positioner

The near side of that arm (the -Y end) drooped about 5 mm below than the side nearest the Z axis slide, so it was time for an update.

Having some MakerBeam ready to hand, this didn’t take long:

Microscope Stage Positioner - Makerbeam overview
Microscope Stage Positioner – Makerbeam overview

Protip: before dismantling a fitted slide, mark one end so you know how to put it back together. Bonus points for taking a picture:

Microscope Stage Positioner - slide marking
Microscope Stage Positioner – slide marking

Double bonus points for writing a blog post.

Rather than fight with the existing fine-pitch USA-ian screws, I drilled out their threaded holes:

Microscope Stage Positioner - Y slide drilling
Microscope Stage Positioner – Y slide drilling

And epoxied 3 mm brass inserts in their place:

Microscope Stage Positioner - Y slide M3 inserts
Microscope Stage Positioner – Y slide M3 inserts

Those holes match up with a pair of corner cubes normally appearing on the end of the beams:

Microscope Stage Positioner - BHCS mods for Makerbeam
Microscope Stage Positioner – BHCS mods for Makerbeam

It turns out M3 button head cap screws will slide into the beams if you file the slightest angle on opposite sides of the button, although a small bag of tiny tee nuts should arrive in a while.

Then a variety of brackets spliced everything together:

Microscope Stage Positioner - Makerbeam detail
Microscope Stage Positioner – Makerbeam detail

Although it looks strictly from industrial, it actually wasn’t much better than the plastic edition and, in fact, the beam supporting the XY slides sagged about the same 5 mm. The plastic upright post also contributed a bit of wobble.

It turns out that the extruded aluminum beams have plenty of longitudinal and torsional stiffness, but all those flat steel fittings don’t.

There’s a way to work with the beam strengths, rather than against them, but that’s a story for another day …

Bicycle Helmet Mirror: Stalk Repair

The mirror on my bike helmet snagged on a mesh fence while walking the bike to Mary’s garden:

Helmet Mirror - bent stalk
Helmet Mirror – bent stalk

One of the good things about building your own stuff is that you have all the parts when something breaks:

Helmet Mirror - damaged parts
Helmet Mirror – damaged parts

The decorative M2 screw and insert pulled out of the ball. The rim of the nail set punch (intruding from the top) just barely caught the edge of the stub inside the ball, so a few taps could extract it. A Dremel cutoff wheel peeled the crumpled end off the stalk.

Reassembly proceeded without incident:

Helmet Mirror - installed
Helmet Mirror – installed

The bizarrely blurred mirror over on the left comes from the Pixel phone camera app deciding this was a Portrait, applying a background blur, and running into trouble with those hard edges in the foreground. The camera app has a distinct Portrait mode that, perhaps, I inadvertently engaged while fumbling around.