Archive for November 7th, 2013

Broom Handle Screw With Dedendum: Effect of Printing Orientation

Although the current OpenSCAD could produce a solid model with the screw thread’s dedendum, I’d never actually printed one of them:

Broom Handle Screw - full thread - solid model

Broom Handle Screw – full thread – solid model

I need some fondlestuff illustrating how to handle overhangs, so I ran one standing vertically, which (pretty much as I expected) didn’t work well at all:

Broom Handle Screw - dedendum - vertical

Broom Handle Screw – dedendum – vertical

The trick is to split the model down the middle:

Broom Handle Screw - horizontal top

Broom Handle Screw – horizontal top

And put holes in each half for alignment pins:

Broom Handle Screw - horizontal bottom

Broom Handle Screw – horizontal bottom

Then you can print it lying down:

Broom Handle Screw - horizontal - as-printed top

Broom Handle Screw – horizontal – as-printed top

The internal overhang would probably call for some support material, particularly in the square recess at the end, but in this case it’s a lesson:

Broom Handle Screw - horizontal - as-printed bottom

Broom Handle Screw – horizontal – as-printed bottom

Glue some filament snippets into the holes, snap it together, and it looks just fine over there on the right:

Broom Handle Screw - orientation comparison

Broom Handle Screw – orientation comparison

Doesn’t matter how many I print, it still doesn’t make any economic sense as a broom repair…

The OpenSCAD source code now has a Layout variable to control the orientation and, not as shown in the model, the alignment pins have glue gutters in the first layer:

// Broom Handle Screw End Plug
// Ed Nisley KE4ZNU October 2013

Layout = "Horizontal";		// Vertical Horizontal Pin

UseDedendum = true;			// true to create full thread form

//- Extrusion parameters must match reality!

ThreadThick = 0.25;
ThreadWidth = 0.40;

HoleWindage = 0.2;

Protrusion = 0.1;			// make holes end cleanly

//----------------------
// Dimensions

PostOD = 22.3;				// post inside metal handle
PostLength = 25.0;

FlangeOD = 24.0;			// stop flange
FlangeLength = 3.0;

PitchDia = 15.5;			// thread center diameter
ScrewLength = 20.0;

ThreadFormOD = 2.5;			// diameter of thread form
ThreadPitch = 5.0;
NumSegments = 32;			//  .. number of cylinder approximations per turn

BoltOD = 7.0;				// clears 1/4-20 bolt
BoltSquare = 6.5;			// across flats
BoltHeadThick = 3.0;

RecessDia = 6.0;			// recesss to secure post in handle

OALength = PostLength + FlangeLength + ScrewLength;

SplitOC = 1.25*FlangeOD;	// separation in Horizontal layout
PinOD = 1.75;				// alignment pin diameter = filament stub
PinLength = 7.0;			//  ... length

$fn=8*4;					// default cylinder sides

echo("Pitch dia: ",PitchDia);
echo("Root dia: ",PitchDia - ThreadFormOD);
echo("Crest dia: ",PitchDia + ThreadFormOD);

Pi = 3.14159265358979;

//----------------------
// Useful routines

// Wrap cylindrical thread segments around larger plug cylinder

module CylinderThread(Pitch,Length,PitchDia,ThreadOD,PerTurn) {

CylFudge = 1.02;				// force overlap

    RotIncr = 1/PerTurn;
    PitchRad = PitchDia/2;

    Turns = Length/Pitch;
    NumCyls = Turns*PerTurn;

    ZStep = Pitch / PerTurn;

    HelixAngle = atan(Pitch/(Pi*PitchDia));
    CylLength = CylFudge * (Pi*(PitchDia + ThreadOD) / PerTurn) / cos(HelixAngle);

	for (i = [0:NumCyls-1]) {
		assign(Angle = 360*i/PerTurn)
			translate([PitchRad*cos(Angle),PitchRad*sin(Angle),i*ZStep])
				rotate([90+HelixAngle,0,Angle])
					cylinder(r1=ThreadOD/2,
							r2=ThreadOD/(2*CylFudge),
							h=CylLength,
							center=true,$fn=12);
	}
}

// Build complete plug

module ScrewPlug() {
	difference() {
		union() {
			cylinder(r=PostOD/2,h=PostLength);
			cylinder(r=PitchDia/2,h=OALength);
			translate([0,0,PostLength])
				cylinder(r=FlangeOD/2,h=FlangeLength);
			color("Orange")
			translate([0,0,(PostLength + FlangeLength)])
				CylinderThread(ThreadPitch,(ScrewLength - ThreadFormOD/2),PitchDia,ThreadFormOD,NumSegments);
		}

		translate([0,0,-Protrusion])
			PolyCyl(BoltOD,(OALength + 2*Protrusion),6);

		translate([0,0,(OALength - BoltHeadThick)])
			PolyCyl(BoltSquare,(BoltHeadThick + Protrusion),4);

		if (UseDedendum)
			translate([0,0,(PostLength + FlangeLength + ThreadFormOD/2 - ThreadPitch/(2*NumSegments))])
				rotate(-90 - 360/(2*NumSegments))
				CylinderThread(ThreadPitch,ScrewLength,PitchDia,ThreadFormOD,NumSegments);

		for (i = [0:90:270]) {
			rotate(45 + i)					// 45 works better with Horizontal layout
				translate([PostOD/2,0,PostLength/2])
					sphere(r=RecessDia/2,$fn=8);
		}
	}
}

// Locating pin hole with glue recess

module LocatingPin() {

	translate([0,0,-ThreadThick])
		PolyCyl((PinOD + 2*ThreadWidth),2*ThreadThick,4);
	translate([0,0,-(PinLength/2 + ThreadThick)])
		PolyCyl(PinOD,(PinLength + 2*ThreadThick),4);

}

module PolyCyl(Dia,Height,ForceSides=0) {			// based on nophead's polyholes

  Sides = (ForceSides != 0) ? ForceSides : (ceil(Dia) + 2);

  FixDia = Dia / cos(180/Sides);

  cylinder(r=(FixDia + HoleWindage)/2,
           h=Height,
	   $fn=Sides);
}

module ShowPegGrid(Space = 10.0,Size = 1.0) {

  Range = floor(50 / Space);

	for (x=[-Range:Range])
	  for (y=[-Range:Range])
		translate([x*Space,y*Space,Size/2])
		  %cube(Size,center=true);

}

//-------------------
// Build it...

ShowPegGrid();

if (Layout == "Vertical")
	ScrewPlug();

if (Layout == "Pin")
	LocatingPin();

if (Layout == "Horizontal")
	for (i=[-1,1])
		difference() {
			translate([i*SplitOC/2,PostLength/2,0])
				rotate([90,180*(i + 1)/2,0])
					ScrewPlug();

			translate([0,0,-FlangeOD/2])
				cube([2*OALength,2*OALength,FlangeOD],center=true);

			for (j=[-1,1], pin=[-1,1])
				assign(PinX = i*SplitOC/2 + pin*(PostOD + BoltOD)/4,
					   PinY = j*PostLength/4) {
					translate([PinX,PinY,0])
						rotate(45)
							LocatingPin();
					echo("i j pin: ",i,j,pin);
					echo("X Y: ",PinX,PinY);
				}
		}

, ,

2 Comments