NB-5L Holder: Plug Spring Holder

After that failure, I thought maybe making the spring guide pocket a bit wider and seating the spring wire in a solid plug would work. A tweak to the OpenSCAD script produced this, along with slightly larger locating ribs around the battery compartment:

Plug spring - solid model
NB-5L Holder - Plug spring - solid model

A closer look at the plug spring assembly:

NB-5L Holder - Plug spring - detail
NB-5L Holder - Plug spring - detail

The hole is now slightly larger, distinct from the side of the pocket, and the partition between the pocket and plug (although something of a formality) seats the plug during assembly. The plug started out at 3 mm in diameter, as I intended to try ramming a heated wire into a length of filament. That worked, mmmm, somewhat poorly, so I drilled a hole in a length of filament:

Music wire in filament plug
Music wire in filament plug

Unfortunately, that whole bodge didn’t work any better than the spring in the first pass at a holder, so I gave up and cast the springs in epoxy. The OpenSCAD code produces a 5 mm diameter hole that should provide a larger epoxy plate with better grip than the 3 mm holes in this picture, but it probably won’t make much difference:

Music wire in epoxy plug
Music wire in epoxy plug

The alert reader will note a complete faceplant: yeah, I forgot to solder the wires into the pins before blobbing the springs in place. Fortunately, the epoxy cures slowly enough that I could:

  • Take the picture
  • Immediately see the obvious problem
  • Ease the music wire springs out just a tidge
  • Extract the pins
  • Quick-like-a-bunny solder wires to pins
  • Insert pins with proper polarity
  • Ease springs back in place

I hate it when that happens…

With springs & wires properly in place and the epoxy cured overnight, the pins had considerably better springiness and free motion than before, although they didn’t have quite the range of travel I wanted. I think the spring wire bent slightly on the first push, as the pins never came quite as far out after that.

So this was a qualified success, but not a solid win. Time for round three…

The OpenSCAD source code:

// Holder for Canon NB-5L Li-Ion battery
// Ed Nisley KE4ZNU August 2011

include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
include </home/ed/Thing-O-Matic/lib/MCAD/boxes.scad>
include </home/ed/Thing-O-Matic/Useful Sizes.scad>

// Layout options

Layout = "Show";					// Case Lid Show Build Fit

//- Extrusion parameters - must match reality!
//  Print with +2 shells and 3 solid layers

ThreadThick = 0.33;
ThreadWidth = 2.0 * ThreadThick;

HoleWindage = 0.2;

function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);

Protrusion = 0.1;			// make holes end cleanly

BuildOffset = 3.0;			// clearance for build layout

//- Battery dimensions - rationalized from several samples
//  Coordinate origin at battery corner by contact plates on bottom surface

BatteryLength = 45.25;
BatteryWidth = 32.17;
BatteryThick =  7.85;

ContactWidth = 2.10;
ContactLength = 4.10;
ContactRecess = 0.85;

ContactOC = 3.18;			// center-to-center across contact face
ContactOffset = 4.45;		// offset from battery edge
ContactHeight = 3.05;		// offset from battery bottom plane

AlignThick = 2.2;			// alignment recesses on contact face
AlignDepth = 2.0;			// into face
AlignWidth1 = 0.7;			// across face at contacts
AlignWidth2 = 2.8;			//  ... other edge

//- Pin dimensions

PinTipDia = 1.6;
PinTipLength = 10.0;

PinTaperLength = 2.3;

PinShaftDia = 2.4;
PinShaftLength = 6.8;

PinFerruleDia = 3.0;
PinFerruleLength = 2.0;

PinLength = PinTipLength + PinTaperLength + PinShaftLength + PinFerruleLength;

PinHoleOffset = 13.9;			// tip to spring hole

ExtendRelax = 1.5 + ContactRecess;		// pin extension when no battery is present
ExtendOvertravel = 1.0;					//  ... beyond engaged position

//- Holder dimensions

GuideRadius = ThreadWidth;						// friction fit ridges
GuideOffset = 10;
WallThick = 4*ThreadWidth;						// holder sidewalls

