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: Thing-O-Matic

Using and tweaking a Makerbot Thing-O-Matic 3D printer

  • Wouxun KG-UV3D Battery Contact Locations

    Having gone to great pains to put the center of the contact studs on the GPS+voice case exactly at the center of the screws on the back of the radio:

    HT-GPS Case - Wouxun KG-UV3D rear view
    HT-GPS Case – Wouxun KG-UV3D rear view

    I now discover why Wouxun used 7 mm square pads on the batteries: the springy contacts hit the pack so far off-center from the studs that they very nearly miss the heads on the 4-40 brass screws I’m using as contacts. This family portrait shows the radio, the battery pack, and the GPS+voice case:

    Wouxun KG-UV3D - battery contact locations - GPS case
    Wouxun KG-UV3D – battery contact locations – GPS case

    The lines on the masking tape highlight where the spring contacts touch the case and barely kiss the screw heads:

    KG-UV3D contact marks on GPS case
    KG-UV3D contact marks on GPS case

    Squinting at the marks on the battery case contacts (you can’t see it in the pictures), the contact line is maybe 2.5 mm beyond the centerline of the square pads. How this worked on the first case I built, I have no clue. For this version, I deliberately filed the heads a bit less and recessed them into the case a bit more; obviously, that was the wrong thing to do, as the connection was intermittent at best.

    For the purposes of getting things working, I wrapped snippets of copper mesh tape (from NASA, according to the surplus blurb, with conductive adhesive) around thin chunks of conductive foam, then put them over the studs. The scars in the plastic came from an abortive attempt to get the springs far enough into the case surface to kiss the very edge of the studs:

    Copper mesh on GPS case contacts
    Copper mesh on GPS case contacts

    There’s no point in having a contact patch on the near side of the radio springs, because nothing ever touches there. So the right thing to do is simply move the contact studs to the far side by 3 mm, centering them around the actual contact point. That means changing the PCB layout by the same amount. That’s easy enough to do, but … drat!

    When I took the case apart to boost the mic gain, I replaced those neatly filed studs with unfiled pan head 4-40 brass screws from the same parts stock. The heads were tall enough to touch the radio spring contacts closer to their centers and make perfect contact. Not elegant, but better than that copper braid tape.

    The one thing I do not like about the Wouxun battery packs: the radio contact pads are flush with the pack surface, so there’s absolutely no protection against casual shorts when the pack isn’t on the radio. The packs also sport four bare round contacts on their outer surface that mate with the charger, two of which make direct contact with the battery; those sit inside a shallow molded recess that helps prevent inadvertent shorts.

    assume there’s a protective circuit inside the pack that turns off the current on a dead short, but I am most assuredly not going to test that assumption. When the packs aren’t on the radio (which they never will be, effective immediately), they sport a strip of tape across those radio contact pads.

  • Longboard Lighting Case: Final Edition

    After our Larval Engineer allowed as how OpenSCAD’s learning curve was rather too steep, I punched a few holes in the solid model of the case for the Longboard Ground Effect Lighting controller:

    Longboard Case Solid Model - with holes
    Longboard Case Solid Model – with holes

    Those rounded corners sucked the Kapton tape right off the build platform as the massive shape shrank. The top layer was the worst offender, with 1.4 mm of clearance (shown with that tapered scale) under one corner:

    Longboard case - warped corner
    Longboard case – warped corner

    The warping doesn’t matter much, because the case will be compression-loaded by screws and wave washers in the corners. We may need to fill or level the warp to keep the polycarbonate cover flat, though.

    I thought about putting a support structure in the rectangular power switch opening, then decided to just try it and see what happens. It turned out fine; this view looks up toward the as-printed top of the opening (the camera’s barrel distortion makes the curve on the bottom surface look worse than it is):

    Longboard case - switch hole overhang
    Longboard case – switch hole overhang

    Four stacked lithium cells produce upwards of 14.8 V, considerably more than those poor 12 V LED strips prefer to see, so I had her take some current vs. voltage data. She figured out how to convert 10-bit ADC values into battery voltage, after which she could, if she wanted to, beat her Arduino sketch into limiting the maximum PWM duty cycle to hold the LED power dissipation down to a reasonable number. Right now, it’s set to a fixed 25% and is way bright.

    Longboard with variable RGB LED Ground Effect lighting
    Longboard with variable RGB LED Ground Effect lighting

    A truly crappy First Light video taken in the driveway is there. She’s been doing the Happy Dance all day… and promises to document the whole project in gruesome detail.

    The OpenSCAD source code:

    // Longboard Ground Effect Lighting Controller Case
    // Ed Nisley KE4ZNU
    // Karen Nisley KC2SYU
    // August 2012
    
    // Layout options
    
    Layout = "Build3";
    					// Overall layout: Fit Show
    					// Printing plates: Build1 .. Buildn (see bottom!)
    					// Parts: BatteryLayer PCBLayer1 PCBLayer2
    					// Shapes: CaseShell PCBEnvelope
    
    ShowGap = 5;		// spacing between parts in Show layout
    
    //-----
    // Extrusion parameters must match reality!
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.2;
    
    //-- Handy stuff
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1;			// make holes end cleanly
    
    inch = 25.4;
    
    Tap10_32 = 0.159 * inch;
    Clear10_32 = 0.190 * inch;
    Head10_32 = 0.373 * inch;
    Head10_32Thick = 0.110 * inch;
    Nut10_32Dia = 0.433 * inch;
    Nut10_32Thick = 0.130 * inch;
    Washer10_32OD = 0.381 * inch;
    Washer10_32ID = 0.204 * inch;
    
    //----------------------
    // Dimensions
    
    CellWidth = 50.0;						// Lithium-ion cell dimensions
    CellLength = 60.0;
    CellThick = 6.0;
    CellClearance = 1.5;					// on all sides
    CellTabClearance = 15.0;				// for connections
    
    CellHoldWidth = 6.0;					// edge to tabs
    CellHoldLength = 4*ThreadWidth;
    
    CellCount = 4;						// cells in the battery
    
    BatteryHeight = CellCount*CellThick + 2*CellClearance;
    BatteryLength = CellLength + 2*CellClearance;
    BatteryWidth = CellWidth + 2*CellClearance;
    
    PCMWidth = 16.0;						// Battery protection module
    PCMLength = 51.0;
    PCMThick = 4.0;							// at terminal end of cells
    
    PillarOD = Washer10_32OD + 2*1.0;		// screw pillar diameter
    PillarOffset = (PillarOD/2) / sqrt(2.0);	// distance to case inside corner
    
    WallThick = 7.5;						// case wall thickness
    
    PinOD = 1.4;							// alignment pin size
    
    CaseInsideLength = BatteryLength + CellTabClearance + PCMThick;
    CaseOALength = CaseInsideLength + 2*WallThick;
    echo("Box Length outside: ",CaseOALength);
    echo("            inside: ",CaseInsideLength);
    
    WiringLength = CaseInsideLength - CellLength - CellHoldLength - PCMThick;	// wiring space at PCM
    echo("Wiring length: ",WiringLength);
    
    CaseInsideWidth = BatteryWidth;
    CaseOAWidth = CaseInsideWidth + 2*WallThick;
    echo("Box Width outside: ",CaseOAWidth);
    echo("           inside: ",CaseInsideWidth);
    echo("Screw OC length: ",CaseInsideLength + 2*PillarOffset);
    echo("          width: ",CaseInsideWidth + 2*PillarOffset);
    
    PCBThick = 2.0;							// PCB thickness
    PCBMargin = 3.0;						// clamping margin around PCB edge
    PartHeight = 17.0;						// height of components above PCB (mind the switch!)
    WiringThick = 5.0;						// wiring below PCB
    
    echo("PCB thickness:",PCBThick);
    echo("    clamp margin: ",PCBMargin);
    echo("    wiring: ",WiringThick);
    echo("    components: ",PartHeight);
    
    PCBLayer1Thick = IntegerMultiple(WiringThick + PCBThick/2,ThreadThick);
    PCBLayer2Thick = IntegerMultiple(PartHeight + PCBThick/2,ThreadThick);
    
    echo("Battery compartment height: ",BatteryHeight);
    echo("PCB Layer 1 height: ",PCBLayer1Thick);
    echo("PCB Layer 2 height: ",PCBLayer2Thick);
    
    PlateThick = 1/16 * inch;				// aluminum mount / armor plates
    
    echo("Total height: ",2*PlateThick + BatteryHeight + PCBLayer1Thick + PCBLayer2Thick);
    
    ChargePlugOD = 11.5;					// battery charger plug
    ChargeJackHeightOC = 6.5;				// coaxial jack center pin height from PCB
    
    SwitchLength = 20.0;					// master power switch
    SwitchWidth = 13.0;
    
    WheelCableOD = 3.0;						// 3-conductor from wheel rotation sensor
    
    LEDCableWidth = 10.0;					// 6 conductor loose wires to LED strips
    LEDCableThick = 2.0;
    
    //----------------------
    // 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);
    
    }
    
    //-------------------
    // Shapes
    
    module CaseShell(h=1.0) {
    
      difference() {
    	union() {
    	  translate([0,0,h/2])
    		cube([CaseOALength,CaseOAWidth,h],center=true);
    
    	  for (x=[-1,1])
    		for (y=[-1,1])
    		  translate([x*(PillarOffset + CaseInsideLength/2),
    					y*(PillarOffset + CaseInsideWidth/2),
    					h/2])
    			cylinder(r=PillarOD/2,h,center=true,$fn=4*6);
    	}
    
    	for (x=[-1,1])					// screw holes on corners
    	  for (y=[-1,1])
    		translate([x*(PillarOffset + CaseInsideLength/2),
    				  y*(PillarOffset + CaseInsideWidth/2),
    				  -Protrusion])
    		  PolyCyl(Clear10_32,(h + 2*Protrusion),8);
    
    	for (x=[-1,1])					// alignment pins in width walls
    	  translate([x*(CaseOALength - WallThick)/2,0,-Protrusion])
    	  rotate(45)
    		  PolyCyl(PinOD,(h + 2*Protrusion));
    	for (y=[-1,1])					// alignment pins in length walls
    	  translate([0,y*(CaseOAWidth - WallThick)/2,-Protrusion])
    	  rotate(45)
    		  PolyCyl(PinOD,(h + 2*Protrusion));
    
      }
    }
    
    module BatteryLayer() {
    
      difference() {
    	CaseShell(BatteryHeight);
    
        translate([0,0,BatteryHeight/2]) {
    	  union() {
    		translate([-(CaseInsideLength/2 - BatteryLength/2),0,0])
    		  cube([BatteryLength,
    			   BatteryWidth,
    			   BatteryHeight + 2*Protrusion],
    			   center=true);
    		cube([CaseInsideLength,
    			 (BatteryWidth - 2*CellHoldWidth),
    			 BatteryHeight + 2*Protrusion],
    			 center = true);
    		translate([(CaseInsideLength/2 - WiringLength/2),0,0])
    		  cube([WiringLength,
    				max(BatteryWidth,PCMLength),
    				BatteryHeight + 2*Protrusion],
    				  center=true);
    	  }
    	}
      }
    }
    
    module PCBEnvelope() {
    
      union() {
    	translate([0,0,WiringThick + PCBThick + PartHeight/2])
    	  cube([CaseInsideLength - 2*PCBMargin,
    		   CaseInsideWidth - 2*PCBMargin,
    		   PartHeight + 2*Protrusion],
    		   center=true);
    
    	translate([0,0,WiringThick + PCBThick/2])
    	  cube([CaseInsideLength,CaseInsideWidth,PCBThick],center=true);
    
    	translate([0,0,WiringThick/2])
    	  cube([CaseInsideLength - 2*PCBMargin,
    		   CaseInsideWidth - 2*PCBMargin,
    		   WiringThick + 2*Protrusion],
    		   center=true);
      }
    }
    
    module PCBLayer1() {
    
      difference() {
    	CaseShell(PCBLayer1Thick);
    	PCBEnvelope();
      }
    
    }
    
    module PCBLayer2() {
    
      difference() {
    	CaseShell(PCBLayer2Thick);
    	translate([0,0,-(WiringThick + PCBThick/2)])
    	  PCBEnvelope();
    	translate([25,0,(PCBThick/2 + ChargeJackHeightOC)])
    	  rotate([90,0,0])
    		PolyCyl(ChargePlugOD,CaseOAWidth);
    	translate([25,CaseOAWidth/2,PCBLayer2Thick/2])
    	  rotate([90,0,0])
    		cube([SwitchLength,SwitchWidth,CaseOAWidth],center=true);
    	translate([-CaseOALength/2,0,PCBThick/2])
    	  rotate([0,-90,0])
    		cube([2*WheelCableOD,WheelCableOD,CaseOALength],center=true);
    	translate([CaseOALength/2,0,PCBThick/2])
    	  rotate([90,0,90])
    		cube([LEDCableWidth,2*LEDCableThick,CaseOALength],center=true);
      }
    
    }
    
    module Aluminum() {
      translate([0,0,PlateThick/2])
    	cube([1.1*CaseOALength,1.1*CaseOAWidth,PlateThick - Protrusion],center=true);
    }
    
    //-------------------
    // Build things...
    
    ShowPegGrid();
    
    if ("Battery" == Layout)
      Battery();
    
    //if ("CaseShell" == Layout)
    //  CaseShell(something here!!!);
    
    if ("BatteryLayer" == Layout)
      BatteryLayer();
    
    if ("PCBEnvelope" == Layout)
      PCBEnvelope();
    
    if ("PCBLayer1" == Layout)
      PCBLayer1();
    
    if ("PCBLayer2" == Layout)
      PCBLayer2();
    
    if ("Fit" == Layout) {
      color("LightBlue") BatteryLayer();
      translate([0,0,BatteryHeight + PlateThick])
    	color("Green") PCBLayer1();
      translate([0,0,BatteryHeight + PlateThick + PCBLayer1Thick])
    	color("Cyan") PCBLayer2();
    }
    
    if ("Show" == Layout) {
      color("LightBlue") BatteryLayer();
      translate([0,0,BatteryHeight + PlateThick + ShowGap])
    	color("Green") PCBLayer1();
      translate([0,0,BatteryHeight + PlateThick + PCBLayer1Thick + 2*ShowGap])
    	color("Cyan") PCBLayer2();
    }
    
    if ("Build1" == Layout)
      rotate(90) BatteryLayer();
    
    if ("Build2" == Layout)
      rotate(90) PCBLayer1();
    
    if ("Build3" == Layout)
      translate([0,0,PCBLayer2Thick])
    	rotate([0,180,90])
    	  PCBLayer2();
    
    
  • TinyTrak3+ Trimpots: Not All Are Created Equal

    I designed the GPS+Audio case around the TinyTrak3+ board in my radio, which has two square, blue-plastic trimpots. The case worked fine for that board. Then I printed the case for the next bike and that TT3+ didn’t slide neatly into place:

    TinyTrak3+ trimpot overhang
    TinyTrak3+ trimpot overhang

    Turns out that one of the three TT3+ boards uses plastic trimpots and the other two have metal trimpots bent to fit the existing holes (so they’re not a drop-in replacement), with a very slight overhang beyond the edge of the PCB.

    So I attacked the case with some riffler files and carved a notch above the PCB slot. No pictures of that, lest you think I’m a butcher of lovely 3D printed objects. Next time: build the notch into the case’s solid model.

    Most likely, this is the only instance of those pots causing anyone a problem…

  • Longboard Ground Effect Lighting Case

    Our Larval Engineer has been diligently procrastinating on her summer project to add ground effect lighting to her longboard. I’m hereby depriving her of the opportunity to learn enough OpenSCAD to build a case from scratch:

    Longboard Ground Effect Lighting Case - exploded view
    Longboard Ground Effect Lighting Case – exploded view

    This is upside-down from its in-use position, but she’ll have it in this orientation on the bench. Four 10-32 screws clamp the whole affair together and hold it to a bottom aluminum plate with threads to suit; that plate also gets bolted between the longboard and the rear truck.

    The general idea is that four 2 A·h lithium prismatic cells live in the bottom slice with their protection circuit, sandwiched between two aluminum plates that should protect them from all but catastrophic impact. The circuit board (which ought to be a PCB, but we’ll go with hand wiring for the first iteration) gets clamped in the recess between the two upper slices, above the upper aluminum plate. A polycarbonate sheet on top provides visibility for the Arduino blinky LED inside and shows off the circuitry to one and all.

    I think a ridge on each long wall should suffice to hold the cells against the end wall; we don’t have the cells in hand to figure that out yet. She gets to add internal partitions, cable cutouts, and suchlike.

    Oh. “Ground effect lighting” means ten RGB LED strips glued under the longboard deck. Her innovation is to make the LED color depend on the speed, which can range upward to scary-fast. It’s a simple matter of software, using a Hall effect sensor for input. This will look much better after dark, but she’s pretty much nocturnal anyway.

    The OpenSCAD source code:

    // Longboard Ground Effect Lighting Controller Case
    // Ed Nisley KE4ZNU
    // Karen Nisley KC2SYU
    // July 2012
    
    // Layout options
    
    Layout = "Show";
     // Overall layout: Fit Show
     // Printing plates: Build1 .. Buildn (see bottom!)
     // Parts: BatteryLayer PCBLayer1 PCBLayer2
     // Shapes: CaseShell PCBEnvelope
    
    ShowGap = 5; // spacing between parts in Show layout
    
    //-----
    // Extrusion parameters must match reality!
    
    ThreadThick = 0.25;
    ThreadWidth = 2.0 * ThreadThick;
    
    HoleWindage = 0.2;
    
    //-- Handy stuff
    
    function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
    
    Protrusion = 0.1; // make holes end cleanly
    
    inch = 25.4;
    
    Tap10_32 = 0.159 * inch;
    Clear10_32 = 0.190 * inch;
    Head10_32 = 0.373 * inch;
    Head10_32Thick = 0.110 * inch;
    Nut10_32Dia = 0.433 * inch;
    Nut10_32Thick = 0.130 * inch;
    Washer10_32OD = 0.381 * inch;
    Washer10_32ID = 0.204 * inch;
    
    //----------------------
    // Dimensions
    
    CellWidth = 50.0; // Lithium-ion cell dimensions
    CellLength = 60.0;
    CellThick = 6.0;
    CellClearance = 1.5; // on all sides
    CellTabClearance = 10.0; // for connections
    
    BatteryCount = 4; // cells in the battery
    BatteryHeight = BatteryCount*CellThick + 2*CellClearance;
    
    PCMWidth = 16.0; // Battery protection board
    PCMLength = 50.0;
    PCMThick = 4.0; // at terminal end of cells
    
    PillarOD = Washer10_32OD + 2*0.5; // screw pillar diameter
    PillarOffset = (PillarOD/2) / sqrt(2.0); // distance to case inside corner
    
    WallThick = 6.0; // case wall thickness
    
    PinOD = 1.4; // alignment pin size
    
    CaseOALength = CellLength + CellClearance + CellTabClearance + PCMThick + 2*WallThick;
    CaseInsideLength = CaseOALength - 2*WallThick;
    echo("Box Length outside: ",CaseOALength);
    echo(" inside: ",CaseInsideLength);
    
    CaseOAWidth = CellWidth + 2*CellClearance + 2*WallThick;
    CaseInsideWidth = CaseOAWidth - 2*WallThick;
    echo("Box Width outside: ",CaseOAWidth);
    echo(" inside: ",CaseInsideWidth);
    
    CaseOAHeight = BatteryCount * CellThick + CellClearance;
    
    PCBThick = 1.0; // PCB thickness
    PCBMargin = 3.0; // clamping margin around PCB edge
    PartHeight = 10.0; // height of components above PCB
    WiringThick = 4.0; // wiring below PCB
    
    echo("PCB thickness:",PCBThick);
    echo(" clamp margin: ",PCBMargin);
    echo(" wiring: ",WiringThick);
    echo(" components: ",PartHeight);
    
    PCBLayer1Thick = IntegerMultiple(WiringThick + PCBThick/2,ThreadThick);
    PCBLayer2Thick = IntegerMultiple(PartHeight + PCBThick/2,ThreadThick);
    
    echo("Battery compartment height: ",BatteryHeight);
    echo("PCB Layer 1 height: ",PCBLayer1Thick);
    echo("PCB Layer 2 height: ",PCBLayer2Thick);
    
    PlateThick = 1/16 * inch; // aluminum mount / armor plates
    
    echo("Total height: ",2*PlateThick + BatteryHeight + PCBLayer1Thick + PCBLayer2Thick);
    
    //----------------------
    // 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);
    
    }
    //-------------------
    // Shapes
    
    module CaseShell(h=1.0) {
    
    difference() {
     union() {
     translate([0,0,h/2])
     cube([CaseOALength,CaseOAWidth,h],center=true);
    
    for (x=[-1,1])
     for (y=[-1,1])
     translate([x*(PillarOffset + CaseInsideLength/2),
     y*(PillarOffset + CaseInsideWidth/2),
     h/2])
     cylinder(r=PillarOD/2,h,center=true,$fn=4*6);
     }
    
    for (x=[-1,1]) // screw holes on corners
     for (y=[-1,1])
     translate([x*(PillarOffset + CaseInsideLength/2),
     y*(PillarOffset + CaseInsideWidth/2),
     -Protrusion])
     PolyCyl(Clear10_32,(h + 2*Protrusion),8);
    
    for (x=[-1,1]) // alignment pins in width walls
     translate([x*(CaseOALength - WallThick)/2,0,-Protrusion])
     rotate(45)
     PolyCyl(PinOD,(h + 2*Protrusion));
     for (y=[-1,1]) // alignment pins in length walls
     translate([0,y*(CaseOAWidth - WallThick)/2,-Protrusion])
     rotate(45)
     PolyCyl(PinOD,(h + 2*Protrusion));
    
    }
    }
    
    module BatteryLayer() {
    
    difference() {
     CaseShell(BatteryHeight);
    
    translate([0,0,BatteryHeight/2])
     cube([CaseOALength - 2*WallThick,
     CaseOAWidth - 2*WallThick,
     BatteryHeight + 2*Protrusion],
     center=true);
     }
    }
    
    module PCBEnvelope() {
    
    union() {
     translate([0,0,WiringThick + PCBThick + PartHeight/2])
     cube([CaseInsideLength - 2*PCBMargin,
     CaseInsideWidth - 2*PCBMargin,
     PartHeight + 2*Protrusion],
     center=true);
    
    translate([0,0,WiringThick + PCBThick/2])
     cube([CaseInsideLength,CaseInsideWidth,PCBThick],center=true);
    
    translate([0,0,WiringThick/2])
     cube([CaseInsideLength - 2*PCBMargin,
     CaseInsideWidth - 2*PCBMargin,
     WiringThick + 2*Protrusion],
     center=true);
     }
    }
    
    module PCBLayer1() {
    
    difference() {
     CaseShell(PCBLayer1Thick);
     PCBEnvelope();
     }
    
    }
    
    module PCBLayer2() {
    
    difference() {
     CaseShell(PCBLayer2Thick);
     translate([0,0,-(WiringThick + PCBThick/2)])
     PCBEnvelope();
     }
    
    }
    
    module Aluminum() {
     translate([0,0,PlateThick/2])
     cube([1.1*CaseOALength,1.1*CaseOAWidth,PlateThick - Protrusion],center=true);
    }
    
    //-------------------
    // Build things...
    
    ShowPegGrid();
    
    if ("Battery" == Layout)
     Battery();
    
    if ("CaseShell" == Layout)
     CaseShell(CaseOAHeight);
    
    if ("BatteryLayer" == Layout)
     BatteryLayer();
    
    if ("PCBEnvelope" == Layout)
     PCBEnvelope();
    
    if ("PCBLayer1" == Layout)
     PCBLayer1();
    
    if ("PCBLayer2" == Layout)
     PCBLayer2();
    
    if ("Fit" == Layout) {
     BatteryLayer();
     translate([0,0,BatteryHeight + PlateThick])
     color("Green") PCBLayer1();
     translate([0,0,BatteryHeight + PlateThick + PCBLayer1Thick])
     color("Cyan") PCBLayer2();
    }
    
    if ("Show" == Layout) {
     BatteryLayer();
     translate([0,0,BatteryHeight + PlateThick + ShowGap])
     color("Green") PCBLayer1();
     translate([0,0,BatteryHeight + PlateThick + PCBLayer1Thick + 2*ShowGap])
     color("Cyan") PCBLayer2();
    }
    
    if ("Build1" == Layout)
     rotate(90) BatteryLayer();
    
    if ("Build2" == Layout)
     rotate(90) PCBLayer1();
    
    if ("Build3" == Layout)
     translate([0,0,PCBLayer2Thick])
     rotate([0,180,90])
     PCBLayer2();
    
  • Wouxun KG-UV3D Plug Plate

    Based on those measurements that suggest spacing the plugs at 11.5 mm on center, I tweaked that parameter in the source code there and printed another one, just like the other one. Actually, I printed four of the fool things this time:

    Wouxun plug plates - 11.5 mm fixture
    Wouxun plug plates – 11.5 mm fixture

    With the plugs in the gluing fixture and the fixture in the vise, a ring of epoxy around the threaded sides holds them in place:

    Wouxun plug plate - wired
    Wouxun plug plate – wired

    A trial fit in the Wouxun KG-UV3D shows that the jacks prefer the 11.2 mm spacing I measured on the Wouxun headset, but they’ll accept plugs on 11.5 mm centers. I don’t know if that’s a real specification difference, a manufacturing tolerance, or what.

    FWIW, I’ve been using snippets of that cable forever, because it’s perfect for this application: two unshielded conductors and three more inside a braid, supple as a snake. It’s surplus, of course, with a gorgeous push-lock plug (and the jack!) on one end that must have cost a fortune… and which I’ll never to use for anything. Got two of them, just in case.

    Mushing an epoxy putty turd on the top anchors everything in place and protects the wires:

    Wouxun plug plate - epoxy cap
    Wouxun plug plate – epoxy cap

    In point of fact, the cable insulation isn’t anchored inside the blob and a minor tug could pull it loose. There will be a bit of slack at the case to allow for unlatching it from the radio, but the lashup will spend its entire life inside a snug pouch, so it shouldn’t come to any harm. We shall see.

  • Kenwood / Wouxun Headset Jack Spacing

    Wouxun plug mounting plate - overview
    Wouxun plug mounting plate – overview

    Try as I might, I cannot uncover a definitive answer to this simple question: What’s the center-to-center spacing of the mic and earphone jacks on the side of Kenwood and Wouxun HTs?

    The usual searches produce answers like 11 and 12 mm, both of which are obviously wrong, as can be determined eyeballometrically just by holding a scale against the plugs.

    Based on measurements I made on a Wouxun headset, the yellow plug mounting plate put the plugs on 11.2 mm centers and they fit into the KG-UV3D radio; it’s been working fine ever since.

    However, having just measured a speaker/mic and a headset, both from Kenwood, I come up with 11.5 mm. Frankly, I trust the Kenwood hardware a bit more: the plugs seem more rugged and the overall production values are higher.

    The calculation is simple: measure the pin diameters, then subtract half their sum from the outside distance across the pins. Cross-check by adding half the sum to the inside distance between the pins, which should give the same answer. It helps if the pins are actually round.

    The jacks in the Kenwood and Wouxun radios have enough compliance to accept either a Wouxun or a Kenwood headset plug without complaint. Maybe it doesn’t matter?

    Despite that, I made another gluing fixture with 11.5 mm spacing:

    Plug alignment plate - 11.5 mm spacing
    Plug alignment plate – 11.5 mm spacing

    Those are 0.1 inch grids; it’s a little bitty block of smoke-gray polycarbonate from the scrap heap. The plugs are nominally 3.5 mm (which is not 1/8 inch in this universe) and 2.5 mm, with clearance drills #28 and #39.

    Then I tried poking those 11.2 mm spaced plugs, now firmly epoxied in place in the yellow plate, and guess what: they don’t fit, no how no way. That’s not surprising, because there’s no compliance on either side of the joint and the plugs aren’t on the right centers for the fixture. Makes for a good No-Go gauge, I suppose.

    However, I think I’ll tweak the solid model spacing to 11.5 mm and run off another plug mounting plate for the next radio.

    FWIW, our ICOM IC-Z1A HTs use a sensible 10.0 mm spacing and that old fixture worked fine.

  • HT GPS+Voice: Battery Contacts

    For this version of the contacts (the old version is there) that make the GPS interface look like a standard Wouxun lithium battery, I left a bit more of the slot on the brass screw heads and increased the recess depth to compensate:

    HT-GPS Case - Battery contacts
    HT-GPS Case – Battery contacts

    The nuts all have fancy nickel plating, with washers & ring lugs silver-soldered in place:

    HT-GPS PCB - battery contact parts
    HT-GPS PCB – battery contact parts

    The trial fit looks OK:

    HT-GPS Case - PCB and battery contacts - end view
    HT-GPS Case – PCB and battery contacts – end view

    I even found the cutest little flat 1/4 inch wrench that fits 4-40 nuts, so I can do a better job of crunching the PCB between the nuts. That excess screw length has got to go, too…