The Sony HDR-AS30V “action camera” uses NP-BX1 lithium batteries (3.7 V @ 1.24 A·h = 4.6 W·h) that are, of course, a completely different size and shape than any other lithium battery on the planet.
So.
Tweaking a few dimensions in the Canon NB-6L source code, tinkering with the layout of the contact pins, and shazam Yet Another 3D Printed Battery Test Fixture:

It builds nicely, although the contact pin tunnels are a bit too close to the top of the case:

After reaming out the contact pin holes to the proper diameters & depths, then gluing the plugs in place, it works just as you’d expect:

It’s worth noting that the Wasabi charger accepts the batteries upside-down, with the conspicuous chevron against the charger body. It’s definitely not the way all the other chargers work. The keying recesses on the battery (corresponding to the blocks in the solid model) lie along the bottom edge of the contact surface, so flipping the battery over means they’ll hold it in place, but … oh, well.
That grotty Powerpole connector last saw use in some random benchtop lashup. At some point I’ll be forced to start making more of those.
The OpenSCAD source code:
// Holder for Sony NP-BX1 Li-Ion battery // Ed Nisley KE4ZNU January 2013 include <MCAD/boxes.scad> // Layout options Layout = "Show"; // Show Build Fit Case Lid Pins Plugs AlignPins //- Extrusion parameters - must match reality! // Print with +2 shells and 3 solid layers ThreadThick = 0.20; ThreadWidth = 0.40; 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 = 8.0; // separation for Fit parts //- Battery dimensions - rationalized from several samples // Coordinate origin at battery corner by contact plates on bottom surface BatteryLength = 43.0; BatteryWidth = 30.0; BatteryThick = 9.5; ContactWidth = 2.90; ContactLength = 4.30; ContactRecess = 0.90; ContactOC = 10.0; // center-to-center across contact face ContactOffset = 6.20; // offset from battery edge ContactHeight = 6.30; // offset from battery bottom plane AlignThick = 2.75; // alignment recesses on contact face AlignDepth = 1.70; // into face AlignWidth1 = 3.70; // across face at contacts AlignWidth2 = 3.60; // ... other edge //- Pin dimensions PinTipDia = 1.6; PinTipLength = 10.0; PinTaperLength = 2.3; PinShaftDia = 2.4; PinShaftLength = 6.8; PinFerruleDia = 3.1; PinFerruleLength = 2.0; PinLength = PinTipLength + PinTaperLength + PinShaftLength + PinFerruleLength; ExtendRelax = 1.5 + ContactRecess; // pin extension when no battery is present ExtendOvertravel = 1.0; // ... beyond engaged position //- Spring dimensions SpringDia = 3.1; // coil OD SpringMax = 9.3; SpringLength = SpringMax - 0.5; // slightly compressed SpringMin = 4.5; SpringPlugOD = IntegerMultiple(5.0,ThreadWidth); // plug retaining the spring SpringPlugID = 2.0; SpringPlugLength = IntegerMultiple(4.0,ThreadWidth); SpringPlugSides = 3*4; SpringTravel = ExtendRelax + ExtendOvertravel; //- 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 CaseLength = SpringPlugLength + SpringLength + PinLength - ExtendRelax + BatteryLength + GuideRadius + WallThick; CaseWidth = 2*WallThick + 2*GuideRadius + BatteryWidth; CaseThick = BaseThick + BatteryThick + TopThick; AlignPinOD = 1.75; // lid alignment pins - filament snippets AlignPinLength = 5.0; AlignPinInset = 7.0; AlignPinOffset = -3.75; // from centerline - choose to miss contact pins //- XY origin at front left battery corner, Z on platform below that CaseLengthOffset = -(SpringPlugLength + SpringLength + PinLength - ExtendRelax); CaseWidthOffset = -(WallThick + GuideRadius); CaseThickOffset = BaseThick; LidLength = ExtendRelax - CaseLengthOffset; echo(str("Contact pin tip dia: ",PinTipDia)); echo(str("Drill depth to taper end: ", (SpringPlugLength + SpringLength + PinFerruleLength + PinShaftLength + PinTaperLength), " -- Dia: ",PinShaftDia)); echo(str(" to ferrule end: ", (SpringPlugLength + SpringLength + PinFerruleLength), " -- Dia: ",PinFerruleDia)); echo(str(" to plug end: ",SpringPlugLength, " -- Dia: ",SpringPlugOD)); //---------------------- // 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); } module ShowPegGrid(Space = 10.0,Size = 1.0) { Range = floor(50 / Space); for (x=[-Range:Range]) for (y=[-Range:Range]) translate([x*Space,y*Space,Size/2]) %cube(Size,center=true); } //------------------- //-- Guides for tighter friction fit module Guides() { translate([GuideOffset,-GuideRadius,CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); translate([GuideOffset,(BatteryWidth + GuideRadius),CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); translate([(BatteryLength - GuideOffset),-GuideRadius,CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); translate([(BatteryLength - GuideOffset),(BatteryWidth + GuideRadius),CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); translate([(BatteryLength + GuideRadius),GuideOffset/2,CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); translate([(BatteryLength + GuideRadius),(BatteryWidth - GuideOffset/2),CaseThickOffset]) PolyCyl(2*GuideRadius,(BatteryThick - Protrusion),4); } //-- Contact pins (holes therefore) module PinShape() { union() { cylinder(r=(PinTipDia + HoleWindage)/2,h=(PinTipLength + Protrusion),$fn=6); translate([0,0,PinTipLength]) cylinder(r=(PinShaftDia + HoleWindage)/2, h=(PinTaperLength + PinShaftLength + Protrusion),$fn=6); translate([0,0,(PinLength - PinFerruleLength)]) cylinder(r=(PinFerruleDia + HoleWindage)/2, h=(PinFerruleLength + Protrusion),$fn=6); translate([0,0,(PinLength)]) cylinder(r=(SpringDia + HoleWindage)/2, h=(SpringLength + Protrusion),$fn=6); translate([0,0,(PinLength + SpringLength - HoleWindage)]) // windage for hole length cylinder(r=(SpringPlugOD + HoleWindage)/2,h=3*SpringPlugLength,$fn=SpringPlugSides); // translate([0,0,(PinLength + SpringLength + SpringPlugLength)]) // cylinder(r=(SpringPlugOD + HoleWindage)/2,h=2*SpringPlugLength,$fn=SpringPlugSides); // extend hole } } module PinAssembly() { translate([ExtendRelax,ContactOffset,CaseThickOffset + ContactHeight]) { rotate([0,270,0]) { PinShape(); // pins translate([0,(1*ContactOC),0]) PinShape(); } } } //-- Alignment pins module AlignPins() { for (x=[-1,1]) translate([x*(LidLength - 2*AlignPinInset)/2,AlignPinOffset,0]) rotate(45) PolyCyl(AlignPinOD,AlignPinLength); } //-- Case with origin at battery corner module Case() { difference() { union() { difference() { translate([(CaseLength/2 + CaseLengthOffset), (CaseWidth/2 + CaseWidthOffset), (CaseThick/2)]) roundedBox([CaseLength,CaseWidth,CaseThick],CornerRadius); // basic case shape translate([-ExtendOvertravel,-GuideRadius,CaseThickOffset]) cube([(BatteryLength + GuideRadius + ExtendOvertravel), (BatteryWidth + 2* GuideRadius), (BatteryThick + Protrusion)]); // battery space } Guides(); translate([-ExtendOvertravel,-GuideRadius,BaseThick]) cube([(AlignDepth + ExtendOvertravel), (AlignWidth1 + GuideRadius), AlignThick]); // alignment blocks translate([-ExtendOvertravel, (BatteryWidth - AlignWidth2), BaseThick]) cube([(AlignDepth + ExtendOvertravel), (AlignWidth2 + GuideRadius), AlignThick]); } translate([(-ExtendOvertravel), (CaseWidthOffset - Protrusion), (CaseThickOffset + BatteryThick)]) cube([CaseLength, (CaseWidth + 2*Protrusion), (TopThick + Protrusion)]); // battery access translate([(CaseLengthOffset - Protrusion), (CaseWidthOffset - Protrusion), (CaseThickOffset + BatteryThick)]) cube([(CaseLength + 2*Protrusion), (CaseWidth + 2*Protrusion), (TopThick + Protrusion)]); // battery insertion allowance translate([(BatteryLength - Protrusion), (CaseWidth/2 + CaseWidthOffset), (CaseThickOffset + ThumbRadius)]) rotate([90,0,0]) rotate([0,90,0]) cylinder(r=ThumbRadius, h=(WallThick + GuideRadius + 2*Protrusion), $fn=22); // remove thumb notch PinAssembly(); translate([-LidLength/2,BatteryWidth/2,CaseThick - TopThick - (AlignPinLength - TopThick/2)]) AlignPins(); } } module Lid() { difference() { translate([0,0,(CaseThick/2 - BaseThick - BatteryThick)]) roundedBox([LidLength, CaseWidth,CaseThick],CornerRadius); translate([0,0,-(CaseThick/2)]) cube([(LidLength + 2*Protrusion), (CaseWidth + 2*Protrusion), (CaseThick)],center=true); translate([-ExtendRelax,0,-(AlignPinLength - TopThick/2)]) AlignPins(); } } module PlugShape() { difference() { cylinder(r=SpringPlugOD/2,h=SpringPlugLength,$fn=SpringPlugSides); translate([0,0,-Protrusion]) PolyCyl(SpringPlugID,(SpringPlugLength + 2*Protrusion),SpringPlugSides); } } module Plugs() { translate([0,ContactOC,0]) PlugShape(); translate([0,-ContactOC,0]) PlugShape(); } //------------------- // Build it! ShowPegGrid(); if (Layout == "Case") Case(); if (Layout == "Lid") Lid(); if (Layout == "Plugs") for (i=[-1:1]) translate([i*1.5*SpringPlugOD,0,0]) Plugs(); if (Layout == "Pins") PinShape(); if (Layout == "AlignPins") AlignPins(); if (Layout == "Show") { // reveal pin assembly difference() { Case(); translate([(CaseLengthOffset - Protrusion), (CaseWidthOffset - Protrusion + WallThick + ContactOffset + ContactOC), (BaseThick + ContactHeight)]) cube([(-CaseLengthOffset + Protrusion), (CaseWidth + 2*Protrusion), CaseThick + BaseThick - ContactHeight + Protrusion]); translate([(CaseLengthOffset - Protrusion), (CaseWidthOffset - Protrusion), -Protrusion]) cube([(-CaseLengthOffset + Protrusion), (WallThick + GuideRadius + ContactOffset + Protrusion), CaseThick]); } translate([ExtendRelax,ContactOffset,(CaseThickOffset + ContactHeight)]) { // pins rotate([0,270,0]) { %PinShape(); // translate([0,(2*ContactOC),0]) // %PinShape(); } } translate([CaseLengthOffset,ContactOffset,(CaseThickOffset + ContactHeight)]) rotate([0,90,0]) PlugShape(); } if (Layout == "Build") { translate([-(CaseLength/2 + CaseLengthOffset),-(CaseWidthOffset - BuildOffset),0]) Case(); translate([CaseWidth/2,(CaseLengthOffset/2 - BuildOffset),0]) rotate([0,0,90]) Lid(); for (i=[-1:1]) translate([CaseLengthOffset/2 + i*1.5*SpringPlugOD,-CaseWidth/2,0]) Plugs(); } if (Layout == "Fit") { Case(); translate([(-LidLength/2 + ExtendRelax), (CaseWidth/2 + CaseWidthOffset), (BaseThick + BatteryThick + Gap)]) Lid(); translate([ExtendRelax,ContactOffset,CaseThickOffset + ContactHeight]) { // pins rotate([0,270,0]) { %PinShape(); translate([0,(1*ContactOC),0]) %PinShape(); } } translate([CaseLengthOffset, (ContactOffset + ContactOC), (CaseThickOffset + ContactHeight)]) rotate([0,90,0]) Plugs(); translate([-LidLength/2,BatteryWidth/2,CaseThick]) # AlignPins(); }
One thought on “Sony NP-BX1 Battery Test Fixture”
Comments are closed.