Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.
The first version of the NB-5L battery holder worked well enough to get some initial performance curves from the assortment of eBay batteries. I bought one apiece from four different vendors for around $3 each; an order of magnitude less than OEM Canon NB-5L camera batteries. Based on past experience, I didn’t expect much and, lo-and-behold, I wasn’t disappointed in the least! Clicky for more dots:
Canon NB-5L – first tests
Using a 500 mA discharge current (roughly C/2) seemed reasonable, but I have no idea what the camera actually draws and the Canon manual isn’t forthcoming. These are all hot off the Canon charger.
That nice long curve on the top is the OEM Canon NB-5L that came with the camera and delivers pretty much its rated 1050 mAh.
The generic batteries have two faults:
Low discharge voltage (high internal resistance?)
Much less than their claimed capacity (they lie!)
The one labeled D Group was advertised as 1500 mAh, which seemed unreasonable on the face of it. The battery case says 1050 mAh and the vendor said their manufacturer “must have shipped them the wrong batteries”. Yeah, right, like they hadn’t noticed up. They wanted me to return it (on their dime, by “refusing” the shipment, which is, AFAICT, prohibited after you open the package), which says that they didn’t have any batteries with “1500 mAh” printed on the side for an exchange. Of course, their advertising for the other NB-5L batteries they offer on eBay hasn’t changed, so … they lie!
The Anonymous Gray battery is particularly feeble; I may harvest the frame and connector and battery protection circuit to build an external battery pack with far more capacity.
The crinkly black trace comes from testing that battery with wires taped in place before I got the first version of the holder up & running well enough to take the rest of the measurements.
Only one generic battery has a manufacturer’s name, two lack regulatory agency markings (not that I expect any to comply with the requirements implied by those markings), and all four are obviously junk. I’ll use them for around-the-house pix with the charger close at hand, but … now we all know that you don’t get something for nothing. No surprise there, eh?
The first pass at a holder for a Canon NB-5L battery didn’t quite work, but the failure was instructive. The overall layout was fine; the battery fit well, it’s just that the pins and springs didn’t function properly.
NB-5L Holder – Internal spring – solid model
I thought a simple straight music wire spring pushed into a hole with a pocket to limit the pin travel would suffice. Watching it build showed that the pocket came out too small and the spring hole was almost completely closed, despite a bit of HoleWindage.
Here’s a closer look at the spring arrangement, with a pocket at the bottom for an epoxy blob after it became obvious the ABS couldn’t properly anchor the pin.
NB-5L Holder – Internal spring – detail
Drilling out the holes to allow free pin movement ended up with #52 for the tip, #40 for the shaft, and #31 for the ferrule at the end; choose for an easy slip fit.
I used 0.024 inch (0.6 mm) music wire, which fit neatly into the pin’s inspection hole. Drilling that (#73 drill) into the nearly closed hole through the bottom showed that things weren’t working well: far too much resistance along what should be a half-open channel.
With the pin in place and a stub of wire pushed upward into the pin, the pins moved very stiffly and tended to not return to their rest position. Minus the spring wire, they slid freely.
After a bit of this and that, I tried 0.020 music wire, which didn’t have enough return force at all.
The end of the spring wire moved around a lot more than I think it should have, gradually turning the hole into an oval. I drilled two pockets in the bottom (and changed the solid model to match what you see above) and cast a dab of epoxy into each hole; that solved the moving-around problem, but the pins were still too stiff.
NB-5L Holder – first version – bottom
The weird orange color comes from a few layers of Safety Orange filament that melded into white in mid-flight. No reason to use fancy filament on a prototype, methinks; that’s what was in place when I started.
But I glued the cap on anyway to see if the pins would work well enough to run some early battery tests. This is what it looked like before gluing the cap:
NB-5L Holder – first version
The Powerpole connectors came from one of those packs, with the wires soldered into the ends of the pins so as to not block the inspection holes that I’m using for the music wire springs.
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
//- Spring dimensions
ExtendRelax = 1.5 + ContactRecess; // pin extension when no battery is present
ExtendOvertravel = 1.0; // ... beyond engaged position
SpringDia = 0.024 * inch; // music wire spring
SpringTravel = ExtendRelax + ExtendOvertravel;
SpringLength = 4.0 + PinShaftDia/2; // free length below pin centerline
//- 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;
SpringPlugDia = 3.0; // filament snippet holding spring wire
SpringPlugLength = IntegerMultiple(1.0,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]) { // pins
rotate([0,270,0]) {
PinShape();
translate([0,(2*ContactOC),0])
PinShape();
}
}
translate([-(PinHoleOffset - ExtendRelax + SpringTravel/2),
ContactOffset,
(CaseThickOffset + ContactHeight - SpringLength/2 + Protrusion/2)]) {
cube([SpringTravel,
(2*SpringDia),
(SpringLength + Protrusion)],
center=true); // spring deflection pocket
translate([0,(2*ContactOC),0])
cube([SpringTravel,
(2*SpringDia),
(SpringLength + Protrusion)],
center=true);
}
translate([-(PinHoleOffset - ExtendRelax),
ContactOffset,
(-Protrusion/2)]) {
PolyCyl(SpringDia,(BaseThick + ContactHeight + Protrusion)); // spring wire
PolyCyl(SpringPlugDia,(SpringPlugLength + Protrusion)); // wire holder
translate([0,(2*ContactOC),0]) {
PolyCyl(SpringDia,(BaseThick + ContactHeight + Protrusion));
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();
}
}
}
Before trotting off to college, my Shop Assistant repaired a pair of headphones she’d scrounged at the end of her Senior year; they were nice Skullcandy on-ear phones with one dead cup. The previous owner evidently wasn’t into fixing things and bequeathed them to her.
She dismantled the offending cup to find some really grody soldering that ought to have produced a cold solder joint: the common lead wasn’t making contact with the plug. Alas, the only way to proceed was to slice the injection-molded cover off the plug and see what was inside; to our surprise, everything looked fine.
We then cut an inch off the cable and pulled the conductors out:
Broken headphone cable conductors
Well, that was easy! Here’s a closer look:
Broken headphone conductor – detail
The three broken wires (only one of which was completely disconnected) failed exactly at the end of that plug covering. It had strain relief notches, but we guessed the previous owner had no qualms about bending the cable hard against the end of the plug.
She soldered it up, shrank some heat stink tubing around the plug and its sliced cover, wrapped self-vulcanizing tape around the junction for better strain relief, and it’s all good. She’ll get plenty of use out of the headphones in the dorm …
The Tiny Toy Dump Truck by madscifi makes a fine tchotchke for a presentation, serving to illustrate the risks and rewards of printing flat overhangs without support. A fleet of six printed well, after repairing some failures as those tall, tall rings and posts near the dump bed pivot fell over. I pasted them down in mid-print using ABS slurry, which is not a technique to emulate.
A closer look shows the overhang problem in the dump bed and the broken pillars behind the wheels.
Truck overhang failure – grayscale
It’s in monochrome because the camera choked on that much Safety Orange filament in the image, to the extent that no amount of color correction produced a usable result.
So it’s time for the whole pile of silica gel to go into the oven. The various packages suggested something around 12 hours at about 250 °F, so I set the oven timer for 11:59 and let it cook overnight:
Assorted Silica Gels
The granules in the trays go into sealed glass jars, where they will remain dry until needed. The assorted beads & kibble in the plates get bagged up and go in the fireproof safe along with the big bag in the front, where they ought to be good for maybe half a year. It’s a new safe, so we’ll see how that works out; I tucked a note with the weights inside the safe.
I found a “sealed” plastic bucket of assorted packages that I’d dried and weighed a decade ago and then lost in the back of the shelf. It had gained 2 ounces, but the packages have rotted out and the beads weren’t in good shape; they were the consumer-grade bags that aren’t intended to be dried and reused.
A first cut at a holder for Canon NB-5L batteries with those dimensions, with the intent of connecting them to a battery tester.
NB-5L Battery Holder Doodle
The cloud in the middle of the bottom holds pin dimensions, which I measured after I’d been doodling for a bit. They come from my heap; they’re nice heavy-gold plated male pins (yeah, I have the other gender, too) intended for a multi-pin connector. They have a convenient hole that’s normally used to verify you’ve actually soldered the wire properly. I plan to stick a music-wire spring in the hole and secure it through the bottom of the holder with a rectangular pocket below the pin that limits the travel in both directions. Drilling the hole completely through the pin to let the spring wire stick out would prevent having it fall out at the end of travel.
The spring pocket dimensions are right down around the very limit of the feature sizes my TOM can achieve. I’m not sure those blind holes will actually open up far enough.
I’m also not sure the Powerpoles will actually fit in there like that. There’s nothing wrong with pigtail leads.
It’s obviously styled after the Official Canon NB-5L charger, although they use nice bent-steel spring contacts that are trivially easy to make in mass production:
Here’s a howling 1200 Hz mechanical resonance excited by a full-step drive at 290 rpm, with the resonance running at 5 cycles for every 4 full steps.:
1 Step Res 240 Hz
[Update: top trace is voltage from big stepper-as-generator, bottom is small stepper winding current = 1 A/div.]
Switching to 1/2 microstepping at the same rotational speed pretty well tamps it down:
Half Step Res 240 Hz
However, here’s the same resonance excited by 1/2 microstepping at half the rotational speed, oscillating at 9 irregular cycles for every 8 half-steps:
Half res 120 Hz
The resonance was strong enough to back the setscrew completely out of the generator end of the shaft, leaving me wondering why the output was dead when the motor was obviously running. Yes, several times…