|
// 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 |
|
DefaultSocket = "Mini7"; |
|
|
|
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_TUBEOD = 7; // envelope or base diameter |
|
T_PIPEOD = 8; // light pipe from LED to tube base (clear evac tip / spigot) |
|
T_SCREWOC = 9; // mounting screw holes |
|
|
|
// Name pins BCD dia length hole punch tube 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, 11.0, 36.2, (8 + 1)/8 * inch, 32.0, 11.5, 47.0], // screw 39.0 OC |
|
["Octal", 8, 17.45, 2.36, 11.0, 36.2, 25.0, 32.0, 11.5, 42.0], // platter + 4 mm screws |
|
["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 |
|
["Magnoval", 10, 17.45, 1.27, 9.0, 29.7, (4 + 1)/4 * inch, 46.0, 12.4, 38.2], // similar to Novar |
|
// ["Duodecar", 13, 19.10, 1.05, 9.0, 32.0, (4 + 1)/4 * inch, 38.0, 12.5, 47.0], // screw was 39.0 OC |
|
["Duodecar", 13, 19.10, 1.05, 9.0, 25.0, 25.0, 38.0, 12.5, 42.0], // 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 |
|
|
|
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 |
|
|
|
//---------------------- |
|
// 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*Pixel[LENGTH])]; |
|
|
|
CapSides = 8*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) + HoleWindage),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,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.9,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[ID] - Stud[OD] + (Stud[OD] - Stud[ID])/2); |
|
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]) |
|
rotate(180/StudSides) |
|
difference() { |
|
cylinder(d=Stud[OD],h=Stud[LENGTH],$fn=2*StudSides); |
|
translate([0,0,Bottom]) |
|
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; |
|
|
|
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*100/2,j*100/2,BasePlate[2] - 2*ThreadThick]) |
|
cylinder(d=1.5,h=1,$fn=6); |
|
|
|
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 |
|
linear_extrude(height=(Platter[LENGTH] + Protrusion),convexity=2) |
|
difference() { |
|
circle(d=(Platter[OD] + 1),$fn=8*4); |
|
circle(d=Platter[ID],$fn=8*4); |
|
} |
|
|
|
translate([0,0,BasePlate[2] - 4.0]) // drilling recess |
|
linear_extrude(height=(4.0 + Protrusion),convexity=2) |
|
difference() { |
|
circle(d=(Platter[OD] - 10),$fn=8*4); |
|
circle(d=(Platter[ID] + 10),$fn=8*4); |
|
} |
|
} |
|
|
|
} |
|
|
|
//---------------------- |
|
// 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 |
|
ClampArc = 3*45; // angle subtended by block bottom |
|
|
|
ClampChordWidth = 2 * (TubeData[Tube][T_TUBEOD]/2) * sin(ClampArc/2); |
|
ClampChordDepth = (ClampChordWidth / 2) * tan(ClampArc/4); |
|
echo(str("Chord width: ",ClampChordWidth," depth: ",ClampChordDepth)); |
|
|
|
ClampBlock = [ClampWidth,(ClampChordDepth + 2*ClampScrew[LENGTH]),ClampLength]; |
|
|
|
difference() { |
|
translate([0,(ClampBlock[1]/2 + TubeData[Tube][T_TUBEOD]/2 - ClampChordDepth),0]) |
|
intersection() { |
|
translate([0,0,ClampLength/2]) |
|
cube(ClampBlock,center=true); |
|
translate([0,(ClampBlock[1]/2 - ClampWidth/2),0]) |
|
cylinder(d=ClampWidth,h=ClampLength); |
|
} |
|
translate([0,0,-Protrusion]) // remove tube base (remains centered) |
|
cylinder(d=TubeData[Tube][T_TUBEOD],h=(ClampLength + 2*Protrusion)); |
|
translate([0,(TubeData[Tube][T_TUBEOD]/2 + ClampScrew[LENGTH]),ClampBlock[LENGTH]/3]) |
|
rotate([-90,0,0]) |
|
PolyCyl(ClampScrew[ID],2*ClampScrew[LENGTH],6); |
|
} |
|
|
|
} |
|
|
|
//---------------------- |
|
// 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 == "PlatterFixture") |
|
PlatterFixture(); |
|
|
|
if (Layout == "USBPort") |
|
USBPort(); |
|
|
|
if (Layout == "TubeClamp") |
|
TubeClamp("Octal"); |
|
|
|
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");} |