In order to clamp the tube in a V-block, the clamp must position the tube’s centerline so the envelope will clear the V groove, thusly:

The clamp now extends into the V-block and surrounds the entire Bakelite tube base:

The little divot captures the clamp screw and the slot lets the whole affair compress just enough to firmly squeeze the entire tube base.
The tube data table now includes columns for the envelope OD and the base OD, although only the 0D3 (and similar) Octal tubes in my collection have a bulging envelope and a smaller base. You can build clamps for cylindrical glass tubes if you like; I don’t vouch for the accuracy of the table contents.
For whatever it’s worth, the 6SN7GTB tube I started with has a 32 mm Bakelite base and the 0D3 tube has a 29 mm base. That should probably justify two separate entries in the table, but I’m making this up as I go along.
The OpenSCAD source code as a GitHub Gist:
// Vacuum Tube LED Lights | |
// Ed Nisley KE4ZNU February ... September 2016 | |
Layout = "TubeClamp"; // Cap LampBase USBPort Bushings | |
// Socket(s) Cap (Build)FinCap Platter[Base|Fixture] | |
// TubeClamp PlatterParts | |
DefaultSocket = "Octal"; | |
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 | |
// CD = 15 mm ID with raised ring at 37 mm, needs screw head clearance | |
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 (must also clear evacuation tip / spigot) | |
T_HOLEOD = 5; // nominal panel hole from various sources | |
T_PUNCHOD = 6; // panel hole optimized for inch-size Greenlee punches | |
T_BASEOD = 7; // base OD | |
T_BULBOD = 8; // glass envelope OD | |
T_PIPEOD = 9; // light pipe from LED to tube base (clear evac tip / spigot) | |
T_SCREWOC = 10; // mounting screw holes | |
T_PLATECAP = 11; // nonzero to print a plate cap | |
// Name pins BCD dia length hole punch base bulb pipe screw cap | |
TubeData = [ | |
["Mini7", 8, 9.53, 1.016, 7.0, 16.0, 25.0, 18.0, 18.0, 5.0, 35.0, 0], // punch 11/16, screw 22.5 OC | |
// ["Octal", 8, 17.45, 2.36, 11.0, 36.2, (8 + 1)/8 * inch, 32.0, 38.1, 11.5, 47.0, 1], // screw 39.0 OC, base 32 or 39 | |
["Octal", 8, 17.45, 2.36, 11.0, 36.2, 25.0, 29.0, 38.1, 11.5, 42.0, 1], // platter + 4 mm screws | |
["Noval", 10, 11.89, 1.1016, 7.0, 22.0, 25.0, 21.0, 21.0, 7.5, 35.0, 0], // punch 7/8, screw 28.0 OC | |
["Magnoval", 10, 17.45, 1.27, 9.0, 29.7, (4 + 1)/4 * inch, 46.0, 46.0, 12.4, 38.2, 0], // similar to Novar | |
// ["Duodecar", 13, 19.10, 1.05, 9.0, 32.0, (4 + 1)/4 * inch, 38.0, 38.0, 12.5, 47.0, 1], // screw was 39.0 OC | |
["Duodecar", 13, 19.10, 1.05, 9.0, 25.0, 25.0, 38.0, 38.0, 12.5, 42.0, 1], // fit un-punched drive platter | |
]; | |
ID = 0; | |
OD = 1; | |
LENGTH = 2; | |
Pixel = [7.0,10.0,3.0]; // ID = contact patch, OD = PCB dia, LENGTH = overall thickness | |
PixelRecessHeight = 1.55*Pixel[LENGTH]; // enough of a recess to allow for tube top curvature | |
SocketNut = // socket mounting: threaded insert or nut recess | |
// [3.5,5.2,7.2] // 6-32 insert | |
[4.0,6.0,5.9] // 4 mm short insert | |
; | |
NutSides = 8; | |
SocketShim = 2*ThreadThick; // between pin holes and pixel top | |
SocketFlange = 1.5; // 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])]; | |
USBPCB = | |
// [28,16,6.5] // small Sparkfun knockoff | |
[36,18 + 1,5.8 + 0.4] // Deek-Robot fake FTDI with ISP header | |
; | |
Platter = [25.0,95.0,1.26]; // hard drive platter dimensions | |
PlatterSides = 8*4; // polygon approximation | |
//---------------------- | |
// 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(d=(FixDia + HoleWindage),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] + 2.0),(CapTube[OD] + 2.0*Pixel[LENGTH])]; | |
CapSides = 8*4; | |
SkirtOD = CapSize[OD] + 4*ThreadWidth; | |
CapTubeHeight = (CapSize[LENGTH] + PixelRecessHeight)/2; | |
CapTubeBossOD = 1*ThreadWidth + 2*(CapTubeHeight - PixelRecessHeight)/cos(180/8); | |
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=SkirtOD,d2=CapSize[OD],h=PixelRecessHeight,$fn=CapSides); // skirt | |
translate([0,-SkirtOD/2,CapTubeHeight]) // boss around brass tube | |
rotate([-90,0,0]) | |
rotate(180/8) | |
cylinder(d=CapTubeBossOD,h=CapTube[LENGTH],$fn=8); | |
} | |
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],(PixelRecessHeight + Protrusion),CapSides); | |
translate([0,0,(PixelRecessHeight - Protrusion)]) // small step + cone to retain PCB | |
cylinder(d1=(Pixel[OD]/cos(180/CapSides) + HoleWindage),d2=Pixel[ID],h=(Pixel[LENGTH] + Protrusion),$fn=CapSides); | |
translate([0,0,CapTubeHeight]) // 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],(PixelRecessHeight + 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,USBPCB[0]]) | |
rotate([90,0,0]) | |
linear_extrude(height=USBPCB[0]) | |
polygon(points=[ | |
[0,0], | |
[USBPCB[1]/2,0], | |
[USBPCB[1]/2,0.5*USBPCB[2]], | |
[USBPCB[1]/3,USBPCB[2]], | |
[-USBPCB[1]/3,USBPCB[2]], | |
[-USBPCB[1]/2,0.5*USBPCB[2]], | |
[-USBPCB[1]/2,0], | |
]); | |
} | |
//---------------------- | |
// Box for Leviton ceramic lamp base | |
module LampBase() { | |
Insert = [3.5,5.2,7.2]; // 6-32 brass insert to match standard electrical screws | |
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 = [Insert[OD], // insert for socket screws | |
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); | |
} | |
} | |
} | |
//---------------------- | |
// Base for hard drive platters | |
module PlatterBase(TubeName = DefaultSocket) { | |
PCB = | |
[36,18,3] // Arduino Pro Mini | |
; | |
Tube = search([TubeName],TubeData,1,0)[0]; | |
SocketHeight = Pixel[LENGTH] + SocketShim + TubeData[Tube][T_PINLEN] - PanelThick; | |
echo(str("Base for ",TubeData[Tube][0]," socket")); | |
Overhang = 5.5; // platter overhangs base by this much | |
Bottom = 4*ThreadThick; | |
Base = [(Platter[OD] - 3*Overhang), // smaller than 3.5 inch Sch 40 PVC pipe... | |
(Platter[OD] - 2*Overhang), | |
2.0 + max(PCB[1],(2.0 + SocketHeight + USBPCB[2])) + Bottom]; | |
Sides = 24*4; | |
echo(str(" Height: ",Base[2]," mm")); | |
Insert = // platter mounting: threaded insert or nut recess | |
// [3.5,5.2,7.2] // 6-32 insert | |
[3.7,5.0,8.0] // 3 mm - long insert | |
; | |
NumStuds = 4; | |
StudSides = 8; | |
Stud = [Insert[OD], // insert for socket screws | |
2*Insert[OD], // OD = big enough to merge with walls | |
Base[LENGTH]]; // leave room for retainer | |
StudBCD = floor(Base[OD] - Stud[OD]/cos(180/StudSides)); | |
echo(str("Platter screw BCD: ",StudBCD," mm")); | |
PCBInset = Base[ID]/2 - sqrt(pow(Base[ID]/2,2) - pow(PCB[0],2)/4); | |
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 PCB on foam tape | |
rotate(0) | |
USBPort(); | |
} | |
for (a = [0:(NumStuds - 1)]) // platter mounting studs | |
rotate(180/NumStuds + a*360/(NumStuds)) | |
translate([StudBCD/2,0,0]) | |
difference() { | |
rotate(180/(2*StudSides)) | |
cylinder(d=Stud[OD],h=Stud[LENGTH],$fn=2*StudSides); | |
translate([0,0,Bottom]) | |
rotate(180/StudSides) | |
PolyCyl(Stud[ID],(Stud[LENGTH] - (Bottom - Protrusion)),StudSides); | |
} | |
intersection() { // microcontroller PCB mounting plate | |
rotate(180/Sides) | |
cylinder(d=Base[OD],h=Base[LENGTH],$fn=Sides); | |
translate([-PCB[0]/2,(Base[ID]/2 - PCBInset),0]) | |
cube([PCB[0],Base[OD]/2,Base[LENGTH]],center=false); | |
} | |
difference() { | |
intersection() { // totally ad-hoc bridge around USB opening | |
rotate(180/Sides) | |
cylinder(d=Base[OD],h=Base[LENGTH],$fn=Sides); | |
translate([-1.25*USBPCB[1]/2,-(Base[ID]/2),0]) | |
cube([1.25*USBPCB[1],2.0,Base[LENGTH]],center=false); | |
} | |
translate([0,-Base[OD]/2,Bottom + 1.2]) // mount PCB on foam tape | |
rotate(0) | |
USBPort(); | |
translate([0,-(Base[ID]/2 - 2.0 + 1*ThreadWidth),Bottom - 3*ThreadThick]) // legend | |
rotate([90,0,180]) | |
linear_extrude(height=1*ThreadWidth + Protrusion) { | |
translate([0,(Base[LENGTH] - 5.5),0]) | |
text(text=TubeName,size=4,font="Arial:style=Bold",halign="center"); | |
// translate([0,(Base[LENGTH] - 8.5),0]) | |
// text(text=str("BCD ",StudBCD),size=2,font="Arial",halign="center"); | |
translate([0,(Base[LENGTH] - 11),0]) | |
text(text="KE4ZNU",size=3,font="Arial",halign="center"); | |
} | |
} | |
} | |
} | |
//---------------------- | |
// Drilling fixture for disk platters | |
module PlatterFixture() { | |
StudOC = [1.16*inch,1.16*inch]; // Sherline tooling plate screw spacing | |
StudClear = 5.0; | |
AlignOffset = 100; | |
AlignBar = [3*ThreadWidth,10.0,3*ThreadThick]; | |
BasePlate = [(20 + StudOC[0]*ceil(Platter[OD] / StudOC[0])),(Platter[OD] + 10),7.0]; | |
PlateRound = 10.0; // corner radius | |
difference() { | |
hull() // basic block | |
for (i=[-1,1], j=[-1,1]) | |
translate([i*(BasePlate[0]/2 - PlateRound),j*(BasePlate[1]/2 - PlateRound),0]) | |
cylinder(r=PlateRound,h=BasePlate[2],$fn=4*4); | |
for (i=[-1,1], j=[-1,1]) // index marks | |
translate([i*AlignOffset/2,j*AlignOffset/2,BasePlate[2] - 2*ThreadThick]) | |
cylinder(d=1.5,h=1,$fn=6); | |
for (i=[-1,1]) | |
translate([i*(AlignOffset + AlignBar[0])/2,0,(BasePlate[2] - AlignBar[2]/2 + Protrusion/2)]) | |
cube(AlignBar + [0,0,Protrusion],center=true); | |
for (j=[-1,1]) | |
translate([0,j*(AlignOffset + AlignBar[0])/2,(BasePlate[2] - AlignBar[2]/2 + Protrusion/2)]) | |
rotate(90) | |
cube(AlignBar + [0,0,Protrusion],center=true); | |
for (a=[0:90:270]) | |
rotate(a) | |
translate([(AlignBar[1]/2 + AlignBar[0]/2),0,(BasePlate[2] - AlignBar[2]/2 + Protrusion/2)]) | |
cube(AlignBar + [0,-Protrusion,Protrusion],center=true); | |
for (i=[-1,1], j=[-1,0,1]) // holes for tooling plate studs | |
translate([i*StudOC[0]*ceil(Platter[OD] / StudOC[0])/2,j*StudOC[0],-Protrusion]) | |
PolyCyl(StudClear,BasePlate[2] + 2*Protrusion,6); | |
translate([0,0,-Protrusion]) // center clamp hole | |
PolyCyl(StudClear,BasePlate[2] + 2*Protrusion,6); | |
translate([0,0,BasePlate[2] - Platter[LENGTH]]) // disk locating recess | |
rotate(180/PlatterSides) | |
linear_extrude(height=(Platter[LENGTH] + Protrusion),convexity=2) | |
difference() { | |
circle(d=(Platter[OD] + 1),$fn=PlatterSides); | |
circle(d=Platter[ID],$fn=PlatterSides); | |
} | |
translate([0,0,BasePlate[2] - 4.0]) // drilling recess | |
rotate(180/PlatterSides) | |
linear_extrude(height=(4.0 + Protrusion),convexity=2) | |
difference() { | |
circle(d=(Platter[OD] - 10),$fn=PlatterSides); | |
circle(d=(Platter[ID] + 10),$fn=PlatterSides); | |
} | |
} | |
} | |
//---------------------- | |
// 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[Tube][T_PUNCHOD]," mm = ",TubeData[Tube][T_PUNCHOD]/inch," inch")); | |
echo(str(" Screws: ",TubeData[Tube][T_SCREWOC]," mm =",TubeData[Tube][T_SCREWOC]/inch," inch OC")); | |
OAH = Pixel[LENGTH] + SocketShim + TubeData[Tube][T_PINLEN]; | |
BaseHeight = OAH - PanelThick; | |
difference() { | |
union() { | |
linear_extrude(height=BaseHeight) // base outline | |
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*SocketNut[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(SocketNut[OD],(SocketNut[LENGTH] + Protrusion),NutSides); | |
PolyCyl(SocketNut[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]); | |
} | |
for (i=[-1,1]) // cable retaining slots | |
translate([i*(Pixel[OD] + TubeData[Tube][T_SCREWOC])/4,0,(Pixel[LENGTH] - Protrusion)/2]) | |
cube([Pixel[LENGTH],TubeData[Tube][T_SCREWOC],(Pixel[LENGTH] + Protrusion)],center=true); | |
} | |
// Totally ad-hoc support structures ... | |
if (Support) { | |
color("Yellow") { | |
for (i=[-1,1]) // nut traps | |
translate([i*TubeData[Tube][T_SCREWOC]/2,0,(SocketNut[LENGTH] - ThreadThick)/2]) | |
for (a=[0:5]) | |
rotate(a*30 + 15) | |
cube([2*ThreadWidth,0.9*SocketNut[OD],(SocketNut[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); | |
} | |
} | |
} | |
//---------------------- | |
// Greenlee punch bushings | |
module PunchBushing(Name = DefaultSocket) { | |
PunchScrew = 9.5; | |
BushingThick = 3.0; | |
Tube = search([Name],TubeData,1,0)[0]; | |
echo(str("Building ",TubeData[Tube][0]," bushing")); | |
NumSides = 6*4; | |
difference() { | |
union() { | |
cylinder(d=Platter[ID],h=BushingThick,$fn=NumSides); | |
cylinder(d=TubeData[Tube][T_PUNCHOD],h=(BushingThick - Platter[LENGTH]),$fn=NumSides); | |
} | |
translate([0,0,-Protrusion]) | |
PolyCyl(PunchScrew,5.0,8); | |
} | |
} | |
//---------------------- | |
// Tube clamp | |
module TubeClamp(Name = DefaultSocket) { | |
Tube = search([Name],TubeData,1,0)[0]; | |
echo(str("Building ",TubeData[Tube][0]," clamp")); | |
ClampWidth = 37.0; // inside of clamp arch | |
ClampLength = 20; // along tube base | |
ClampScrew = [6.0,7.8,6.0]; // nose of clamp screw | |
ClampBlock = [4*ThreadWidth + TubeData[Tube][T_BULBOD], | |
4*ThreadWidth + TubeData[Tube][T_BULBOD], | |
ClampLength]; | |
difference() { | |
union() { | |
intersection() { | |
translate([0,0,ClampBlock[2]/2]) | |
rotate(45) | |
cube(ClampBlock,center=true); // V-block sides | |
translate([0,-ClampWidth/2,ClampBlock[2]/2]) | |
cube([ClampWidth,ClampWidth,ClampBlock[2]],center=true); // clamp sides | |
} | |
intersection() { | |
cylinder(d=ClampWidth,h=ClampBlock[2]); | |
translate([0,ClampWidth/4,ClampBlock[2]/2]) | |
cube([ClampWidth,ClampWidth/2,ClampBlock[2]],center=true); // clamp sides | |
} | |
} | |
translate([0,0,-Protrusion]) // remove tube base (remains centered) | |
cylinder(d=TubeData[Tube][T_BASEOD],h=(ClampLength + 2*Protrusion)); | |
translate([0,(ClampWidth/2 + TubeData[Tube][T_BASEOD]/2)/2,ClampBlock[LENGTH]/3]) | |
rotate([-90,0,0]) | |
PolyCyl(ClampScrew[ID],1*ClampScrew[LENGTH],6); // clamp screw recess | |
translate([0,-(6*ThreadWidth)/2,-Protrusion]) | |
cube([ClampWidth,6*ThreadWidth,(ClampLength + 2*Protrusion)]); // clamp relief slot | |
} | |
} | |
//---------------------- | |
// 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 == "PlatterBase") | |
PlatterBase(); | |
if (Layout == "PlatterParts") { | |
Tube = search([DefaultSocket],TubeData,1,0)[0]; | |
echo(str("Parts for ",TubeData[Tube][T_NAME]," assembly")); | |
PlatterBase(); | |
translate([0.25*Platter[OD],-0.6*Platter[OD],0]) | |
rotate(0) | |
Socket(); | |
if (TubeData[Tube][T_PLATECAP]) | |
for (i=[-1,1]) | |
translate([(-0.25*Platter[OD] - i*Pixel[OD]),-0.6*Platter[OD],0]) | |
rotate(i*90) | |
Cap(); | |
} | |
if (Layout == "PlatterFixture") | |
PlatterFixture(); | |
if (Layout == "USBPort") | |
USBPort(); | |
if (Layout == "TubeClamp") | |
TubeClamp(); | |
if (Layout == "Bushings") | |
PunchBushing(); | |
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"); | |
translate([0,-85,0]) | |
Socket("Magnoval");} |
Light bulb (and vacuum tube) envelopes have a shape, naming, and size convention that goes WAY back. The first tubes had a spherical envelope (known as a “globe” or G shape), with its diameter measured in eighths of an inch (G12 would be an inch an a half in diameter). Later tubes used a “sign” or S shaped envelope (although they’re known as “globe” tubes in the audiophile community, confusingly). Later still, they went to an ST envelope, which is a combination of an S envelope and a T (“tubular”) one. This allowed the top mica to be stabilized by the tubular section. Your 0D3 is this shape. It’s also known as “shouldered tubular” by some folks. All of these are generally larger in diameter than their bases. Later tubes went to a plain tubular envelope, which is easier and cheaper to make, supports both micas, and doesn’t (usually) extend beyond the base. Fluorescent tubes are similar: an F40T12 is a tubular envelope an inch and a half in diameter.
Ya learn something new every day around here… [grin]
I knew about fluorescent tube sizing, with old-school 40 W T12 tubes versus today’s downsized 32 W T8 tubes. You’ve tied some random bits I (thought I) knew together!
The ST envelope wins, hands down, for good looks, but the regulators tubes (around here, anyway) have dark mica sheets and a getter flash on top that severely attenuate the top LED; there’s barely a hint of color up there.
Until we moved up here, I had a 4 pin Type 80 dual rectifier. The envelope was unusual; conical from the base to about the top insulator, then a hemisphere to top it off. I suppose it dated back to the 1920s. I recall it having a lot of getter flash, but don’t recall just where.
FWIW, Costco is now selling T8-style LED shop light tubes. I passed on them, and got a couple of shop-light fixtures for $48 each. I think the tubes are currently on sale for $13 a pair. Might try the tubes later on; I’ve had another one of the circa 2004 fixtures die due to a flaky ballast. The brand name for the Costco stuff is FEIT. No signs of any bare tubes at Home Depot just yet.
Correction, LED shop lights cost $30 each, not $48.
Some of the early tubes (Kellogg was one such brand) had the odd conical envelopes. The gettering was done differently then too, so sometimes the getter flash covered the whole tube (01 tubes often look like that). Those LED tubes are great when you have a dead ballast, since you have to rewire the fixture to deliver line voltage to the pins for most of them anyway. FEIT has been around (making low-end bulbs and fixtures) for quite a while. My main squeeze works at Home Depot, I’ve seen some of the bare LED tubes there on a clearance rack out by the lumber department (don’t remember the price, but I was tempted).
“main squeeze”… implies the existence of auxiliary one(s) as well :)
Hopefully she’s not into Ed’s blog :P:P:P