The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Delta Shower Head Holder: Now With Rotation

We decided a few more inches of hose would be useful, so the shower head holder now has a 90° rotation in the middle to straighten the hose from plumbing to the side clip holding it out of the way:

Delta show head holder - installed rotated
Delta show head holder – installed rotated

The original rectangular connection becomes a simple square:

Delta shower head holder extension - rotated - solid model
Delta shower head holder extension – rotated – solid model

Unlike the original version, however, building this one requires a support structure:

Delta shower head holder extension - PrusaSlicer support
Delta shower head holder extension – PrusaSlicer support

Which turned out to be a Good Thing™, because a new cheap textured PEI steel printing plate seems to have poor adhesion despite being scrupulously clean:

Delta shower head - poor print adhesion
Delta shower head – poor print adhesion

Despite obvious defects due to the shifts while printing, the holder sufficed for acceptance testing.

I’m not sure about that steel plate, though.

The OpenSCAD source code as a GitHub Gist, which also contains the non-rotated version:

// Delta shower head holder extension
// Ed Nisley – KE4ZNU
// 2025-05-02
// 2026-11-09 add rotation for hose repositioning
include <BOSL2/std.scad>
Layout = "Show"; // [Show,Build,Plug,Socket,Connector,Retainer,Latch,Test]
MountAngle = 30; // between OEM and new holder
MountOffset = 40.0;
BaseAngle = 90; // [90,0,-90]
/* [Hidden] */
HoleWindage = 0.2;
Protrusion = 0.1;
NumSides = 3*3*4;
Gap = 5.0;
ID = 0;
OD = 1;
LENGTH = 2;
WallThick = 8.0; // holder wall thickness
Radius = 3.0; // shapely rounding
Insert = [21.0,24.5,35.0]; // hose connector taper
PlugSize = Insert + [-0.3,-0.3,0]; // … for better fit in OEM holder
Slot = [Insert[OD],14.6,3*Insert[LENGTH]]; // slot on OEM holder, arbitrary length
Latch = [Insert[OD] – 0.25,Insert[OD] + 2*WallThick,1.5]; // ID = latch engagement
RetainerSize = [14.5,25.0,6.0];
RetainerPegThick = 3.0;
$fn=NumSides;
//———-
// Define Shapes
module Plug() {
up(Slot.y/2)
xrot(BaseAngle)
down(Slot.y/2)
difference() {
cyl(l=Insert[LENGTH],d1=PlugSize[ID],d2=PlugSize[OD],anchor=BOTTOM);
down(Protrusion)
cyl(10.0 + 5,d=5.5,anchor=BOTTOM); // M4 burly insert
}
}
module LatchRing() {
difference() {
union() {
tube(Latch[LENGTH],id=Insert[OD],od=Latch[OD],anchor=BOTTOM);
difference() {
tube(Latch[LENGTH]/2,id1=Insert[OD],id2=Latch[ID],od=Insert[OD],anchor=BOTTOM)
position(TOP)
tube(Latch[LENGTH]/2,id1=Latch[ID],id2=Insert[OD],od=Insert[OD],anchor=BOTTOM);
cuboid(Slot + [0,1.0,0],anchor=RIGHT+CENTER);
}
}
cuboid(Slot + [0,1.0,0],anchor=LEFT+CENTER);
right(Insert[OD]/2)
cube([Insert[OD],Insert[OD] + 2*WallThick,3*Insert[LENGTH]],anchor=LEFT+CENTER);
}
}
module Socket() {
difference() {
tube(l=Insert[LENGTH],id1=Insert[ID],id2=Insert[OD],wall=WallThick,anchor=BOTTOM)
position(TOP) LatchRing();
cuboid(Slot + [0,1.0,0],anchor=LEFT+CENTER);
right(Insert[OD]/2)
cube([Insert[OD],Insert[OD] + 2*WallThick,3*Insert[LENGTH]],anchor=LEFT+CENTER);
}
}
module Connector() {
difference() {
left(MountOffset – Insert[ID]/4)
cuboid([MountOffset + Insert[LENGTH]*sin(MountAngle),Slot.y,Slot.y + 0*Insert[LENGTH]*cos(MountAngle)],
anchor=LEFT+BOTTOM);
left(MountOffset)
down(Protrusion)
cyl(10.0 + 5,d=5.5,anchor=BOTTOM); // M4 burly insert
yrot(MountAngle) right(Insert[ID]/2 + WallThick)
cyl(l=Insert[LENGTH],d1=Insert[ID] + 2*WallThick,d2=Insert[OD] + 2*WallThick,anchor=BOTTOM);
}
}
module Retainer() {
difference() {
cyl(RetainerSize[LENGTH] – RetainerPegThick,d=RetainerSize[OD],anchor=BOTTOM) position(TOP)
cyl(RetainerPegThick,d=RetainerSize[ID],anchor=BOTTOM);
down(Protrusion)
cyl(2*RetainerSize[LENGTH],d=4.0,anchor=BOTTOM);
}
}
module Adapter() {
union() {
left(MountOffset)
Plug();
yrot(MountAngle) right((Insert[ID] + 2*WallThick)/2)
Socket();
Connector();
}
}
//———-
// Build things
if (Layout == "Plug")
Plug();
if (Layout == "Socket")
Socket();
if (Layout == "Retainer")
Retainer();
if (Layout == "Connector")
Connector();
if (Layout == "Latch")
LatchRing();
if (Layout == "Test")
render()
difference() {
left(0.75*Insert[LENGTH])
up(Insert[OD]/2)
yrot(90)
Socket();
cuboid(2*(Insert[OD] + 2*WallThick),anchor=RIGHT);
}
if (Layout == "Show") {
Adapter();
if (BaseAngle)
back(sign(BaseAngle)*(RetainerSize[LENGTH] + Slot.y/2 + Gap))
up(Slot.y/2)
left(MountOffset)
xrot(BaseAngle)
Retainer();
else
left(MountOffset) down(RetainerSize[LENGTH] + Gap)
Retainer();
}
if (Layout == "Build") {
up(Insert[ID]/2 + WallThick + Insert[OD]/2)
yrot(90-MountAngle)
Adapter();
right(Insert[LENGTH] + Insert[OD])
Retainer();
if (false)
right(Insert[LENGTH] + 5.0) // fit test piece
difference() {
left(0.75*Insert[LENGTH])
up(Insert[OD]/2)
yrot(90)
Socket();
cuboid(2*(Insert[OD] + 2*WallThick),anchor=RIGHT);
}
}
// Delta shower head holder extension
// Ed Nisley – KE4ZNU
// 2025-05-02
include <BOSL2/std.scad>
Layout = "Show"; // [Show,Build,Plug,Socket,Connector]
MountAngle = 30; // between OEM and new holder
MountOffset = 20.0;
/* [Hidden] */
HoleWindage = 0.2;
Protrusion = 0.1;
NumSides = 3*3*4;
ID = 0;
OD = 1;
LENGTH = 2;
Insert = [21.0,24.5,35.0]; // hose connector taper
PlugSize = Insert + [-0.3,-0.3,0]; // … for better fit in OEM holder
Slot = [Insert[OD],14.6,3*Insert[LENGTH]]; // slot on OEM holder, arbitrary length
WallThick = 8.0; // holder wall thickness
Radius = 3.0; // shapely rounding
$fn=NumSides;
//———-
// Define Shapes
module Plug() {
cyl(l=Insert[LENGTH],d1=PlugSize[ID],d2=PlugSize[OD],anchor=BOTTOM);
}
module Socket() {
difference() {
tube(l=Insert[LENGTH],id1=Insert[ID],id2=Insert[OD],wall=WallThick,anchor=BOTTOM);
cuboid(Slot + [0,1.0,0],anchor=LEFT+CENTER);
right(Insert[OD]/2)
cube([Insert[OD],Insert[OD] + 2*WallThick,3*Insert[LENGTH]],anchor=LEFT+CENTER);
}
}
module Connector() {
difference() {
left(MountOffset)
cuboid([MountOffset + Insert[LENGTH]*sin(MountAngle),Slot.y,Insert[LENGTH]*cos(MountAngle)],
anchor=LEFT+BOTTOM);
yrot(MountAngle) right(Insert[ID]/2 + WallThick)
cyl(l=Insert[LENGTH],d1=Insert[ID] + 2*WallThick,d2=Insert[OD] + 2*WallThick,anchor=BOTTOM);
}
}
module Adapter() {
union() {
left(MountOffset)
Plug();
yrot(MountAngle) right((Insert[ID] + 2*WallThick)/2)
Socket();
Connector();
}
}
//———-
// Build things
if (Layout == "Plug")
Plug();
if (Layout == "Socket")
Socket();
if (Layout == "Connector")
Connector();
if (Layout == "Show")
Adapter();
if (Layout == "Build")
up(Insert[ID]/2 + 1*WallThick + Insert[OD]/2)
yrot(90-MountAngle)
Adapter();

Comments

Spam comments get trashed, so don’t bother; you’re not as clever as you think. Comment moderation may cause a delay.