/* Tubaphone modular holder code version: 2 (With grove for Rubber Bands Bracelets) License: This code is placed in the Public Domain Contributed By: maremho creations January 2020 */ $fn=16; //parameters beamw=12; outfr=3; tubor=16/2; gapct=1.0; //100%*tubor;tube spacing at flat expressed as R% slotc=0.15;//slot clearance //anglt=20.88; // angle tube to beam (>0 for black keys, <0 for white keys) rubod=18.2; //rubber hair ring outer diameter rubth=1.8; //rubber hair ring groove thickness //uncomment the next line for the white keys tube holders white(nb=4,anglt=15.53,offst=2.93); //uncomment the next line for the black keys tube holders //black(nb=2,anglt=20.88); //translate([20, 7,0]) head(15,0); //translate([20,-7,0]) head(0,0); module white(nb,anglt,offst){ translate([0, 7,0]) head(-anglt,-offst); translate([1*(-2.501-gapct)*tubor, 7,0]) head(-anglt,0); translate([2*(-2.501-gapct)*tubor, 7,0]) head(-anglt,0); if (nb==4){ translate([3*(-2.501-gapct)*tubor, 7,0]) head(-anglt,0); } // and opposite tube holders at flat... translate([0, -7,0]) head(0,0); translate([1*(-2.501-gapct)*tubor,-7,0]) head(0,0); translate([2*(-2.501-gapct)*tubor,-7,0]) head(0,0); if (nb==4){ translate([3*(-2.501-gapct)*tubor,-7,0]) head(0,0); } } module black(nb,anglt){ translate([0, 7,0]) head(anglt,0,femdovetail=true,maldovetail=false); translate([1*(-2.501-gapct)*tubor, 7,0]) head(anglt,0); if (nb==2){ translate([1*(-2.501-gapct)*tubor, 7,0]) head(anglt,0,femdovetail=false,maldovetail=true); } if (nb==3){ translate([1*(-2.501-gapct)*tubor, 7,0]) head(anglt,0); translate([2*(-2.501-gapct)*tubor, 7,0]) head(anglt,0,femdovetail=false,maldovetail=true); } // and opposite tube holders at flat... translate([0, -7,0]) head(0,0,femdovetail=true,maldovetail=false); if (nb==2){ translate([1*(-2.501-gapct)*tubor,-7,0]) head(0,0,femdovetail=false,maldovetail=true); } if (nb==3){ translate([1*(-2.501-gapct)*tubor,-7,0]) head(0,0); translate([2*(-2.501-gapct)*tubor,-7,0]) head(0,0,femdovetail=false,maldovetail=true); } } module head(angl1,slidlen,normaltype=true,femdovetail=true,maldovetail=true) //tubeangle, distance the male dovetail needs to slide (>0 for positive angles and vice-versa) to accomodate angle differences,normaltype=false for spacing elements that does not hold a tube) { difference(){ union(){ // start of union section //translate([-gapct*tubor/5,-beamw/2,0])cube([(gapct+2+gapct/2.5)*tubor,beamw,tubor+2*outfr]); // straight box //outer polygon profile linear_extrude(height=tubor+2*outfr) polygon(points=[ [-beamw/2*tan(angl1)-gapct*tubor/4/cos(angl1), beamw/2], [ beamw/2*tan(angl1)-gapct*tubor/4/cos(angl1), -beamw/2], [(gapct*3/4+2)*tubor/cos(angl1)+beamw/2*tan(angl1), -beamw/2], [(gapct*3/4+2)*tubor/cos(angl1)-beamw/2*tan(angl1), beamw/2] ] ); // male dovetail if (maldovetail){ translate([(gapct*3/4+2)*tubor/cos(angl1)+1*slotc/2-slidlen*sin(angl1),slidlen*cos(angl1),0])linear_extrude(height=tubor+2*outfr)offset(delta=-slotc)rotate([0,0,180+angl1])circle(r=0.5*tubor, $fn=3); } }// end of union section //fillet along -X edge translate([(gapct/4+1)*tubor+beamw/2*tan(angl1),-beamw/2,tubor+2*outfr])mirror([-1,0,-1])otrim((gapct+2)*tubor*1.2); //fillet along +X edge translate([(gapct/4+1)*tubor-beamw/2*tan(angl1),beamw/2,tubor+2*outfr]) mirror([0,1,0])mirror([1,0,1])otrim((gapct+2)*tubor*1.2); //Double-cone inside and central groove if(normaltype){ mirror([0,1,0])translate([(gapct/3+1)*tubor/cos(angl1),0,tubor+outfr])rotate([90,0,-angl1])cylinder(h=beamw+1, r1=tubor, r2=tubor+outfr, center=false,$fn=60); translate([(gapct/3+1)*tubor/cos(angl1),0,tubor+outfr])rotate([90,0,angl1])cylinder(h=beamw+1, r1=tubor, r2=tubor+outfr, center=false,$fn=60); translate([(gapct/3+1)*tubor/cos(angl1),0,tubor+outfr])rotate([90,0,angl1])cylinder(h=rubth,d=rubod,center=false,$fn=60); } // female dovetail if (femdovetail){ translate([(-gapct*1/4)*tubor/cos(angl1),0,-0.5])linear_extrude(height=tubor+2*outfr+1)rotate([0,0,180+angl1])circle(r=0.5*tubor, $fn=3); } } } // MODULES FOR TRIMMING THE EDGES - DON'T REMOVE module quarterround(){ difference() { translate([-1,-1]) square([outfr+1,outfr+1]); translate([outfr,outfr])circle(outfr,$fn=32); }} module otrim(l) { linear_extrude (l,center=true,convexity=20)translate([0,0]) quarterround(); }