-
Vacuum Tube LEDs: Noval Tube on a Platter
Replacing the hex nut traps with knurled insert cylinders slims the ends of the socket:

Noval Socket – knurled inserts – bottom – Slic3r preview Making the raised part of the socket fit the 25 mm ID of a hard drive platter swells the midsection of the socket
, but the platter won’t need any machining or punching:
Noval Socket – knurled inserts – top – Slic3r preview The octal and duodecar sockets will require a punch to open up the platter hole and all sockets require two drilled clearance holes for the screws. Given that I’ll eventually do this on the Sherline, maybe milling the hole for the bigger tubes will be faster & easier than manually punching them.
I moved the screw centers to 35 mm (from the historically accurate 28 mm) to accommodate the larger center, not that anybody will ever notice, and enlarged the central hole to 7.5 mm (from 5.0 mm) to let more light into the tube base.
The support structures inside the (now much smaller) knurled insert cylinders might not be strictly necessary, but I left them in place to see how well they built. Which was perfectly, as it turns out, and they popped out with a slight push:

Noval socket – knurled inserts – support structures They’re just the cutest little things (those are 0.100 inch grid squares in the background):

Noval socket – support structures Anyhow, the knurled inserts pressed into their holes with a slight shove:

Noval socket – installing knurled insert The chuck jaws were loose on the screw cutoff stud and stopped at the surface, putting the knurled inserts perfectly flush with the socket:

Noval socket – knurled inserts – installed The surface looks very slightly distorted around the inserts, although it’s still smooth to the touch, and I think the PETG will slowly relax around the knurls. Even without heat or epoxy, they’re now impossible to pull out with any force I’m willing to apply to the screws threaded into them. Given that the platter screws will (be trying to) pull the inserts through the socket, I think a dry install will suffice for my simple needs.
Match-mark, drill #27 6-32 clearance holes, and the screws drop right in:

Noval socket – installed Those stainless steel pan-head 6-32 screws seem a bit large in comparison with the socket. Perhaps I should use 4-40 screws, even though they’re not, ahem, historically accurate.
The tube pin holes get hand-reamed with a #53 drill = 1.5 mm. That’s a bit over the nominal 1.1 mm pin diameter, but seems to provide both easy insertion and firm retention. For permanent installation, an adhesive would be in order.
Buff off the fingerprints, stick the tube in place, and it looks pretty good:

