Badge Lanyard Reel Mount

A certain young engineer of my acquaintance now carries an ID badge and, so I hear, works in a PCB design & test venue. Seeing as how her favorite color is purple, this seemed appropriate:

Badge Lanyard Reel - front - overall
Badge Lanyard Reel – front – overall

The guts came from Circuit Breaker Labs in the form of a recycled PCB trapped in acrylic resin atop a plastic housing with a spring-loaded reel inside.

It arrived with a plastic bullet at the end of the lanyard:

Badge Lanyard Reel - plastic bullet link
Badge Lanyard Reel – plastic bullet link

Which I immediately replaced with brass, because Steampunk:

Badge Lanyard Reel - bullet cross-drill
Badge Lanyard Reel – bullet cross-drill

That made the plastic housing look weak, so, in a series of stepwise refinements, I conjured a much better case from the vasty digital deep:

Badge Lanyard Reel - iterations
Badge Lanyard Reel – iterations

All of the many, many critical dimensions lie inside the case, where they can’t be measured accurately, so each of those iterations could improve only one or two features. The absolutely wonderful thing about OpenSCAD is having it regenerate the whole model after loosening, say, the carabiner slot by two thread thicknesses; you can do that with a full-on relational CAD drawing, but CAD drawings always seems like a lot of unnecessary work if I must figure out the equations anyway.

The back sports my favorite Hilbert Curve infill with a nicely textured finish:

Badge Lanyard Reel - rear - oblique
Badge Lanyard Reel – rear – oblique

It’d surely look better in solid brass with Hilbert curve etching.

Black PETG doesn’t photograph well, but at least you can see the M2 brass inserts:

Badge Lanyard Reel - lower interior
Badge Lanyard Reel – lower interior

The first prototype showed the inserts needed far more traction than the usual reamed holes could provide, so I added internal epoxy grooves in each hole:

Badge Lanyard Reel Mount - show
Badge Lanyard Reel Mount – show

Recessing the screw heads into the top plate made them more decorative and smoother to the touch. Button-head screws would be even smoother, but IMO didn’t look quite as bold.

After seeing how well the grooves worked, I must conjure a module tabulating all the inserts on hand and automagically generating the grooves.

The yellow star holds up the roof of the reel recess in the build layout:

Badge Lanyard Reel Mount - build layout - bottom
Badge Lanyard Reel Mount – build layout – bottom

Slic3r produced the rest of the support material for the carabiner exit slot:

Badge Lanyard Reel Mount - bottom - Slic3r support
Badge Lanyard Reel Mount – bottom – Slic3r support

Those two support lumps on the right don’t actually support anything, but tweaking the support settings to disable them also killed the useful support on the left; come to find out Slic3r’s modifier meshes don’t let you disable support generation.

The top plate required support all the way around the inside of the bezel:

Badge Lanyard Reel Mount - top - Slic3r support
Badge Lanyard Reel Mount – top – Slic3r support

I carved the original plastic housing in half, roughly along its midline, and discarded the bottom section with the belt clip (it’s on the far left of the scrap pile). The top section, with PCB firmly affixed, holds the lanyard reel and anchors the retracting spring in a central slotted peg. No pictures of that, as it’s either a loose assembly of parts or a spring-loaded bomb and I am not taking it apart again.

The lanyard passes through an eyelet that pays it out to the rotating reel. I’d definitely do that differently, were I building it from scratch, because mounting the eyelet in exactly the proper position to prevent the lanyard from stacking up on the reel and jamming against the inside of the housing turned out to be absolutely critical and nearly impossible.

The top plate presses the original housing against the carabiner, with the cut-off section inside the carabiner’s circular embrace, which just barely worked: the PCB bezel is a millimeter smaller than the shoulder of the housing.

All in all, I think it came out really well for a 3D printed object made by a guy who usually builds brackets:

Badge Lanyard Reel - front - oblique
Badge Lanyard Reel – front – oblique

I hope she likes it …

The OpenSCAD source code as a GitHub Gist:

// Badge Lanyard Reel Mount
// Ed Nisley KE4ZNU April 2017
// Reel center at origin, lanyard exit toward +X
Layout = "Show";
Support = true;
//- Extrusion parameters must match reality!
ThreadThick = 0.20;
ThreadWidth = 0.40;
HoleWindage = 0.2;
Protrusion = 0.05; // make holes end cleanly
inch = 25.4;
function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);
//----------------------
// Dimensions
ID = 0; // for round things
OD = 1;
LENGTH = 2;
Carabiner = [30.7,35.3,3.5]; // metal carabiner around original reel
Latch = [6.0,-15,8.0]; // wire spring latch: offset from OD + thickness
LatchAngle = 60; // max deflection angle to center from -X direction
LatchPoints = [[0,0],
[Latch[1]/tan(LatchAngle),0],
[Latch[1]/tan(LatchAngle),-Latch[1]]]; // polygon in as-cut orientation
echo(str("Latch polygon: ",LatchPoints));
Screw = [2.0,3.8 + 0*ThreadWidth,10.0]; // M2 screw: ID = clear, OD = head
ScrewHeadLength = 2.0;
ScrewSides = 8;
ScrewRecess = 5*ThreadThick;
MountSides = ScrewSides; // suitably gritty corners
MountThick = Screw[LENGTH] / cos(180/MountSides) + ScrewRecess + 2.0;
Insert = [Screw[ID],3.4,4.0]; // brass insert for screws
BCD = Carabiner[OD] + 2.5*Insert[OD];
BoltAngles = [20,110]; // ± angles to bolt holes
Reel = [5.3,25.5 + 2*ThreadWidth,6.0 + 2*ThreadThick]; // lanyard cord reel
ShimThick = 2*ThreadThick; // covers open side of reel for better sliding
Bezel = [31.0,32.0,7.5]; // PCB holder + shell, LENGTH = post + shell
BezelSides = 6*4;
BezelBlock = [5.5,7.5,3.6] + [ThreadWidth,ThreadWidth,ThreadThick]; // block around lanyard eyelet
Eyelet = [3.5,4.5,3.0];
Bullet = [2.0,6.5,2.0]; // brass badge holder, LENGTH = recess into mount
//----------------------
// 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);
}
//-- Lanyard reel mockup
module Reel() {
cylinder(d=Reel[OD],h=Reel[LENGTH],center=true,$fn=6*4);
}
// Carabiner metal mockup
// Some magic numbers lie in wait
module Beener() {
difference() {
hull() {
cylinder(d=Carabiner[OD],
h=Carabiner[LENGTH] + 2*ThreadThick,
center=true,$fn=BezelSides);
translate([-Carabiner[OD]/2,0,0])
cylinder(d=Carabiner[OD] - 2.0,
h=Carabiner[LENGTH] + 2*ThreadThick,
center=true,$fn=6*4);
}
cylinder(d=Carabiner[ID],
h=2*Carabiner[LENGTH],
center=true,$fn=BezelSides);
translate([Carabiner[ID]/4,0,0])
cube([Carabiner[ID],7.0,2*Carabiner[LENGTH]],center=true);
}
}
// mockup of PCB holder atop remains of old mount with reel post
// Z = 0 at midline of case
module BezelMount() {
rotate(180/BezelSides) {
PolyCyl(Bezel[ID] + HoleWindage,MountThick,BezelSides); // PCB punches through mount
PolyCyl(Bezel[OD] + HoleWindage,Bezel[LENGTH] - Reel[LENGTH]/2,BezelSides);
}
translate([Reel[OD]/2,0,BezelBlock[2]/2])
scale([2,1,1])
cube(BezelBlock,center=true);
}
// Main mount around holder & carabiner
module Mount(Section="All") {
render()
difference() {
hull() {
for (a = BoltAngles) // spheres defining corners
for (i=[-1,1])
rotate(i*a)
translate([BCD/2,0,0])
sphere(d=MountThick,$fn=MountSides);
cylinder(d=Carabiner[OD] + 4*ThreadWidth,
h=MountThick,center=true); // capture carabiner ring
}
for (a = BoltAngles) // screw & insert holes, head recess
for (i=[-1,1])
rotate(i*a)
translate([BCD/2,0,0])
rotate(0*i*180/ScrewSides) {
translate([0,0,-(Insert[LENGTH] + 2*ThreadThick)])
PolyCyl(Insert[OD],
Insert[LENGTH] + 2*ThreadThick + Protrusion,ScrewSides);
for (k = [-2:2]) // epoxy retaining grooves
translate([0,0,-(k*3*ThreadThick + Insert[LENGTH]/2)])
PolyCyl(Insert[OD] + 1*ThreadWidth,
2*ThreadThick,ScrewSides);
PolyCyl(Screw[ID],Screw[LENGTH],ScrewSides);
translate([0,0,MountThick/2 - ScrewRecess]) // recess screw heads
PolyCyl(Screw[OD],Screw[LENGTH],ScrewSides);
}
translate([0,0,-1*ThreadThick]) // Minkowski Z extends only top surface!
minkowski() { // space for metal carabiner
Beener();
// cube([ThreadWidth,ThreadWidth,2*ThreadThick]);
cylinder(d=ThreadWidth,h=2*ThreadThick,$fn=6);
}
rotate([0,90,0]) rotate(180/6) // cord channel = brass tube clearance
PolyCyl(Bullet[ID],Carabiner[ID],6);
translate([Eyelet[LENGTH] + 2.0,0,0]) // eyelet, large end inward
rotate([0,90,0]) rotate(180/6)
PolyCyl(Eyelet[OD] + HoleWindage, Reel[OD]/2,6);
if (false)
translate([Reel[OD]/2 + Eyelet[LENGTH]/2,0,0]) // eyelet, small end outward
rotate([0,90,0]) rotate(180/6)
PolyCyl(Eyelet[ID],Eyelet[LENGTH],6);
translate([(BCD/2 + MountThick/2)*cos(BoltAngles[0]) - Bullet[LENGTH],0,0]) // bullet recess
rotate([0,90,0]) rotate(180/6)
PolyCyl(Bullet[OD],Carabiner[ID],6);
BezelMount(); // PCB holder clearance
Reel(); // reel clearance
translate([0,0,-(Reel[LENGTH] + ShimThick)/2]) // sliding plate on open side of reel
cylinder(d=Reel[OD],h=ShimThick,center=true,$fn=6*4);
translate([-Carabiner[OD]/2 + Latch[0],Latch[1],0])
linear_extrude(height=Latch[2],center=true)
polygon(LatchPoints);
if (Section == "Upper") // display & build section cutting
translate([0,0,-2*Carabiner[LENGTH]])
cube(4*Carabiner,center=true);
else if (Section == "Lower")
translate([0,0,2*Carabiner[LENGTH]])
cube(4*Carabiner,center=true);
}
if (Support) { // Completely ad-hoc support structures
color("Yellow", Layout == "Show" ? 0.3 : 1.0) {
if (false && Section == "Upper") {
Spokes = BezelSides;
Offset = 6*ThreadWidth;
for (i = [2:Spokes - 2])
rotate(i * 360/Spokes)
translate([Offset,-ThreadWidth,0*(Carabiner[LENGTH]/2)/2])
cube([Carabiner[OD]/2 - Offset - 0*ThreadWidth,
2*ThreadWidth,
Carabiner[LENGTH]/2],center=false);
for (i = [0:Spokes - 1])
rotate(i * 360/Spokes)
translate([Offset,-ThreadWidth,0])
cube([Bezel[OD]/2 - Offset,
2*ThreadWidth,
Bezel[LENGTH] - Reel[LENGTH]/2 - 2*ThreadThick],center=false);
Bars = 7;
render()
difference() {
union() {
for (i = [-floor(Bars/2) : floor(Bars/2)])
translate([-Carabiner[ID]/2,i*Carabiner[OD]/Bars,Carabiner[LENGTH]/4])
cube([Carabiner[ID]/3,2*ThreadWidth,Carabiner[LENGTH]/2],center=true);
translate([-Carabiner[ID]/2,0,ThreadThick/2])
cube([Carabiner[ID]/3,Carabiner[ID],ThreadThick],center=true);
}
cylinder(d=Carabiner[ID] + 2*ThreadWidth,h=Carabiner[LENGTH]);
}
}
if (Section == "Lower") {
translate([0,0,-(Reel[LENGTH]/4 + ShimThick/2 - ThreadThick/2)])
for (i = [0:8])
rotate(i * 360/8)
cube([Reel[OD] - 2*ThreadWidth,
2*ThreadWidth,
Reel[LENGTH]/2 + ShimThick - ThreadThick],center=true);
if (false) {
Bars = 7;
render()
difference() {
union() {
for (i = [-floor(Bars/2) : floor(Bars/2)])
translate([-Carabiner[ID]/2,i*Carabiner[OD]/Bars,-Carabiner[LENGTH]/4])
cube([Carabiner[ID]/3,2*ThreadWidth,Carabiner[LENGTH]/2],center=true);
translate([-Carabiner[ID]/2,0,-ThreadThick/2])
cube([Carabiner[ID]/3,Carabiner[ID],ThreadThick],center=true);
}
translate([0,0,-Carabiner[LENGTH]])
cylinder(d=Carabiner[ID] + 0*ThreadWidth,h=Carabiner[LENGTH]);
}
}
}
}
}
}
//----------------------
// Build it
if (Layout == "Beener")
Beener();
if (Layout == "Mount")
Mount();
if (Layout == "Reel")
Reel();
if (Layout == "BezelMount")
BezelMount();
Gap = 25;
if (Layout == "Show") {
translate([0,0,Gap/2])
Mount("Upper");
translate([0,0,-Gap/2])
Mount("Lower");
color("Green",0.3)
Beener();
color("Brown",0.3)
Reel();
color("Red",0.3)
translate([0,0,-(Reel[LENGTH] + ShimThick)/2])
cylinder(d=Reel[OD],h=ShimThick,center=true,$fn=6*4);
}
if (Layout == "Build") {
translate([(BCD + MountThick)/2,0,0])
rotate(180)
Mount("Upper");
rotate([180,0,0])
translate([-(BCD + MountThick)/2,0,0])
Mount("Lower");
}
if (Layout == "BuildUpper")
Mount("Upper");
if (Layout == "BuildLower")
rotate([180,0,0])
Mount("Lower");

 

7 thoughts on “Badge Lanyard Reel Mount

  1. One more little improvement. A brass exit bushing will keep the lanyard from fraying or cutting into the plastic housing, the first of which is the dominant failure mode for my lanyards (the second not because the housing mine come with have a small stainless bushing at the exit.)

    1. I think the original eyelet served both purposes, although (IMO) did neither very well. An additional bushing / sleeve / whatever seems like a great idea: when this holder wears out, it’s on the list … [grin]

Comments are closed.