Astable Multivibrator vs. Charged NP-BX1 Lithium Battery

Hitching a charged, albeit worn, NP-BX1 lithium battery to the astable multivibrator produces a blinding flash:

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

The current pulse shows the wearable LED really takes a beating:

Astable - NP-BX1 4V - 100mA-div
Astable – NP-BX1 4V – 100mA-div

The current trace is at 100 mA/div: the pulse starts at 400 mA, which seems excessive even to me, and tapers down to 200 mA. It’s still an order of magnitude too high at the end of the pulse.

On the other paw, maybe a 14% duty cycle helps:

Astable - NP-BX1 4V - base V - 100mA-div
Astable – NP-BX1 4V – base V – 100mA-div

The top trace shows the base drive voltage dropping slightly, although I suspect the poor little transistor can’t take the strain.

The LED really does need a ballast resistor …

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;
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() {
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])
union() {
PolyCyl(PinTip[OD],PinShank[LENGTH] + PinTip[LENGTH],6);
PolyCyl(PinShank[ID],PinShank[LENGTH] + Protrusion,6); // slight extension for clean cuts
// 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([-(PinShank[LENGTH] + OverTravel) + PinChannel/2,
(Contacts[1].y + Contacts[0].y)/2,
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)])
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)])
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),
cube([CaseSize.x,(CaseSize.y + 2*Protrusion),(TopThick + Protrusion)]);
translate([(CaseOffset.x - Protrusion), // battery insertion allowance
(CaseOffset.y - Protrusion),
cube([(CaseSize.x + 2*Protrusion),(CaseSize.y + 2*Protrusion),(TopThick + Protrusion)]);
translate([(Battery.x - Protrusion), // remove thumb notch
(CaseSize.y/2 + CaseOffset.y),
h=(WallThick + GuideRadius + 2*Protrusion),
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]),
// Lid position offset to match case
module Lid() {
translate([-LidSize.x/2 + LidOffset.x + LidOverhang,LidSize.y/2 + LidOffset.y,0])
difference() {
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
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")
if (Layout == "Lid")
if (Layout == "Pins") {
if (Layout == "Show") { // reveal pin assembly
difference() {
translate([(CaseOffset.x - Protrusion),
cube([(-CaseOffset.x + Protrusion),
(CaseSize.z - Contacts[0].z + Protrusion)]);
translate([(CaseOffset.x - Protrusion),
(CaseOffset.y - Protrusion),
cube([(-CaseOffset.x + Protrusion),
Contacts[0].y + Protrusion - CaseOffset.y,
translate([0,0,Battery.z + Gap])
if (Layout == "Build") {
translate([-(CaseSize.x/2 + CaseOffset.x),-(CaseOffset.y - BuildOffset),BaseThick])
translate([CaseSize.y/2,(CaseOffset.x/2 - BuildOffset),0])
if (Layout == "Fit") {
translate([0,0,(Battery.z + Gap)])

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.

Kindle Fire Picture Frame: Copying the Pictures

Being a bear of unbearable consistency, I save edited picture files with a description following the original camera-assigned sequence number:

IMG_20181108_190041 - Kindle Fire Picture Frame - Another Test Image.jpg

Yup, spaces and all.

Kindle Fire Picture Frame - Another Test Image
Kindle Fire Picture Frame – Another Test Image

I store my general-interest pix chronologically by year, in subdirectories for interesting categories, so copying all the edited (a.k.a. “interesting”) pictures to the Kindle Fire becomes a one-liner:

cd /mnt/bulkdata/Cameras
find 20?? -iname \*\ \*jpg -print0 | xargs -0 cp --parents -t /mnt/part/Pictures

The --parents parameter tells cp to recreate the directory structure holding the picture in the target directory, thereby keeping the pix neatly sorted in their places, rather than creating one heap o’ pictures.

Come to find out I’ve edited slightly over 7 k general-interest pictures in the eighteen years I’ve been using digital cameras, of maybe 27 k total pictures. Call it a 25% hit ratio; obviously I’m not nearly fussy enough.

Then there’s another 16 k project-related pictures, of which 10 k were edited into something useful. With an emphasis on utility, rather than aesthetics, a 60% hit ratio seems OK.

Which works out to half a dozen pictures a day, every day, for eighteen years. I loves me some good digital camera action!

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.