Noval socket – tube on platter Yeah, those screws are too big. Maybe a brace of black M3 socket head screws would look better, despite a complete lack of historicity.
Now to wire it up and ponder how to build a base.
The OpenSCAD source code as a GitHub Gist:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// Vacuum Tube LED Lights // Ed Nisley KE4ZNU February 2016 Layout = "Socket"; // Cap LampBase USBPort Socket(s) (Build)FinCap DefaultSocket = "Noval"; Section = false; // cross-section the object Support = true; //- Extrusion parameters must match reality! ThreadThick = 0.25; ThreadWidth = 0.40; HoleWindage = 0.2; Protrusion = 0.1; // make holes end cleanly inch = 25.4; function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit); //———————- // Dimensions // https://en.wikipedia.org/wiki/Tube_socket#Summary_of_Base_Details // punch & screw OC modified for drive platter chassis plate // platter = 25 mm ID T_NAME = 0; // common name T_NUMPINS = 1; // total, with no allowance for keying T_PINBCD = 2; // tube pin circle diameter T_PINOD = 3; // … diameter T_PINLEN = 4; // … length (overestimate) T_HOLEOD = 5; // nominal panel hole from various sources T_PUNCHOD = 6; // panel hole optimized for inch-size Greenlee punches T_TUBEOD = 7; // envelope or base diameter T_PIPEOD = 8; // light pipe from LED to tube base T_SCREWOC = 9; // mounting screw holes // Name pins BCD dia length hole punch env pipe screw TubeData = [ ["Mini7", 8, 9.53, 1.016, 7.0, 16.0, 25.0, 18.0, 5.0, 35.0], // punch 11/16, screw 22.5 OC ["Octal", 8, 17.45, 2.36, 10.0, 36.2, (8 + 1)/8 * inch, 32.0, 11.5, 39.0], ["Noval", 10, 11.89, 1.1016, 7.0, 22.0, 25.0 , 21.0, 7.5, 35.0], // punch 7/8, screw 28.0 OC ["Duodecar", 13, 19.10, 1.05, 9.0, 32.0, (4 + 1)/4 * inch, 38.0, 12.5, 39.0], // aka Compactron ]; ID = 0; OD = 1; LENGTH = 2; Pixel = [7.0,10.0,3.0]; // ID = contact patch, OD = PCB dia, LENGTH = overall thickness Nut = [3.5,5.2,7.2]; // socket mounting nut recess — threaded insert NutSides = 8; BaseShim = 2*ThreadThick; // between pin holes and pixel top SocketFlange = 2.0; // rim around socket below punchout PanelThick = 1.5; // socket extension through punchout FinCutterOD = 1/8 * inch; FinCapSize = [(Pixel[OD] + 2*FinCutterOD),30.0,(10.0 + 2*Pixel[LENGTH])]; //———————- // 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); } //———————- // Tube cap CapTube = [4.0,3/16 * inch,10.0]; // brass tube for flying lead to cap LED CapSize = [Pixel[ID],(Pixel[OD] + 3.0),(CapTube[OD] + 2*Pixel[LENGTH])]; CapSides = 6*4; module Cap() { difference() { union() { cylinder(d=CapSize[OD],h=(CapSize[LENGTH]),$fn=CapSides); // main cap body translate([0,0,CapSize[LENGTH]]) // rounded top scale([1.0,1.0,0.65]) sphere(d=CapSize[OD]/cos(180/CapSides),$fn=CapSides); // cos() fixes slight undersize vs cylinder cylinder(d1=(CapSize[OD] + 2*3*ThreadWidth),d2=CapSize[OD],h=1.5*Pixel[LENGTH],$fn=CapSides); // skirt } translate([0,0,-Protrusion]) // bore for wiring to LED PolyCyl(CapSize[ID],(CapSize[LENGTH] + 3*ThreadThick + Protrusion),CapSides); translate([0,0,-Protrusion]) // PCB recess with clearance for tube dome PolyCyl(Pixel[OD],(1.5*Pixel[LENGTH] + Protrusion),CapSides); translate([0,0,(1.5*Pixel[LENGTH] – Protrusion)]) // small step + cone to retain PCB cylinder(d1=(Pixel[OD]/cos(180/CapSides)),d2=Pixel[ID],h=(Pixel[LENGTH] + Protrusion),$fn=CapSides); translate([0,0,(CapSize[LENGTH] – CapTube[OD]/(2*cos(180/8)))]) // hole for brass tube holding wire loom rotate([90,0,0]) rotate(180/8) PolyCyl(CapTube[OD],CapSize[OD],8); } } //———————- // Heatsink tube cap module FinCap() { CableOD = 3.5; // cable + braid diameter BulbOD = 3.75 * inch; // bulb OD; use 10 inches for flat echo(str("Fin Cutter: ",FinCutterOD)); FinSides = 2*4; BulbRadius = BulbOD / 2; BulbDepth = BulbRadius – sqrt(pow(BulbRadius,2) – pow(FinCapSize[OD],2)/4); echo(str("Bulb OD: ",BulbOD," recess: ",BulbDepth)); NumFins = floor(PI*FinCapSize[ID] / (2*FinCutterOD)); FinAngle = 360 / NumFins; echo(str("NumFins: ",NumFins," angle: ",FinAngle," deg")); difference() { union() { cylinder(d=FinCapSize[ID],h=FinCapSize[LENGTH],$fn=2*NumFins); // main body for (i = [0:NumFins – 1]) // fins rotate(i * FinAngle) hull() { translate([FinCapSize[ID]/2,0,0]) rotate(180/FinSides) cylinder(d=FinCutterOD,h=FinCapSize[LENGTH],$fn=FinSides); translate([(FinCapSize[OD] – FinCutterOD)/2,0,0]) rotate(180/FinSides) cylinder(d=FinCutterOD,h=FinCapSize[LENGTH],$fn=FinSides); } rotate(FinAngle/2) // cable entry boss translate([FinCapSize[ID]/2,0,FinCapSize[LENGTH]/2]) cube([FinCapSize[OD]/4,FinCapSize[OD]/4,FinCapSize[LENGTH]],center=true); } for (i = [1:NumFins – 1]) // fin inner gullets, omit cable entry side rotate(i * FinAngle + FinAngle/2) // joint isn't quite perfect, but OK translate([FinCapSize[ID]/2,0,-Protrusion]) rotate(0*180/FinSides) cylinder(d=FinCutterOD/cos(180/FinSides),h=(FinCapSize[LENGTH] + 2*Protrusion),$fn=FinSides); translate([0,0,-Protrusion]) // PCB recess PolyCyl(Pixel[OD],(1.5*Pixel[LENGTH] + Protrusion),FinSides); PolyCyl(Pixel[ID],(FinCapSize[LENGTH] – 3*ThreadThick),FinSides); // bore for LED wiring translate([0,0,(FinCapSize[LENGTH] – 3*ThreadThick – 2*CableOD/(2*cos(180/8)))]) // cable inlet rotate(FinAngle/2) rotate([0,90,0]) rotate(180/8) PolyCyl(CableOD,FinCapSize[OD],8); if (BulbOD <= 10.0 * inch) // curve for top of bulb translate([0,0,-(BulbRadius – BulbDepth + 2*ThreadThick)]) // … slightly flatten tips sphere(d=BulbOD,$fn=16*FinSides); } } //———————- // Aperture for USB-to-serial adapter snout // These are all magic numbers, of course module USBPort() { translate([0,28.0]) rotate([90,0,0]) linear_extrude(height=28.0) polygon(points=[ [0,0], [8.0,0], [8.0,4.0], // [4.0,4.0], [4.0,6.5], [-4.0,6.5], // [-4.0,4.0], [-8.0,4.0], [-8.0,0], ]); } //———————- // Box for Leviton ceramic lamp base module LampBase() { Bottom = 3.0; Base = [4.0*inch,4.5*inch,20.0 + Bottom]; Sides = 12*4; Retainer = [3.5,11.0,1.0]; // flat fiber washer holding lamp base screws in place StudSides = 8; StudOC = 3.5 * inch; Stud = [Nut[OD], // 6-32 tapped brass insert min(15.0,1.5*(Base[ID] – StudOC)/cos(180/StudSides)), // OD = big enough to merge with walls (Base[LENGTH] – Retainer[LENGTH])]; // leave room for retainer union() { difference() { rotate(180/Sides) cylinder(d=Base[OD],h=Base[LENGTH],$fn=Sides); rotate(180/Sides) translate([0,0,Bottom]) cylinder(d=Base[ID],h=Base[LENGTH],$fn=Sides); translate([0,-Base[OD]/2,Bottom + 1.2]) // mount on double-sided foam tape rotate(0) USBPort(); } for (i = [-1,1]) translate([i*StudOC/2,0,0]) rotate(180/StudSides) difference() { cylinder(d=Stud[OD],h=Stud[LENGTH],$fn=StudSides); translate([0,0,Bottom]) PolyCyl(Stud[ID],(Stud[LENGTH] – (Bottom – Protrusion)),6); } } } //———————- // Tube Socket module Socket(Name = DefaultSocket) { NumSides = 6*4; Tube = search([Name],TubeData,1,0)[0]; echo(str("Building ",TubeData[Tube][0]," socket")); echo(str(" Punch: ",TubeData[ID][T_PUNCHOD]," mm = ",TubeData[ID][T_PUNCHOD]/inch," inch")); echo(str(" Screws: ",TubeData[ID][T_SCREWOC]," mm =",TubeData[ID][T_SCREWOC]/inch," inch OC")); OAH = Pixel[LENGTH] + BaseShim + TubeData[Tube][T_PINLEN]; BaseHeight = OAH – PanelThick; difference() { union() { linear_extrude(height=BaseHeight) hull() { circle(d=(TubeData[Tube][T_PUNCHOD] + 2*SocketFlange),$fn=NumSides); for (i=[-1,1]) translate([i*TubeData[Tube][T_SCREWOC]/2,0]) circle(d=2.0*Nut[OD],$fn=NumSides); } cylinder(d=TubeData[Tube][T_PUNCHOD],h=OAH,$fn=NumSides); // boss in chassis punch hole } for (i=[0:(TubeData[Tube][T_NUMPINS] – 1)]) // tube pins rotate(i*360/TubeData[Tube][T_NUMPINS]) translate([TubeData[Tube][T_PINBCD]/2,0,(OAH – TubeData[Tube][T_PINLEN])]) rotate(180/4) PolyCyl(TubeData[Tube][T_PINOD],(TubeData[Tube][T_PINLEN] + Protrusion),4); for (i=[-1,1]) // mounting screw holes & nut traps / threaded inserts translate([i*TubeData[Tube][T_SCREWOC]/2,0,-Protrusion]) { PolyCyl(Nut[OD],(Nut[LENGTH] + Protrusion),NutSides); PolyCyl(Nut[ID],(OAH + 2*Protrusion),NutSides); } translate([0,0,-Protrusion]) { // LED recess PolyCyl(Pixel[OD],(Pixel[LENGTH] + Protrusion),8); } translate([0,0,(Pixel[LENGTH] – Protrusion)]) { // light pipe rotate(180/TubeData[Tube][T_NUMPINS]) PolyCyl(TubeData[Tube][T_PIPEOD],(OAH + 2*Protrusion),TubeData[Tube][T_NUMPINS]); } } // Totally ad-hoc support structures … if (Support) { color("Yellow") { for (i=[-1,1]) // nut traps translate([i*TubeData[Tube][T_SCREWOC]/2,0,(Nut[LENGTH] – ThreadThick)/2]) for (a=[0:5]) rotate(a*30 + 15) cube([2*ThreadWidth,0.9*Nut[OD],(Nut[LENGTH] – ThreadThick)],center=true); if (Pixel[OD] > TubeData[Tube][T_PIPEOD]) // support pipe only if needed translate([0,0,(Pixel[LENGTH] – ThreadThick)/2]) for (a=[0:7]) rotate(a*22.5) cube([2*ThreadWidth,0.9*Pixel[OD],(Pixel[LENGTH] – ThreadThick)],center=true); } } } //———————- // Build it if (Layout == "Cap") { if (Section) difference() { Cap(); translate([-CapSize[OD],0,CapSize[LENGTH]]) cube([2*CapSize[OD],2*CapSize[OD],3*CapSize[LENGTH]],center=true); } else Cap(); } if (Layout == "FinCap") { if (Section) render(convexity=5) difference() { FinCap(); // translate([0,-FinCapSize[OD],FinCapSize[LENGTH]]) // cube([2*FinCapSize[OD],2*FinCapSize[OD],3*FinCapSize[LENGTH]],center=true); translate([-FinCapSize[OD],0,FinCapSize[LENGTH]]) cube([2*FinCapSize[OD],2*FinCapSize[OD],3*FinCapSize[LENGTH]],center=true); } else FinCap(); } if (Layout == "BuildFinCap") translate([0,0,FinCapSize[LENGTH]]) rotate([180,0,0]) FinCap(); if (Layout == "LampBase") LampBase(); if (Layout == "USBPort") USBPort(); if (Layout == "Socket") if (Section) { difference() { Socket(); translate([-100/2,0,-Protrusion]) cube([100,50,50],center=false); } } else Socket(); if (Layout == "Sockets") { translate([0,50,0]) Socket("Mini7"); translate([0,20,0]) Socket("Octal"); translate([0,-15,0]) Socket("Duodecar"); translate([0,-50,0]) Socket("Noval"); }