|
// HQ Sixteen Nose Ring Lights |
|
// Ed Nisley – KE4ZNU |
|
// 2025-05-23 |
|
|
|
include <BOSL2/std.scad> |
|
|
|
Layout = "Show"; // [Show,Build,NosePlan,PowerCap] |
|
|
|
// Number of side-by-side LED strips |
|
Strips = 2; |
|
|
|
/* [Hidden] */ |
|
|
|
HoleWindage = 0.2; |
|
Protrusion = 0.1; |
|
NumSides = 3*3*4; |
|
|
|
$fn=NumSides; |
|
|
|
ID = 0; |
|
OD = 1; |
|
LENGTH = 2; |
|
|
|
Gap = 5.0; |
|
|
|
WallThick = 5.0; // default thickness for things |
|
|
|
NoseRadius = 6.0; // corner roundoff |
|
|
|
NoseOA = [44.0,36.5]; // overall nose size |
|
NoseAngles = [87,87]; // front & rear inward angles wrt left side |
|
|
|
NoseCenters = [ // centers of circles defining the nose corners |
|
[NoseRadius, NoseOA.y/2 – NoseRadius], |
|
[NoseRadius,-(NoseOA.y/2 – NoseRadius)], |
|
[NoseOA.x – NoseRadius, NoseOA.y/2 – NoseRadius – (NoseOA.x – 2*NoseRadius)*tan(90 – NoseAngles[0])], |
|
[NoseOA.x – NoseRadius,-(NoseOA.y/2 – NoseRadius – (NoseOA.x – 2*NoseRadius)*tan(90 – NoseAngles[1]))], |
|
]; |
|
|
|
LEDMargin = 1.0; |
|
LEDStrip = [41.5 + LEDMargin,8.0 + LEDMargin,1.8 + 0.2]; // 24 V COB LED strip unit + windage |
|
LEDBaseOA = [LEDStrip.x + Strips*LEDStrip.y,NoseOA.y + 2*Strips*LEDStrip.y,WallThick]; // LED mount |
|
|
|
DraftAngle = 3.0; // angle of frame wrt horizontal at right end of nose |
|
DraftWedge = [NoseOA.x,NoseOA.y + 2*LEDStrip.y,NoseOA.x*tan(DraftAngle)]; |
|
|
|
HoleOffset = [-10.0,5.5,DraftWedge.z + 10.0]; // from left front corner of nose |
|
HolePosition = HoleOffset + [0,-NoseOA.y/2,WallThick]; // absolute coordinates from origin |
|
|
|
Screw = [4.0 + HoleWindage,9.0,2.0]; // LENGTH=button head |
|
|
|
Bracket = [WallThick,Screw[OD] + 4.0,HoleOffset.z + Screw[OD/2] + 2.0 + WallThick]; |
|
|
|
Supply = [46.0,30.0,21.0]; // 24 VDC power supply |
|
SupplyScrewOffset = 5.0; // … M4 screw hole from end of supply case |
|
|
|
CapWall = 3.0; |
|
CapRadius = CapWall – 1.0; |
|
CapInset = 1.0; |
|
CapOA = [20.0,Supply.y + 2*CapWall,Supply.z + CapWall]; // x & y to cover existing holes |
|
|
|
//———- |
|
// Define Shapes |
|
|
|
//—– 2D outline of nose piece just under frame casting |
|
|
|
module NosePlan() { |
|
hull() |
|
for (p = NoseCenters) |
|
translate(p) circle(r=NoseRadius); |
|
} |
|
|
|
//—– LED mounting plate |
|
|
|
module Mount() { |
|
|
|
union() { |
|
difference() { |
|
union() { |
|
right(LEDBaseOA.x/2 – Strips*LEDStrip.y) |
|
cuboid(LEDBaseOA,rounding=WallThick/2,except=BOTTOM,anchor=BOTTOM); |
|
up(LEDBaseOA.z) left(-HoleOffset.x/2) |
|
yrot(DraftAngle) |
|
cuboid(DraftWedge,rounding=WallThick/2,edges="Z",anchor=LEFT+BOTTOM); |
|
} |
|
down(Protrusion) |
|
linear_extrude(LEDBaseOA.z + DraftWedge.z + Protrusion) |
|
NosePlan(); |
|
if (Strips > 1) |
|
translate([HolePosition.x – Bracket.x/2,HolePosition.y – Bracket.y,-Protrusion]) |
|
cyl(LEDBaseOA.z + 2*Protrusion,d=4.0,anchor=BOTTOM); |
|
} |
|
difference() { |
|
union() { |
|
translate([HolePosition.x,HolePosition.y,(Bracket.x/2)*sin(DraftAngle)]) |
|
left(Bracket.x) |
|
cuboid(Bracket,rounding=WallThick/2,edges=LEFT,anchor=BOTTOM+LEFT); |
|
translate([HolePosition.x – Bracket.x/2,HolePosition.y,0]) // rounding filler |
|
cuboid([LEDStrip.y,Bracket.y,WallThick],anchor=BOTTOM+LEFT); |
|
} |
|
translate(HolePosition) |
|
xrot(180/6) xcyl(l=NoseOA.x,d=Screw[ID],$fn=6); |
|
} |
|
} |
|
} |
|
|
|
//—– Endcap for power supply |
|
|
|
module EndCap() { |
|
|
|
difference() { |
|
cuboid(CapOA,rounding=CapRadius,except=BOTTOM,anchor=LEFT+BOTTOM); |
|
right(CapOA.x – CapWall) down(Protrusion) |
|
cuboid(Supply + [0,0,Protrusion],anchor=RIGHT+BOTTOM); |
|
right(CapInset + SupplyScrewOffset) |
|
zcyl(l=2*CapOA.z,d=Screw[ID],$fn=6,anchor=BOTTOM); |
|
} |
|
|
|
} |
|
|
|
|
|
//———- |
|
// Build things |
|
|
|
if (Layout == "NosePlan") { |
|
NosePlan(); |
|
} |
|
|
|
if (Layout == "PowerCap") { |
|
EndCap(); |
|
} |
|
|
|
if (Layout == "Show") { |
|
Mount(); |
|
|
|
ctr = 80; |
|
ofs = Supply.x/2 – CapInset; |
|
left(ctr – ofs) |
|
EndCap(); |
|
left(ctr + ofs) |
|
xflip() |
|
EndCap(); |
|
color("Silver",0.6) |
|
left (ctr) |
|
cuboid(Supply,anchor=BOTTOM); |
|
} |
|
|
|
if (Layout == "Build") { |
|
Mount(); |
|
back((LEDBaseOA.y + CapOA.y)/2 + Gap) right(Gap) up(CapOA.z) zflip() |
|
EndCap(); |
|
back((LEDBaseOA.y + CapOA.y)/2 + Gap) left(Gap) zrot(180) up(CapOA.z) zflip() |
|
EndCap(); |
|
} |