BaseThick = IntegerMultiple(6.0,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 = 2*WallThick + PinLength - ExtendRelax + ExtendOvertravel + BatteryLength + GuideRadius;
CaseWidth = 2*WallThick + 2*GuideRadius + BatteryWidth;
CaseThick = BaseThick + BatteryThick + TopThick;

//- XY origin at front left battery corner, Z on platform below that

CaseLengthOffset = -(WallThick + PinLength - ExtendRelax + ExtendOvertravel);
CaseWidthOffset = -(WallThick + GuideRadius);
CaseThickOffset = BaseThick;

LidLength = ExtendRelax - CaseLengthOffset;

//- Spring dimensions

SpringPlugDia = 5.0;					// epoxy plug holding spring wire
SpringPlugLength = IntegerMultiple(1.5,ThreadThick);

SpringDia = 0.024 * inch;	// music wire spring
SpringTravel = ExtendRelax + ExtendOvertravel;
SpringLength = BaseThick + ContactHeight - SpringPlugLength - 2*ThreadThick;

echo(str("Spring wire from end: ",WallThick + PinLength - PinHoleOffset));
echo(str("            from side: ",WallThick + GuideRadius + ContactOffset));
echo(str("Pin spacing on centers: ",ContactOC));

//----------------------
// 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() {

PolyPin = false;

  union() {
	if (PolyPin)
	  PolyCyl(PinTipDia,(PinTipLength + Protrusion));
	else
	  cylinder(r=(PinTipDia + HoleWindage)/2,h=(PinTipLength + Protrusion),$fn=6);

	translate([0,0,PinTipLength])
	  if (PolyPin)
		PolyCyl(PinShaftDia,(PinTaperLength + PinShaftLength + Protrusion));
	  else
		cylinder(r=(PinShaftDia + HoleWindage)/2,
				 h=(PinTaperLength + PinShaftLength + Protrusion),$fn=6);

	translate([0,0,(PinLength - PinFerruleLength)])
	  if (PolyPin)
		PolyCyl(PinFerruleDia,(PinFerruleLength + Protrusion));
	  else
		cylinder(r=(PinFerruleDia + HoleWindage)/2,
				 h=(PinFerruleLength + Protrusion),$fn=6);

	translate([0,0,PinLength])
	  if (PolyPin)
		PolyCyl(PinFerruleDia,PinLength);			// very long holes to punch case
	  else
		cylinder(r=(PinFerruleDia + HoleWindage)/2,h=PinLength,$fn=6);
  }

}

module PinAssembly() {

  translate([ExtendRelax,ContactOffset,CaseThickOffset + ContactHeight]) {
	rotate([0,270,0]) {
	  PinShape();												// pins
	  translate([0,(2*ContactOC),0])
		PinShape();
	}
  }

  translate([-(PinHoleOffset - ExtendRelax + SpringTravel/2 - SpringDia/2 - HoleWindage/2),
			 ContactOffset,
			 (CaseThickOffset + ContactHeight - SpringLength/2 - Protrusion)]) {
	  cube([(SpringTravel + SpringDia/2 + HoleWindage),
		    PinShaftDia,
			(SpringLength + 2*Protrusion)],
		   center=true);										// spring deflection pocket
	  translate([0,(2*ContactOC),0])
		cube([(SpringTravel + SpringDia/2 + HoleWindage),
			 PinShaftDia,
			 (SpringLength + 2*Protrusion)],
			 center=true);
  }

  translate([-(PinHoleOffset - ExtendRelax),
			 ContactOffset,
			 (-Protrusion/2)]) {
	PolyCyl(SpringDia,(BaseThick + ContactHeight + Protrusion),4);		// spring wire
	PolyCyl(SpringPlugDia,(SpringPlugLength + Protrusion));				// wire holder
	translate([0,(2*ContactOC),0]) {
	  PolyCyl(SpringDia,(BaseThick + ContactHeight + Protrusion),4);
	  PolyCyl(SpringPlugDia,(SpringPlugLength + Protrusion));
	}
  }

}

//-- 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();

  }

}

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);
  }

}

//-------------------
// Build it!

ShowPegGrid();

if (Layout == "Case")
  Case();

if (Layout == "Lid")
  Lid();

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();
	}
  }

}

if (Layout == "Build") {
  translate([-(CaseLength/2 + CaseLengthOffset),-(CaseWidthOffset - BuildOffset),0])
	Case();
  translate([0,(CaseLengthOffset/2 - BuildOffset),0])
	rotate([0,0,90])
	  Lid();

}

if (Layout == "Fit") {
  Case();
  translate([(-LidLength/2 + ExtendRelax),
			(CaseWidth/2 + CaseWidthOffset),
			(BaseThick + BatteryThick)])
	  Lid();
  translate([ExtendRelax,ContactOffset,CaseThickOffset + ContactHeight]) {	// pins
	rotate([0,270,0]) {
	  %PinShape();
	  translate([0,(2*ContactOC),0])
		%PinShape();
	}
  }

}

One thought on “NB-5L Holder: Plug Spring Holder

Comments are closed.