The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Electronics Workbench

Electrical & Electronic gadgets

  • Canon NB-6LH Battery Test Fixture

    Our Larval Engineer’s new camera uses Canon NB-6LH batteries, which have exactly the same nominal capacity as the NB-5L batteries for my camera, despite being not quite the same size. I cannot imagine any reason for that, other than brand fractionation, but there it is.

    Fortunately, the sizes are pretty close, so I conjured up another 3D printed battery test fixture for the rundown tests:

    Canon NB-6L battery holder
    Canon NB-6L battery holder

    That hideous Powerpole thing came from one of the AA cell packs I’d been using to power the HTs on the bikes, before switching to lithium battery packs. It’s easier to harvest something suitable than to build a new thing, particularly for such a low duty cycle gadget.

    This view of the solid model shows the contact pins, with the lid floating over its alignment pegs (made from snippets of 1.75 mm filament):

    NB-6L Holder - fit layout
    NB-6L Holder – fit layout

    The pegs simplify gluing the lid in place, a process for which you can never have enough clamps:

    Canon NB-6L holder - lid gluing
    Canon NB-6L holder – lid gluing

    A cutaway shows the stepped holes around the contact pin, with the coil springs being the largest cylinder to the right of the solid-looking plug:

    NB-6L Holder - show layout
    NB-6L Holder – show layout

    The contact pins look like this, at least after one remembers to slide on all the parts before soldering the wires in place:

    Canon NB-6L holder - contact pin detail
    Canon NB-6L holder – contact pin detail

    I filed off the inevitable solder bumps, rounded the butt ends with gentle suasion, and generally tidied the pins up so they’re smooth and symmetrical. The springs don’t have a lot of oomph, so wasting any force on friction or binding is a Bad Thing.

    The holes require reaming with twist drills for a nice slip fit around the pins. The OpenSCAD script prints out the relevant diameters and depths:

    ECHO: "Contact pin tip dia: 1.6"
    ECHO: "Drill depth to taper end: 24.1 -- Dia: 2.4"
    ECHO: "            to ferrule end: 15 -- Dia: 3.1"
    ECHO: "            to plug end: 4 -- Dia: 5.2"
    

    Grab the proper drill in a pin punch, adjust so that length protrudes, and have at it. Making the holes about 0.2 mm larger than nominal works well, although your mileage will definitely vary.

    The build layout includes extra retaining plugs, as they tend to go walkabout under the bench:

    NB-6L Holder - build layout
    NB-6L Holder – build layout

    Add a dab of PVC cement with THF inside the holes and the plugs push firmly into place:

    Canon NB-6L holder - pin retaining plugs - detail
    Canon NB-6L holder – pin retaining plugs – detail

    I loves me my 3D printer…

    The OpenSCAD source code:

    // Holder for Canon NB-6L Li-Ion battery
    // Ed Nisley KE4ZNU January 2013
    
    include <MCAD/boxes.scad>
    
    // Layout options
    
    Layout = "Plugs";					//  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 = 42.5;
    BatteryWidth = 35.5;
    BatteryThick =  7.0;
    
    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.8;			// alignment recesses on contact face
    AlignDepth = 2.0;			// into face
    AlignWidth1 = 0.7;			// across face at contacts
    AlignWidth2 = 2.0;			//  ... 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.3;			// 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 = 10;
    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;
    
    //- 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,(2*ContactOC),0])
    		PinShape();
    	}
      }
    
    }
    
    //-- Alignment pins
    
    module AlignPins() {
    
    	for (x=[-1,1])
    		translate([x*(LidLength - 2*AlignPinInset)/2,0,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,(2*ContactOC),0])
    		%PinShape();
    	}
      }
    
      translate([CaseLengthOffset,
    			(ContactOffset + ContactOC),
    			(CaseThickOffset + ContactHeight)])
      rotate([0,90,0])
    	Plugs();
    
      translate([-LidLength/2,BatteryWidth/2,CaseThick])
    #	AlignPins();
    
    }
    
    
  • Canon vs. Wasabi NB-6LH Batteries

    Our Larval Engineer reported that her camera, which is my old Casio pocket camera, has begun fading away, so we’re getting her a shiny new camera of her very own. Being a doting father, I picked up a pair of Wasabi NB-6L batteries (and a charger, it not costing much more for the package) so she’s never without electrons, and did the usual rundown test on all three batteries:

    Canon NB-6L - 2014 OEM vs Wasabi
    Canon NB-6L – 2014 OEM vs Wasabi

    Fairly obviously, the Wasabi batteries aren’t first tier products, but they’re definitely better than that bottom-dollar crap from eBay.

  • Thing-o-Matic 286 Conversion

    A few months ago I fired the Thing-O-Matic, only to have it wake up dead. Not exactly dead, but spitting out checksum errors on simple G-Code files sent from Pronterface, which used to work just fine. Trying a bit of this-and-that to no avail, I proposed to The Mighty Thor that I could loan the carcass to Squidwrench, reanimate it with a less bizarre set of hardware and firmware than the much-hacked Makerbot menagerie under the hood, and use it as an exemplar in my 3D Printing classes.

    Fortunately, that particular Thing-O-Matic has the most well-documented hardware evah

    Matt suggested an Azteeg X3 controller, because it has thermocouple inputs that match the existing sensor, Thor ordered one, and I tinkered up a first-pass version of Marlin that could read the inputs and twiddle the motors. The firmware is on Github, not that you’ll need it for anything you’re doing; more on that later.

    Here’s the Official Doc for the microstepping jumpers hidden under the driver boards:

    Azteeg X3 - microstep jumpers
    Azteeg X3 – microstep jumpers

    That’s XYZE = 16 16 8 4, respectively, with a spare slot (and spare driver, not installed) for the second extruder it’ll never have.

    A first pass at setting the motor currents

    The extruder’s Type K thermocouple connects to the TC1 port on the shield, exactly reversed from the way you see the test thermocouple there: the red lead is to the left, the yellow lead is to the right. If you get it backwards, the indicated temperature goes down when you touch the bead. The printer’s thermocouple has some backstory.

    The 10 kΩ thermistor bead connects to the BED port on the main board and isn’t polarized. The Heated Build Platform has a bit of backstory, too.

    The gutted TOM286 carcass with the MBI hardware off to the side:

    TOM286 - gutted electronics bay
    TOM286 – gutted electronics bay

    After a few sessions, it looked pretty cheerful again:

    TOM286 - reborn at Squidwrench
    TOM286 – reborn at Squidwrench

    The penguin duct tape adds a festive flair, don’t you agree?

    This is what you see when looking down through the acrylic baseplate:

    Azteeg X3 - inside TOM286
    Azteeg X3 – inside TOM286

    The blurry silver rectangle off to the left is an aluminum channel glommed to bottom of the acrylic baseplate with silicone snot to eliminate a nasty mechanical resonance.

    The thermal cutout circuitry isn’t wired in yet; the ATX power supply has its -Power-On pin hotwired to the adjacent ground pin for now. The X3 gets its power directly from the +12 V supply, so there doesn’t seem to be any way to power the X3 from the +5 V Standby ouput, deliver +12 V to the motors, and switch the supply through the X3’s ATX output pin.

    The heaters work fine, the motors turn properly, and the extruder feeds molten plastic; all the motor calibrations seem to be pretty close. The first test object was a total botch, of course, but the printer’s parts seem to work OK again.

    Next step: calibration!

  • FC1002 Frequency Counter Battery Pack

    The main reason for taking the FC1002 frequency counter apart was to replace the failed quad-AA NiCd battery pack. Rather than buy new cells with tabs, I recycled some low-discharge “ready to use” NiMH cells from the heap. Back in 2009, they looked like this:

    Tenergy RTU Pack A Tests - Aug 2009
    Tenergy RTU Pack A Tests – Aug 2009

    Nowadays, they’re a bit less peppy:

    Tenergy RTU - 2014-01 - loose cells
    Tenergy RTU – 2014-01 – loose cells

    The red blooper shows that you can’t trust a smart fast charger to get the right answer; it concluded that pair was fully charged. After the discharge test and an overnight C/10 charge, they regained as much enthusiasm as they’ll ever have.

    They have slightly less capacity than in 2009 and also a somewhat lower terminal voltage. That shouldn’t matter here, as the frequency meter has a power supply to take care of that problem.

    Although I’ve sometimes been able to (quickly!) solder directly to ordinary AA cells, a trial run on a defunct RTU cell showed that wasn’t going to work on whatever variety of steel they used, no matter how much I scuffed it and despite using aggressive flux that normally blends silver solder onto stainless steel.

    Fortunately, the top half of a four cell case fit exactly in the space available, so I used woven copper fabric tape inside the case to interconnect the cells, then lashed everything together with the obligatory Kapton tape:

    FC1002 Frequency Counter - battery pack
    FC1002 Frequency Counter – battery pack

    That cracked faceplate isn’t the nicest thing to confront, but it’ll suffice until I get more motivation:

    FC1002 Frequency Counter - repaired
    FC1002 Frequency Counter – repaired

    I’ve misplaced my stack of Round Tuits again…

  • MHV LUG Lightning Talk: Intro to NSA Hardware Implants

    Meme - Nixon - I see what you did there - 5x38k
    Meme – Nixon – I see what you did there – 5x38k

    I did five minutes of standup comedy at yesterday’s MHV Lug meeting, pointing out some of the more interesting ways to compromise a PC when you have an infinite budget for development and consumables.

    You don’t get my patter with the PDF (unless you had access to the room’s bugging hardware), but the links may come in handy in the unlikely event you haven’t been following the story closely.

    If you have a security clearance or are in line for one, you probably shouldn’t click on the link, because it contains copies of pages from the leaked NSA catalog:

    I See What You Did There – NSA Hardware Guide

  • Water Cooled Stepper Motors: Flow Calculation

    A discussion on the Makergear Google Group about a heated enclosure prompted me to run the numbers for cooling stepper motors with water, rather than fans and finned heatsinks.

    The general idea comes from my measurements of the air-cooled heatsink stuck to a stepper’s end cap. The metal-to-metal conductivity works surprisingly well and reduces the case temperature to slightly over ambient with decent airflow through the heatsink; epoxying a cold plate to the end cap should work just as well. A NEMA 17 stepper case is 42.3 mm square, so a standard 40 mm square CPU cooling plate will fit almost exactly.

    The question then becomes: how much water flow do you need to keep the motors cool?

    Some numbers:

    • Water’s heat capacity is 4.2 J/g·K
    • 1 J = 1 W·s, 1 W = 1 J/s
    • NEMA 17 motors dissipate about 5 W (13 W if you’re abusing them)
    • We’ll cool all four motors in parallel, for a total of 20 W
    • Allow a 5 K = 5 °C temperature rise in each cold plate

    Rub them all together:

    (20 J/s) / (5 K * (4.2 J/g·K)) = 0.95 g/s

    For water, 1 g = 1 cc, so the total flow is 1 cc/s = 3600 cc/h = 3.6 liter/h, which, here in the US, works out to a scant 1 gallon/hour. It’s tough getting a pump that small and cheap flowmeters run around 0.5 liter/m…

    If you don’t want a pump. put an aquarium up on a (sturdy) shelf and drain it through the cold plates. A cubic foot of water, all eight gallons and sixty-some-odd pounds of it, will last 8 hours, which should be enough for most printing projects.

    If you want reliability, drain the coolers into a sump with a float switch (high = on), put another float switch (high = off) on the aquarium, and have the pump top up the aquarium. If the pump fails, your steppers stay cool for the next 8 hours. Heating the water about 5 °C during 8 hours won’t require active cooling.

    Now, managing the hoses leading to the X axis stepper may be challenging, but a cable drag chain would control the rest of the wiring, too.

  • External DVD Battery Pack Status

    One of the battery packs powering the GPS+audio interface on our bikes has completely failed, with zero volts at the output and no charge indication. The other five chug along as well as can be expected:

    Initial-brand DVD External Packs - 2013-11
    Initial-brand DVD External Packs – 2013-11

    The push-to-test button on Pack 4 has become increasingly erratic over the last few months, rendering the charge status LEDs mostly useless, so it has two curves: the lower capacity came directly from the bike, the higher hot off the charger.

    For reference, here’s what they looked like in May 2012:

    External Li-Ion packs - 2012-05
    External Li-Ion packs – 2012-05

    And right after they arrived:

    Initial External Li-Ion packs
    Initial External Li-Ion packs

    Given their nearly constant use and charge cycling, I’m impressed.

    Those Lenmar DVDU923 packs look similar, at twice the no-name 2010 price. So it goes…