Kenmore Progressive Vacuum Tool Adapters: First Failure

I picked up a horsehair dust brush from eBay as a lightweight substitute for the Electrolux aluminum ball, discovered that an adapter I’d already made fit perfectly, did the happy dance, and printed one for the brush. That worked perfectly for half a year, whereupon:

Dust Brush Adapter - broken parts
Dust Brush Adapter – broken parts

It broke about where I expected, along the layer lines at the cross section where the snout joins the fitting. You can see the three perimeter shells I hoped would strengthen the part:

Dust Brush Adapter - layer separation
Dust Brush Adapter – layer separation

That has the usual 15% 3D Honeycomb infill, although there’s not a lot area for infill.

There’s obviously a stress concentration there and making the wall somewhat thicker (to get more plastic-to-plastic area) might suffice. I’m not convinced the layer bonding would be good enough, even with more wall area, to resist the stress; that’s pretty much a textbook example of how & where 3D printed parts fail.

That cross section should look like this:

Dust Brush Adapter - Snout infill - Slic3r preview
Dust Brush Adapter – Snout infill – Slic3r preview

Anyhow, I buttered the snout’s broken end with JB Kwik epoxy, aligned the parts, and clamped them overnight:

Dust Brush Adapter - clamping
Dust Brush Adapter – clamping

The source code now has a separate solid model for the dust brush featuring a slightly shorter snout; if when the epoxy fails, we’ll see how that changes the results. I could add ribs and suchlike along the outside, none of which seem worth the effort right now. Fairing the joint between those two straight sections would achieve the same end, with even more effort, because OpenSCAD.

The OpenSCAD source code as a GitHub Gist:

