-
Improved Octal Tube Base Clamp
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:

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

Octal base compression clamp – Slic3r preview 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:
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 … 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");}