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.

Tag: Improvements

Making the world a better place, one piece at a time

  • Vanilla Extract: Commercial Variations

    This look at the ingredients found in various commercial vanilla extracts (plus their prices) finally pushed me over the edge into brewing up that DIY vanilla extract.

    We’ve been using McCormick vanilla forever, mostly because it has the simplest and shortest list of ingredients:

    McCormick Vanilla
    McCormick Vanilla

    Nielson-Massey vanilla seemed about the same, although it’s not clear why it needs more sugar than those “vanilla bean extractives”:

    Nielsen-Massey Vanilla
    Nielsen-Massey Vanilla

    Wal-Mart vanilla doesn’t smell like vanilla, even though it has more “extractive” than corn syrup:

    Wal-Mart Vanilla
    Wal-Mart Vanilla

    All three extracts have “Pure” on the label, which (according to Wikipedia, anyway) means that they have at least 13.35 ounce of vanilla bean per gallon of extract. I didn’t weigh the three beans in my 8 ounces of hooch, but I suspect they weighed far less than the regulation 0.834 ounce. Next time, for sure, I’ll go for triple strength extract!

    Despite that, my DIY hooch has turned brown and smells pretty good…

    These full-frame pix used my new close-up lens gizmo; even with some vignetting the results seem perfectly usable. Normally I crop pix down to the central section, so this will be as bad as it gets.

  • Presta Valve: Proper Pump Attachment Thereto

    All our bikes have Presta valves, which seem better suited for bike rims than the larger and more common automotive Schraeder valves:

    Presta valve stem
    Presta valve stem

    For all these years, I’d been attaching the pump head so the obvious sealing ring near the nozzle opening lined up with the flat section adjacent to the valve core stem. The pump head never seemed stable on the stem, often leaked, and generally had a precarious hold:

    Incorrect Presta pump head attachment
    Incorrect Presta pump head attachment

    Come to find out, more by accident than intention, that the correct way to attach the pump head involves ramming it all the way down onto the stem so that it can seal along the entire length of the threads. That’s nice and secure, doesn’t leak, and even looks like it should work perfectly:

    Correct Presta pump head attachment
    Correct Presta pump head attachment

    I’d feel even more like a doof if I hadn’t learned to do it wrong by watching somebody else back in the day or if I haven’t observed many other people making exactly the same mistake. I think the fact that the short nozzles on the old-school Zéfal pumps I swore by back in my wedgie-bike days never got a good grip on Presta stems got me off to a bad start, but … dang do I feel stupid.

    FWIW, the little tab sticking out under the latch handle makes up for a bit of slop in the valve head. When I got the pump, the Schraeder nozzle didn’t seal very well, either, and taking up a few mils of slack helped immeasurably. We don’t need that nozzle very often, but our bicycle touring guests frequently do; they know that they can top off a Schraeder-valved tube at any gas station or with any pump anywhere around the world.

    [Update: I hate it when I misspell a word in the title…]

  • Canon SX230HS Microscope and Close-up Macro Adapters

    The deal was, if my Shop Assistant repaired my pocket camera, she could have it. She did, which meant I lost the ability to take pix through the microscope. While I was conjuring up a replacement, it occurred to me that I should also build a gadget to hold a close-up lens in front of the camera for tighter macro shots that don’t quite require a microscope’s magnification.

    The solid model of the microscope adapter:

    Microscope mount - solid model
    Microscope mount – solid model

    The close-up macro adapter, with an LED ring light around the snout:

    LED Ring mount - solid model
    LED Ring mount – solid model

    They have a common camera mounting plate, with a hex recess for a 1/4-20 nut that mates with a standard tripod screw and some support material sticking up through the hole for the screw that holds the camera to the plate:

    Mounting plate - solid model - top view
    Mounting plate – solid model – top view

    The main tube glues into the plate’s cutout and is long enough to accommodate the fully extended lens turret, with four shallow holes for filament snippet locating pins to align the snout:

    Main tube - solid model - bottom view
    Main tube – solid model – bottom view

    An exploded view shows how everything fits together, with the stud below the camera representing its tripod mounting screw:

    LED Ring mount - solid model - exploded view
    LED Ring mount – solid model – exploded view

    More details on the parts will appear over the next few days, but here’s the view through the macro adapter:

    Dahlia through macro adapter
    Dahlia through macro adapter

    Yeah, some slight vignetting, but overall it’s pretty good.

    The OpenSCAD source code that builds both adapters:

    // Close-up lens mount & Microscope adapter for Canon SX230HS camera
    // Ed Nisley KE4ZNU - Nov 2011
    
    Mount = "Eyepiece";			// End result: LEDRing Eyepiece
    
    Layout = "Show";			// Assembly: Show
    							// Parts: Plate Tube LEDRing Camera Eyepiece
    							// Build Plates: Build1..4
    
    Gap = 12;					// between "Show" objects
    
    include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
    include </home/ed/Thing-O-Matic/Useful Sizes.scad>
    include </home/ed/Thing-O-Matic/lib/visibone_colors.scad>
    
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +1 shells, 3 solid layers, 0.2 infill
    
    ThreadThick = 0.33;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleFinagle = 0.2;
    HoleFudge = 1.02;
    
    function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;
    
    Protrusion = 0.1;			// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Dimensions
    
    // doublet lens
    
    LensDia = 25.0;
    LensRad = LensDia/2;
    LensClearance = 0.2;
    
    LensEdge = 6.7;
    LensThick = 8.6;
    LensRimThick = IntegerMultiple((2.0 + LensThick),ThreadThick);
    
    // LED ring light
    
    LEDRingOD = 50.0;
    LEDRingID = 36.0;
    LEDBoardThick = 1.5;
    LEDThick = 4.0;
    LEDRingClearance = 0.5;
    LEDWireHoleDia = 3.0;
    
    // microscope eyepiece
    
    EyepieceOD = 30.0;
    EyepieceID = 24.0;
    EyepieceLength = 25.0;
    
    // camera
    // Origin at base of [0] ring, Z+ along lens axis, X+ toward bottom, Y+ toward left
    
    CameraBodyWidth = 2*10.6;							// 2 x center-to-curve edge
    CameraBaseWidth = 15.5;								// flat part of bottom front to back
    CameraBaseRadius = (CameraBodyWidth - CameraBaseWidth)/2;	// edge rounding
    CameraBaseLength = 60.0;							// centered on lens axis
    CameraBaseHeight = 55.0;							// main body height
    CameraBaseThick = 0.9;								// downward from lens ring
    
    echo(str("Camera base radius: ",CameraBaseRadius));
    
    TripodHoleOffset = -19.0;							// mount screw wrt lens centerline
    TripodHoleDia = Clear025_20;						// clearance hole
    
    TripodScrewHeadDia = 14.5;							// recess for screw mounting camera
    TripodScrewHeadRad = TripodScrewHeadDia/2;
    TripodScrewHeadThick = 3.0;
    
    // main lens tube
    
    TubeDia = 		[53.0,	44.0,	40.0,	37.6];		// lens rings, [0] is fixed to body
    TubeLength = 	[8.1,	20.6,	17.6,	12.7];
    
    TubeEndClearance = 2.0;								// camera lens end to tube end
    TubeEndThickness = IntegerMultiple(1.5,ThreadThick);
    TubeInnerClearance = 0.5;
    
    TubeInnerLength = TubeLength[0] + TubeLength[1] + TubeLength[2] + TubeLength[3] +
    				  TubeEndClearance;
    TubeOuterLength = TubeInnerLength + TubeEndThickness;
    
    TubeID = TubeDia[0] + TubeInnerClearance;
    TubeOD = TubeID + 6*ThreadWidth;
    TubeWall = (TubeOD - TubeID)/2;
    TubeSides = 48;
    
    echo(str("Main tube outer length: ",TubeOuterLength));
    echo(str("          ID: ",TubeID," OD: ",TubeOD," wall: ",TubeWall));
    
    // camera mounting base
    
    BaseWidth = IntegerMultiple((CameraBaseWidth + 2*CameraBaseRadius),ThreadThick);
    BaseLength = 60.0;
    BaseThick = IntegerMultiple((1.0 + Nut025_20Thick + CameraBaseThick),ThreadThick);
    
    // LED ring mount
    
    LEDBaseThick = IntegerMultiple(2.0,ThreadThick);	// base under lens + LED ring
    LEDBaseRimWidth = IntegerMultiple(6.0,ThreadWidth);
    LEDBaseRimThick = IntegerMultiple(LensThick,ThreadThick);
    
    LEDBaseOD = max((LEDRingOD + LEDRingClearance + LEDBaseRimWidth),TubeOD);
    
    echo(str("LED Ring OD: ",LEDBaseOD));
    
    // alignment pins between tube and LED ring / microscope eyepiece
    
    AlignPins = 4;
    AlignPinOD = 2.9;
    AlignPinCircleDia = TubeOD - 2*TubeWall - 2*AlignPinOD;		// 2*PinOD -> more clearance
    
    //-------
    
    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=HoleAdjust(FixDia)/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);
    
    }
    
    //-------
    
    //- Camera body segment
    //	Including lens base and peg for tripod hole access
    //	Z=0 at edge of lens base ring, X=0 along lens axis
    
    module CameraBody() {
    
      translate([0,0,-CameraBaseThick])
    	rotate(90)
    	  union() {
    		translate([0,0,(CameraBaseHeight/2 + CameraBaseRadius)])
    		  minkowski() {
    			cube([CameraBaseWidth,
    				  (CameraBaseLength + 2*Protrusion),
    				  CameraBaseHeight],center=true);
    			rotate([90,0,0])
    			  cylinder(r=CameraBaseRadius,h=Protrusion,$fn=8);
    		  }
    
    		translate([0,0,(TubeDia[0]/2 + CameraBaseThick)])
    		  rotate([0,90,0])
    			rotate(180/TubeSides)
    			  cylinder(r=(TubeDia[0]/2 + CameraBaseThick),
    					  h=(CameraBodyWidth/2 + Protrusion),
    					  $fn=TubeSides);
    
    		translate([CameraBodyWidth/2,0,(TubeDia[0]/2 + CameraBaseThick)])
    		  rotate([0,90,0])
    			cylinder(r=TubeDia[0]/2,h=TubeLength[0]);
    
    		translate([(TubeLength[0] + CameraBodyWidth/2),
    				  0,(TubeDia[0]/2 + CameraBaseThick)])
    		  rotate([0,90,0])
    			cylinder(r=TubeDia[1]/2,h=TubeLength[1]);
    
    		translate([(TubeLength[0] + TubeLength[1] + CameraBodyWidth/2),
    				  0,(TubeDia[0]/2 + CameraBaseThick)])
    		  rotate([0,90,0])
    			cylinder(r=TubeDia[2]/2,h=TubeLength[2]);
    
    		translate([(TubeLength[0] + TubeLength[1] + TubeLength[2] + CameraBodyWidth/2),
    				  0,(TubeDia[0]/2 + CameraBaseThick)])
    		  rotate([0,90,0])
    			cylinder(r=TubeDia[3]/2,h=TubeLength[3]);
    
    		translate([0,TripodHoleOffset,-BaseThick])
    		  PolyCyl(TripodHoleDia,(BaseThick + 2*Protrusion));
    
    	  }
    }
    
    //- Main tube
    
    module Tube() {
    
      difference() {
    	cylinder(r=TubeOD/2,h=TubeOuterLength,$fn=TubeSides);
    
    	translate([0,0,TubeEndThickness])
    	  PolyCyl(TubeID,(TubeInnerLength + Protrusion),TubeSides);
    
    	translate([0,0,-Protrusion]) {
    	  if (Mount == "LEDRing")
    		cylinder(r=LensRad,h=(TubeEndThickness + 2*Protrusion));
    	  if (Mount == "Eyepiece")
    		cylinder(r=EyepieceID/2,h=(TubeEndThickness + 2*Protrusion));
    	}
    
    	for (Index = [0:AlignPins-1])
    	  rotate(Index*90)
    		translate([(AlignPinCircleDia/2),0,-ThreadThick])
    		  rotate(180)			// flat sides outward
    			PolyCyl(AlignPinOD,TubeEndThickness);
      }
    
    }
    
    //- Base plate
    
    module BasePlate() {
    
      union() {
    	difference() {
    		linear_extrude(height=BaseThick)
    		  hull() {
    			translate([-(BaseLength/2 - BaseWidth/2),0,0])
    			  circle(BaseWidth/2);
    			translate([ (BaseLength/2 - BaseWidth/2),0,0])
    			  circle(BaseWidth/2);
    			translate([0,(0.75*BaseLength),0])
    			  circle(BaseWidth/2);
    		  }
    
    		translate([0,0,BaseThick])
    		  CameraBody();
    
    		translate([0,(TubeOuterLength + CameraBodyWidth/2),
    				  (BaseThick + TubeDia[0]/2)])
    		  rotate([90,0,0])
    			PolyCyl(TubeOD,TubeOuterLength,$fn=TubeSides);
    
    		translate([0,0,3*ThreadThick])
    		  PolyCyl((Nut025_20Dia*sqrt(3)/2),2*Nut025_20Thick,6);	// dia across hex flats
    
    		translate([0,0,-Protrusion])
    		  PolyCyl(Clear025_20,(BaseThick + 2*Protrusion));
    
    		translate([TripodHoleOffset,0,3*ThreadThick])
    		  PolyCyl((Nut025_20Dia*sqrt(3)/2),2*Nut025_20Thick,6);	// dia across hex flats
    
    		translate([TripodHoleOffset,0,-Protrusion])
    		  PolyCyl(Clear025_20,(BaseThick + 2*Protrusion));
    
    		translate([-TripodHoleOffset,0,-Protrusion])
    		  PolyCyl(TripodScrewHeadDia,(TripodScrewHeadThick + Protrusion));
    
    	}
    
    	translate([-TripodHoleOffset,0,0]) {				// support for tripod screw hole
    	  for (Index=[0:3])
    		rotate(Index*45)
    		  translate([-ThreadWidth,-TripodScrewHeadRad,0])
    			cube([2*ThreadWidth,TripodScrewHeadDia,TripodScrewHeadThick]);
    
    	  cylinder(r=0.4*TripodScrewHeadRad,h=(BaseThick - CameraBaseThick),$fn=9);
    	}
      }
    }
    
    //- LED mounting ring
    
    module LEDRing() {
    
      difference() {
    	cylinder(r=LEDBaseOD/2,h=LensRimThick,$fn=48);
    
    	translate([0,0,-Protrusion])
    	  PolyCyl((LensDia + LensClearance),
    			  (LensRimThick + 2*Protrusion));
    
    	translate([0,0,LEDBaseRimThick])
    	  difference() {
    		PolyCyl(LEDBaseOD,LensThick);
    		PolyCyl(LEDRingID,LensThick);
    	  }
    
    	translate([0,0,LEDBaseThick])
    	  difference() {
    		PolyCyl((LEDRingOD + LEDRingClearance),LensThick);
    		cylinder(r1=HoleAdjust(LEDRingID - LEDRingClearance)/2,
    				 r2=HoleAdjust(LensDia + LensClearance)/2 + 2*ThreadWidth,
    				 h=LensThick);
    	  }
    
    	for (Index = [0:AlignPins-1])
    	  rotate(Index*90)
    		translate([(AlignPinCircleDia/2),0,-ThreadThick])
    		  rotate(180)			// flat sides outward
    			PolyCyl(AlignPinOD,LEDBaseThick);
    
    	rotate(45)
    	  translate([0,LEDRingID/2,(LEDBaseThick + 1.2*LEDWireHoleDia/2)])
    		rotate([0,-90,0])			// flat side down
    		  rotate([-90,0,0])
    			PolyCyl(LEDWireHoleDia,2*LEDBaseRimWidth);
      }
    
    }
    
    //- Microscope eyepiece adapter
    
    module EyepieceMount() {
    
      difference() {
    	cylinder(r1=TubeOD/2,
    			 r2=(EyepieceOD + 8*ThreadWidth)/2,
    			 h=EyepieceLength,
    			 $fn=TubeSides);
    
    	translate([0,0,-Protrusion])
    	  PolyCyl(EyepieceOD,(EyepieceLength + 2*Protrusion));
    
    	for (Index = [0:AlignPins-1])
    	  rotate(Index*90)
    		translate([(AlignPinCircleDia/2),0,-ThreadThick])
    		  rotate(180)			// flat sides outward
    			PolyCyl(AlignPinOD,6*ThreadThick);
      }
    
    }
    
    //-------
    // Build it!
    
    if (Layout != "Show")
      ShowPegGrid();
    
    if (Layout == "Tube")
      Tube();
    
    if (Layout == "LEDRing")
      LEDRing();
    
    if (Layout == "Plate")
      BasePlate();
    
    if (Layout == "Camera")
      CameraBody();
    
    if (Layout == "Eyepiece")
      EyepieceMount();
    
    if (Layout == "Build1")
      translate([0,-BaseLength/3,0])
    	BasePlate();
    
    if (Layout == "Build2")
      Tube();
    
    if (Layout == "Build3")
      LEDRing();
    
    if (Layout == "Build4")
      EyepieceMount();
    
    if (Layout == "Show") {
      translate([0,TubeOuterLength,TubeDia[0]/2]) {
    	rotate([90,0,0])
    	  color(LTC) Tube();
    	translate([0,Gap,0])
    	  rotate([-90,0,0]) {
    		if (Mount == "LEDRing")
    		  color(OOR) LEDRing();
    		if (Mount == "Eyepiece")
    		  color(OOR) EyepieceMount();
    	  }
      }
    
      translate([0,-CameraBodyWidth/2,0])
    	color(PG) CameraBody();
    
      color(PDA)
    	render()
    	translate([0,-CameraBodyWidth/2,-(BaseThick + Gap)])
    	  BasePlate();
    }
    

    The original doodles & dimensions:

    Close-up Lens Doodles
    Close-up Lens Doodles
  • Canon SX230HS Lens Cap

    The SX230HS camera lives in my pants pocket, where it gets pressed between my leg and anything I lean against. Turns out that the lens turret end cap isn’t quite thick enough to not bend inward against the leaves that cover the lens, which causes them to hang up. The solution boils down to a hideous external lens cap:

    Canon SX230HS with lens cap
    Canon SX230HS with lens cap

    It’s built from forget-me-not yellow filament for an obvious reason…

    The sheet-metal plate bears against the non-moving rim around the turret. I marked the plate’s diameter with a compass, extracted it from the sheet with left-cutting tin snips, filed off the slivers, rounded the edge, and it snapped right into the recess where a touch of acrylic caulk holds it firmly in place.

    A thin plastic cover would be too flexible and a thicker plastic cover would be too thick; this must fit into an already-snug cloth pouch where a few additional millimeters of girth actually matter. My previous camera taught me that pocket fuzz gets into everything, so a pouch isn’t optional.

    The interior isn’t too inspiring, but you can see what two layers of plastic look like across the bottom:

    SX230HS lens cap - interior
    SX230HS lens cap – interior

    The front has the shallow recess that captures the metal plate. Because the front builds against the aluminum build platform, I added a support structure inside the recess:

    SX230HS lens cap - support in place
    SX230HS lens cap – support in place

    The solid model gives a better view:

    Lens cap - solid model - bottom view
    Lens cap – solid model – bottom view

    It’s basically a ring with tabs under the recess. The ring OD matches the lens caps’s ID, with a height equal to the recess depth, so only the tabs contact the cap. I removed them by twisting each tab with a needle-nose pliers until the whole thing popped loose:

    SX230HS lens cap - support structure
    SX230HS lens cap – support structure

    A bit of scraper and scalpel cleanup and it’s all good. The detail pix show the first trial of the lens cap, which lacks the nice bevel around the front rim.

    The camera is smart enough to notice when something blocks the lens: it immediately shuts down and displays a lens failure error message. That’s probably not a Good Thing on a regular basis, but it doesn’t seem to do any harm.

    FWIW, my previous pocket camera, a Casio EX-Z850 , sported a recessed and somewhat thicker turret end cap that didn’t have this problem. Mary says she’ll make a case for this camera, too, but until then I’m using a pouch from a dinky VOIP phone that just barely holds the camera.

    The OpenSCAD source code:

    // Lens cap for Canon SX230HS
    // Ed Nisley KE4ZNU - Nov 2011
    
    //-------
    //- Extrusion parameters must match reality!
    //  Print with +1 shells, 3 solid layers, 0.2 infill
    
    ThreadThick = 0.33;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleFinagle = 0.20;
    HoleFudge = 1.00;
    
    function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;
    
    Protrusion = 0.1;			// make holes end cleanly
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    //-------
    // Dimensions
    
    LensDia = 53.0;
    LensRad = LensDia/2;
    LensLength = 8.0;
    
    PlateThick = IntegerMultiple(0.75,ThreadThick);
    PlateDia = 48.0;
    
    Shell = 2*ThreadWidth;
    Spacer = 2*ThreadThick;
    
    CapOD = LensDia + 2*Shell;
    CapLength = LensLength + Spacer + PlateThick;
    CapSides = 48;
    
    CenterHoleDia = 44.0;
    
    BevelWidth = PlateThick;
    
    NumStruts = 16;
    SupportStrutLen = (PlateDia - ThreadWidth)/2;		// small gap to cap
    
    //-------
    
    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=HoleAdjust(FixDia)/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);
    
    }
    
    //-------
    
    ShowPegGrid();
    
    difference() {
      PolyCyl(CapOD,CapLength,CapSides);
    
      translate([0,0,(Spacer + PlateThick)])					// lens shell
    	PolyCyl(LensDia,(LensLength + Protrusion),CapSides);
    
      translate([0,0,-Protrusion])								// center hole
    	PolyCyl(CenterHoleDia,(CapLength + Protrusion));
    
      translate([0,0,-Protrusion])								// bevel
    	difference() {
    	  cylinder(r=(CapOD/2 + 2*(BevelWidth + Protrusion)),
    			   h=(2*BevelWidth + Protrusion),
    			   $fn=CapSides);
    	  cylinder(r1=(CapOD/2 - BevelWidth - Protrusion),
    			   r2=(CapOD/2 + BevelWidth),
    			   h=(2*BevelWidth + Protrusion),
    			   $fn=CapSides);
    	}
    
      difference() {
    	translate([0,0,-Protrusion])							// cover plate recess
    	  PolyCyl(PlateDia,(PlateThick + Protrusion));
    	for (Index=[0:(NumStruts - 1)])							// support struts
    	  rotate(Index*360/NumStruts)
    		translate([-ThreadWidth,-SupportStrutLen,0])
    		  cube([2*ThreadWidth,SupportStrutLen,PlateThick]);
      }
    }
    
    difference() {									// support ring
      PolyCyl(CenterHoleDia,PlateThick);
      translate([0,0,-Protrusion])
    	PolyCyl((CenterHoleDia - 4*ThreadWidth),(PlateThick + 2*Protrusion));
    }
    
  • DIY Vanilla Extract: The Beginning

    DIY Vanilla Extract
    DIY Vanilla Extract

    Having bought some low-budget Walmart vanilla extract that smells nothing at all like vanilla, I figured it’s time to get serious about this stuff. Recipes for DIY vanilla extract abound on the Internet, but as nearly as I can tell, the basic idea is to put vanilla beans in contact with ethanol, shake occasionally for a couple of months, then enjoy. Uh, by the teaspoonful, that is.

    Quite some years ago I discovered that NYS prohibits the sale of grain alcohol, so you must buy stiff vodka to get high-test ethanol. That glass bottle contains the cheapest 160 proof vodka I could find in the waning years of the last millennium; I figured it was likely to have fewer additives around its 80% ethyl alcohol than anything else in the liquor store. After more than a decade on the Basement Laboratory’s Solvents Shelf (I don’t use a lot of ethanol), a dollop in a saucer burns with an ethereal blue flame: it’s in fine shape.

    The plastic bottle originally held some weird alien fruity liquid (which, IIRC, I  picked up while doing amateur radio duty at a charity event) and has the desirable attribute of a tight sealing lid. It’d be better to use glass and I suppose amber beats clear, but this stuff will spend its entire life in a dark cupboard with all the other spices. Although some recipes call for sterilizing the bottle in boiling water, I figure any bug that can survive 80% ethanol will shrug off hot water… and the vanilla beans probably aren’t all that sterile, anyway.

    A cup of neat vodka, three slit-and-chopped vanilla beans, and away we go. It should be ready for the Christmas baking season.

    If this works, I’ll get a substantial quantity of vanilla beans from the usual eBay supplier and make some really stiff extract. Two bucks a bean at the local grocery store: ouch.

  • Self-resonant Frequencies of Some Ceramic Capacitors

    In that version of the GPS+voice interface, I sprinkled 100 nF and 100 pF SMD caps across the input lines in the hope that they’d reduce EMI on the audio board. The board worked fine for years, but now that it’s time to build another board & box, I figured it’d be good to know a bit more about their actual response.

    So I cobbled up a test fixture with a 3 dB pad from the tracking generator output and a 20 dB pad to the spectrum analyzer input (both of those are bogus, because the cap impedance varies wildly, but work with me on this):

    Ceramic 100 nF cap on copper
    Ceramic 100 nF cap on copper

    Pulled an assortment of 100 nF ceramic caps from the stockpile:

    100 nF ceramic capacitor assortment
    100 nF ceramic capacitor assortment

    And rubbed them against the HP8591 spectrum analyzer & tracking generator:

    Cap Comparison - Detail
    Cap Comparison – Detail

    Their self-resonant frequencies are much lower than I expected:

    Cap Comparison
    Cap Comparison

    The attenuators produce about 17 dB of loss with no cap in the circuit, so the disk caps are pretty much asleep at the switch from VHF on up. The small bypass cap in the top photo is OK and the SMD cap is pretty good, but they’re all well past their self-resonant frequency and acting like inductors.

    The relevant equations:

    • FR = 1/(2π √(LC))
    • XC = 1/(2π f C)
    • Q = FR / BW
    • ESR = XC / Q

    The drill goes a little something like this:

    • Find resonant frequency FR and 3 db bandwidth BW
    • Knowing FR and C, find parasitic L
    • Knowing FR and BW, find Q
    • Knowing XC and Q, find ESR

    In round numbers, the 100 nF SMD cap has L=2 nH and ESR=60 mΩ.

    Now, it turns out a 100 pF SMD cap resonates up at 300 MHz, between the VHF and UHF amateur bands:

    SMD - 100 pF Bandwidth
    SMD – 100 pF Bandwidth

    So I think the way to do this is to pick the capacitance to put the self-resonant frequency in the VHF band, parallel another cap to put a second dip in the UHF band, and run with it. A back of the envelope calculation suggests 470 pF and 47 pF, but that obviously depends on a bunch of other imponderables and I’ll just interrogate the heap until the right ones step forward.

    Just to show the test fixture isn’t a complete piece of crap, here’s a 12 pF cap resonating up around 850 MHz:

    SMD - 12 pF Bandwidth
    SMD – 12 pF Bandwidth

    For the combination of components, sweep speeds, bandwidths, and suchlike in effect, the spectrum analyzer’s noise floor is down around -75 dBm. I think the 12 pF cap is actually better than it looks, but I didn’t fiddle around with a narrower resolution bandwidth.

  • Auto Escape Hammer LED Flashlight Hackage

    A cheap auto escape hammer (IIRC, free in the bottom of a tag-sale box filled with stuff I could actually use) has been kicking around the back of the bench for far too long; it had a feeble single-cell incandescent bulb flashlight with the cheapest possible non-switch. I ripped all that out, carved out enough plastic to fit a CR123 lithium cell, hot-melt-glued a real pushbutton switch and 10 mm white LED in place, and soldered it up:

    Lithium cell hacked into auto escape tool
    Lithium cell hacked into auto escape tool

    The CR123 puts out enough juice to light up the LED, but it’d be happier with a bit more current. There’s no limiting resistor, so the LED gets what it gets.

    Augment the screws with a few snippets of Kapton tape, use some real 3M Velcro tape, and it’s all good (albeit ugly on a stick):

    Hacked auto escape hammer
    Hacked auto escape hammer

    Now, there’s no way to test the hammer part of it (perhaps I could visit a junkyard and whack out a few windows for practice?), but at least now we have a disposable flashlight in the van…