// Kenmore vacuum cleaner nozzle adapters
// Ed Nisley KE4ZNU August 2016
// Layout options
Layout = "DustBrush"; // MaleFitting CoilWand FloorBrush CreviceTool ScrubbyTool LuxBrush DustBrush
//- Extrusion parameters must match reality!
// Print with +1 shells and 3 solid layers
ThreadThick = 0.25;
ThreadWidth = 0.40;
HoleWindage = 0.2;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
Protrusion = 0.1; // make holes end cleanly
//----------------------
// Dimensions
ID1 = 0; // for tapered tubes
ID2 = 1;
OD1 = 2;
OD2 = 3;
LENGTH = 4;
OEMTube = [35.0,35.0,41.7,40.5,30.0]; // main fitting tube
EndStop = [OEMTube[ID1],OEMTube[ID2],47.5,47.5,6.5]; // flange at end of main tube
FittingOAL = OEMTube[LENGTH] + EndStop[LENGTH];
$fn = 12*4;
//----------------------
// 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(r=(FixDia + HoleWindage)/2,h=Height,$fn=Sides);
}
//-------------------
// Male fitting on end of Kenmore tools
// This slides into the end of the handle or wand and latches firmly in place
module MaleFitting() {
Latch = [40,11.5,5.0]; // rectangle latch opening
EntryAngle = 45; // latch entry ramp
EntrySides = 16;
EntryHeight = 15.0; // lower edge on *inside* of fitting
KeyRadius = 1.0;
translate([0,0,6.5])
difference() {
union() {
cylinder(d1=OEMTube[OD1],d2=OEMTube[OD2],h=OEMTube[LENGTH]); // main tube
hull() // insertion guide
for (i=[-(6.0/2 - KeyRadius),(6.0/2 - KeyRadius)],
j=[-(28.0/2 - KeyRadius),(28.0/2 - KeyRadius)],
k=[-(26.0/2 - KeyRadius),(26.0/2 - KeyRadius)])
translate([(i - (OEMTube[ID1]/2 + OEMTube[OD1]/2)/2 + 6.0/2),j,(k + 26.0/2 - 1.0)])
sphere(r=KeyRadius,$fn=8);
translate([0,0,-EndStop[LENGTH]]) // wand tube butts against this
cylinder(d=EndStop[OD1],h=EndStop[LENGTH] + Protrusion);
}
translate([0,0,-OEMTube[LENGTH]]) // main bore
cylinder(d=OEMTube[ID1],h=2*OEMTube[LENGTH] + 2*Protrusion);
translate([0,-11.5/2,23.0 - 5.0]) // latch opening
cube(Latch);
translate([OEMTube[ID1]/2 + EntryHeight/tan(90-EntryAngle),0,0]) // latch ramp
translate([(Latch[1]/cos(180/EntrySides))*cos(EntryAngle)/2,0,(Latch[1]/cos(180/EntrySides))*sin(EntryAngle)/2])
rotate([0,-EntryAngle,0])
intersection() {
rotate(180/EntrySides)
PolyCyl(Latch[1],Latch[0],EntrySides);
translate([-(2*Latch[0])/2,0,-Protrusion])
cube(2*Latch[0],center=true);
}
}
}
//-------------------
// Refrigerator evaporator coil wand
module CoilWand() {
union() {
translate([0,0,50.0])
rotate([180,0,0])
difference() {
cylinder(d1=EndStop[OD1],d2=42.0,h=50.0);
translate([0,0,-Protrusion])
cylinder(d1=35.0,d2=35.8,h=100);
}
translate([0,0,50.0 - Protrusion])
MaleFitting();
}
}
//-------------------
// Samsung floor brush
module FloorBrush() {
union() {
translate([0,0,60.0])
rotate([180,0,0])
difference() {
union() {
cylinder(d1=EndStop[OD1],d2=32.4,h=10.0);
translate([0,0,10.0 - Protrusion])
cylinder(d1=32.4,d2=30.7,h=50.0 + Protrusion);
}
translate([0,0,-Protrusion])
cylinder(d1=28.0,d2=24.0,h=100);
}
translate([0,0,60.0 - Protrusion])
MaleFitting();
}
}
//-------------------
// Crevice tool
module CreviceTool() {
union() {
translate([0,0,60.0])
rotate([180,0,0])
difference() {
union() {
cylinder(d1=EndStop[OD1],d2=32.0,h=10.0);
translate([0,0,10.0 - Protrusion])
cylinder(d1=32.0,d2=30.4,h=50.0 + Protrusion);
}
translate([0,0,-Protrusion])
cylinder(d1=28.0,d2=24.0,h=100);
}
translate([0,0,60.0 - Protrusion])
MaleFitting();
}
}
//-------------------
// Mystery brush
module ScrubbyTool() {
union() {
translate([0,0,60.0])
rotate([180,0,0])
difference() {
union() {
cylinder(d1=EndStop[OD1],d2=31.8,h=10.0);
translate([0,0,10.0 - Protrusion])
cylinder(d1=31.8,d2=31.0,h=50.0 + Protrusion);
}
translate([0,0,-Protrusion])
cylinder(d1=26.0,d2=24.0,h=100);
}
translate([0,0,60.0 - Protrusion])
MaleFitting();
}
}
//-------------------
// eBay horsehair dusting brush
module DustBrush() {
union() {
translate([0,0,40.0])
rotate([180,0,0])
difference() {
union() {
cylinder(d1=EndStop[OD1],d2=31.8,h=10.0);
translate([0,0,10.0 - Protrusion])
cylinder(d1=31.6,d2=31.8,h=30.0 + Protrusion);
}
translate([0,0,-Protrusion])
cylinder(d1=26.0,d2=24.0,h=100);
}
translate([0,0,40.0 - Protrusion])
MaleFitting();
}
}
//-------------------
// Electrolux brush ball
module LuxBrush() {
union() {
translate([0,0,30.0])
rotate([180,0,0])
difference() {
union() {
cylinder(d1=EndStop[OD1],d2=30.8,h=10.0);
translate([0,0,10.0 - Protrusion])
cylinder(d1=30.8,d2=30.0,h=20.0 + Protrusion);
}
translate([0,0,-Protrusion])
cylinder(d1=25.0,d2=23.0,h=30 + 2*Protrusion);
}
translate([0,0,30.0 - Protrusion])
MaleFitting();
}
}
//----------------------
// Build it!
if (Layout == "MaleFitting")
MaleFitting();
if (Layout == "CoilWand")
CoilWand();
if (Layout == "FloorBrush")
FloorBrush();
if (Layout == "CreviceTool")
CreviceTool();
if (Layout == "DustBrush")
DustBrush();
if (Layout == "ScrubbyTool")
ScrubbyTool();
if (Layout == "LuxBrush")
LuxBrush();