Ever bought a vintage pump with a BS336 fire hose fitting and not had a mating half? Not a very common problem I know, but in case it's useful to anyone here is an openscad implimentation of a BS336 suction fitting. Note it relies on some libraries here. The capital letters in the comments refer to the measurements specified in the standard.
use <RCS_SCAD_Modules.scad>
use <ShortCuts.scad>
use <Spiral_Extrude.scad>
use <threads.scad>
backing = 1;
maleR = 1.85;
femaleR = 2.39;
radOffset = 1.07;
pitch = 8.466;
maleCouplerMajorD = 91.8;
maleCouplerMinorD = maleCouplerMajorD - 2*(maleR+femaleR+radOffset);
echo("male minor d =", maleCouplerMinorD);
femaleCouplerMinorD = 82.8;
femaleCouplerMajorD = femaleCouplerMinorD + 2*(maleR+femaleR+radOffset);
echo("female major d =", femaleCouplerMajorD);
$fn=50;
tailMatingOD = 68.2; // L
tailMatingL = 6.35;
tailRimD = 92.0; //K
tailRimL = 8;
tailNutD = 77.8; //E
tailNutL = 27;
tailTransitionL = 4;
tailNarrowD = 71.4; // F
tailWideD = 77.8; //E
tailSlopeL = 13;
tailT = 4 ; //t
tailNarrow1L = 38 ; // G - 13 - 13 - H
tailNarrow2L = 25; //H
tailLength = 6.35+8+27+89;
tailID = tailNarrowD - 2*tailT;
nutLength = 57;
nutThreadedLength = nutLength - 31;
nutThreads = nutThreadedLength/pitch;
nutLowerOD = 110; //N
nutLowerL = 15;
nutLugOD = 171; //P
nutLugD = 19; //R
nutMidOD = nutLugOD-2*22;
nutMidL = nutLugD +6;
nutTopOD = 114.3; //S1
nutTopL = 17;
nutID = 93.7;//K1
nutFinethreadPitch = 8; //TPI
nutFinethreadOD = 3.90; //inches
nutFinethreadL = 17;
//nutLength = nutLowerL+nutMidL+nutTopL;
lockingRingL = 22;
lockingRingOD = 114.3; //S
lockingRingID = 80.2; //Q
lockingRingUndercutL = 3;
lockingRingThreadL = 16 - lockingRingUndercutL;
lockingRingChampherL = 3;
lockingRingNotchW = 10;
lockingRingNotchH = 8;
lockingRingTopL = lockingRingL - lockingRingThreadL - lockingRingUndercutL;
washerID = 68.2; //J1
washerOD = 90; //J
washerT = 6;
section = false;
// Tail
Tz(nutThreadedLength)
difference() {
union() {
cylinder(d=tailMatingOD, h=tailMatingL+0.1);
Tz(tailMatingL)
cylinder(d=tailRimD, h=tailRimL);
Tz(tailMatingL+tailRimL-0.1)
cylinder(d=tailNutD, h=tailNutL+0.1);
Tz(tailMatingL+tailRimL+tailNutL)
cylinder(d1=tailNutD, d2=tailNarrowD, h=tailTransitionL);
Tz(tailMatingL+tailRimL+tailNutL)
cylinder(d=tailNarrowD, h=tailNarrow1L+2*tailSlopeL+tailNarrow2L);
Tz(tailMatingL+tailRimL+tailNutL+tailNarrow1L)
cylinder(d1=tailWideD, d2=tailNarrowD, h=tailSlopeL);
Tz(tailMatingL+tailRimL+tailNutL+tailNarrow1L+tailSlopeL+tailNarrow2L)
cylinder(d1=tailWideD, d2=tailNarrowD, h=tailSlopeL);
}
Tz(-1)
cylinder(d=tailID, h=tailLength+2);
if (section) {
Tz(-1)
cube(200);
}
}
// Nut
difference() {
union() {
//thread
Tz(-pitch)
extrude_spiral(StartRadius=femaleCouplerMajorD/2, Angle=360*(nutThreads+1), RPitch=0, ZPitch=pitch, StepsPerRev=60)
female_suction_thread_2D($fn=20);
// outside profile
ring(D=nutLowerOD, d=femaleCouplerMajorD+backing, h=nutLowerL+0.1, center=false, $fn=100);
Tz(nutLowerL)
ring(D=nutMidOD, d=femaleCouplerMajorD+backing, h=nutMidL, center=false, $fn=100);
Tz(nutLowerL+nutMidL-0.1)
ring(D=nutTopOD, d=femaleCouplerMajorD+backing, h=nutTopL+0.1, center=false, $fn=100);
// lugs
for (i = [0:3]) {
Rz(i*90)
Tz(nutLowerL+nutMidL/2)
Ry(90)
Tz(nutMidOD/2-3)
cylinder(d=nutLugD, h=(nutLugOD-nutMidOD)/2+3, , $fn=50);
}
}
// trim away bototm of thread
Tz(-pitch)
cylinder(d=2*femaleCouplerMajorD, h=2*pitch, center=true);
// Inner D before fine thread
Tz(nutThreadedLength)
cylinder(d=nutID, h=nutLength, $fn=60);
// fine thread
Tz(nutLength-nutFinethreadL)
//render()
english_thread(diameter=nutFinethreadOD, threads_per_inch=nutFinethreadPitch, length=(nutFinethreadL+1)/25.4, internal=true, test=false
);
if (section) {
Tz(-1)
cube(200);
}
}
// Locking ring
Tz(nutLength-nutFinethreadL+0.5)
difference() {
union() {
english_thread(diameter=nutFinethreadOD, threads_per_inch=nutFinethreadPitch, length=lockingRingThreadL/25.4, internal=false, test=false, leadin=3);
Tz(lockingRingThreadL-0.1)
cylinder(d=25.4*nutFinethreadOD-(25.4/nutFinethreadPitch), h=lockingRingUndercutL+0.2);
Tz(lockingRingThreadL+lockingRingUndercutL)
cylinder(d=lockingRingOD, h=lockingRingTopL);
}
cylinder(d=lockingRingID, h=100, center=true);
// notches for hook spanner
for (i = [0:3]) {
Tz(lockingRingThreadL+lockingRingUndercutL+lockingRingTopL/2)
Rz(i*90)
Tx(lockingRingOD/2)
cube([2*lockingRingNotchH,lockingRingNotchW,lockingRingTopL+1], center=true);
}
//chamfer
Tz(lockingRingL-lockingRingChampherL)
cylinder(d1=0, d2=2*lockingRingID, h=lockingRingID, center=true);
if (section) {
Tz(-1)
cube(200);
}
}
// Washer
Tz(nutThreadedLength)
ring(D=washerOD, d=washerID, h=washerT, center=false, $fn=100);
// Thread tests
*
extrude_spiral(StartRadius=maleCouplerMinorD/2, Angle=720, RPitch=0, ZPitch=pitch, StepsPerRev=72)
male_suction_thread_2D();
*
rotate_extrude(angle=1)
Ty(pitch/2)
Tx(femaleCouplerMajorD/2)
female_suction_thread_2D();
// Modules = threads
module male_suction_thread_2D()
Tx(-backing)
union() {
square([backing,pitch]);
Ty(pitch/2)
Tx(backing+femaleR+radOffset)
circle(r=maleR);
Ty(pitch/2 - maleR)
square([backing+femaleR+radOffset,2*maleR]);
difference() {
square([backing+femaleR,2*femaleR]);
Tx(backing+femaleR)
circle(r=femaleR);
}
Ty(pitch-2*femaleR)
difference() {
square([backing+femaleR,2*femaleR]);
Ty(2*femaleR)
Tx(backing+femaleR)
circle(r=femaleR);
}
}
module female_suction_thread_2D()
Tx(backing)
mirror([1,0,0])
union() {
square([backing,pitch]);
Ty(pitch/2)
Tx(backing+femaleR+radOffset)
circle(r=maleR);
Ty(pitch/2 - maleR)
square([backing+femaleR+radOffset,2*maleR]);
difference() {
square([backing+femaleR,2*femaleR]);
Tx(backing+femaleR)
circle(r=femaleR);
}
Ty(pitch-2*femaleR)
difference() {
square([backing+femaleR,2*femaleR]);
Ty(2*femaleR)
Tx(backing+femaleR)
circle(r=femaleR);
}
}
Giving this result (with section set to true):
And this is what it looks like 3D printed in Nylon (right) after attempt 1 in PLA failed due to creeping in the hot sun (left).