Helmet Mirror Mount: Solid Model

Helmet mirror mount - 3D model - Fit layout
Helmet mirror mount - 3D model - Fit layout

After a bit of OpenSCAD twiddling, those doodles turned into a printable model. This view shows what it looks like all neatly assembled:

The tiny hole on the top of the Elevation Body accepts a 2-56 setscrew that grabs the arc protruding from the Elevation Plate and locks the up-and-down setting. The Azimuth Mount pivots on the 3-48 screw holding it to the Elevation Mount.

Both of those pivots must be loose enough to move when you bump the mirror and tight enough to stay put in normal use. It’s a delicate balance and I’m not convinced this will work for the long term, but it’s a brassboard.

The 2-56 stud on the end of the mirror shaft screws into a socket in the rear side of the Az Mount. Another 2-56 setscrew in the Az Mount (facing the El Body), grabs the side of the shaft and prevents it from rotating.

All the parts lay out on their backs for printing, with a grid to show how they fit on the build platform:

Helmet mirror mount - 3D model - Show layout
Helmet mirror mount - 3D model - Show layout

The mirror shaft shoulder on the Az Mount (front center) sticks out in mid air and requires a little bit of support.

The El Mount (left rear) builds surprisingly well with its curved top surface downward. If it’s rotated 90 degrees with the curve facing to the left, Skeinforge grumps about not being able to do something or another and generates totally bogus G-Code.

The Helmet Plate has a 3 mm deep depression that more-or-less corresponds to the helmet’s surface. It’s gouged out by a huge sphere sitting on the plate, with a radius calculated from the measured helmet curvature.

The OpenSCAD source code has two useful parameters near the top:

  • Layout selects the overall appearance: Fit, Show, or Build
  • Examine selects a single part for inspection & tweakage

You’ll need the MCAD and Visibone libraries to make this work. It’s the original code, without the tweaks to the grid mentioned in the comments there:

// Helmet mirror mount
// Ed Nisley KE4ZNU June 2011

include </home/ed/Thing-O-Matic/lib/MCAD/units.scad>
include </home/ed/Thing-O-Matic/lib/MCAD/boxes.scad>
include </home/ed/Thing-O-Matic/lib/visibone_colors.scad>

//-- Layout Control

Layout = "Show";					// Build Fit Show None

Examine = "None";				// AzMount ElMount ElBody ElPlate HelmetPlate None

//-- Extrusion parameters

ThreadThick = 0.33;
ThreadWT = 2.0;
ThreadWidth = ThreadThick * ThreadWT;

HoleWindage = 0;			// enlarge hole dia by this amount

//-- Useful sizes

Tap2_56 = 0.070 * inch;
Clear2_56 = 0.082 * inch;
Head2_56 = 0.156 * inch;
Head2_56Thick = 0.055 * inch;
Nut2_56Dia = 0.204 * inch;
Nut2_56Thick = 0.065 * inch;

Tap3_48 = 0.079 * inch;
Clear3_48 = 0.096 * inch;
Head3_48 = 0.184 * inch;
Head3_48Thick = 0.058 * inch;
Nut3_48Dia = 0.201 * inch;
Nut3_48Thick = 0.073 * inch;

Tap4_40 = 0.089 * inch;
Clear4_40 = 0.110 * inch;
Head4_40 = 0.211 * inch;
Head4_40Thick = 0.065 * inch;
Nut4_40Dia = 0.228 * inch;
Nut4_40Thick = 0.086 * inch;

//-- Azimuth Mount

AzMountDia = 12.0;
AzMountLength = 14.0;

AzFacets = 30;

echo(str("Azmuth mount dia: ",AzMountDia," length: ",AzMountLength));

//-- Mirror sizes

MirrorShaftDia = 3.60;
MirrorShaftOffset = -1.5;				// vertical offset from center of AzMountBody
MirrorShoulderLen = 3*MirrorShaftDia;
MirrorShoulderDia = min(AzMountDia,MirrorShaftDia + 6*ThreadWidth);

MirrorStudDia = Tap3_48;
MirrorStudLen = 2.0;

//-- Elevation Mount / Body / Plate

ElMountDia = AzMountDia;
ElMountLength = 2.0 + ElMountDia;

ElMountBase = 2.0;

ElMountRounding = 2.0;

ElMountFacets = AzFacets;

ElBodyWidth = ElMountDia;
ElBodyBlockLength = ElMountLength + AzMountLength/2 - MirrorShaftOffset;
ElBodyThick = 8.0;

echo(str("Elevation body overall: ",(ElBodyBlockLength + ElBodyWidth/2)," width: ",ElBodyWidth));

ElPlateTall = ElBodyBlockLength + 0.70*ElBodyWidth;
ElPlateWidth = 1.25 * ElPlateTall;
ElPlateThick = ceil(4.0 / ThreadThick) * ThreadThick;

ElPlatePlusX = ElPlateThick + (ElMountDia/2 + ElMountBase) + ElBodyThick;

echo(str("Elevation plate tall: ",ElPlateTall," width: ",ElPlateWidth));

ElArcRadius = (3/4) * ElBodyBlockLength;
ElArcThick = 4*ThreadWidth;
ElArcHeight = (1/2) * ElBodyThick;
ElArcAngle = 35;
ElArcFacets = 32;

ElPlateFacets = 52;

//-- Helmet Interface Plate

HelmetCX = 60.0;
HelmetMX = 4.0;
HelmetRX = (pow(HelmetMX,2) + pow(HelmetCX,2)/4)/(2*HelmetMX);

HelmetPlateC = max(ElPlateTall,ElPlateWidth);
HelmetPlateTheta = atan(HelmetPlateC/HelmetRX);
HelmetPlateM = 2*HelmetRX*pow(sin(HelmetPlateTheta/4),2);

HelmetPlateThick = ThreadThick*(ceil(HelmetPlateM/ThreadThick) + 1);

//-- Bearing Interfaces

BearingWidth = 3*ThreadWidth;

BearingOverlap = 3*ThreadThick;
BearingClearance = 1*ThreadThick;

BearingStudDia = min(AzMountDia,ElBodyWidth) - 2*BearingWidth;

//-- Convenience values

Protrusion = 0.1;		// make holes look good

PegSize = 1.0;

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

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

  Sides = ceil(Dia) + 2;
  FixDia = Dia / cos(180/Sides);

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

module ShowPegGrid(Size) {
	for (x=[-5:5])
	  for (y=[-5:5])
		translate([x*10,y*10,Size/2])
		  cube(Size,center=true);

}

//----------------------
// Azimuth Mount

module AzMount() {

  difference() {
	union() {
	  cylinder(r=AzMountDia/2,h=AzMountLength,$fn=AzFacets);		// body
	  translate([0,0,AzMountLength/2 + MirrorShaftOffset])
		rotate([-90,0,0])
		  cylinder(r=MirrorShoulderDia/2,
				   h=MirrorShoulderLen,$fn=AzFacets);				// mirror shaft shoulder

	  if (Layout != "Fit")
		for (y=[0:1])												// shoulder support
		  translate([-AzMountDia/2,(4*y + AzMountDia/2 + ThreadWidth),0])
			difference() {
			  cube([AzMountDia,2*ThreadWidth,AzMountLength/6]);
			  translate([AzMountDia/2,-Protrusion,AzMountLength/2 + MirrorShaftOffset])
				rotate([-90,0,0])
				  cylinder(r=MirrorShoulderDia/2,h=ThreadWidth + 2*Protrusion);
			}
	}

    translate([0,-Head3_48/2,AzMountLength/2 + MirrorShaftOffset])
      rotate([-90,0,0])
		PolyCyl(MirrorShaftDia,(AzMountDia + MirrorShoulderLen));	// mirror shaft

    translate([0,-(Head3_48/2 - Protrusion),AzMountLength/2 + MirrorShaftOffset])
	  rotate([90,0,0])
		PolyCyl(MirrorStudDia,MirrorStudLen+Protrusion);			// mirror stud

    translate([0,0,
	       Head3_48Thick - (AzMountLength - MirrorShaftDia)/2 + MirrorShaftOffset - Protrusion])
      PolyCyl(Head3_48,AzMountLength + Protrusion);					// mounting screw head

    translate([0,0,-Protrusion])
      cylinder(r=(Clear3_48 + HoleWindage)/2,
	  h=(AzMountLength + 2*Protrusion),
	  $fn=ceil(Clear3_48)+2);										// mounting screw clearance

	translate([0,0,AzMountLength/2 + Head3_48Thick + MirrorShaftDia/2 + MirrorShaftOffset - Protrusion])
	  cylinder(r1=(Head3_48/cos(180/7) + HoleWindage)/2,
			   r2=Clear3_48/2,
			   h=(3*ThreadThick + Protrusion),
			   $fn=7);												// overhang support

    translate([0,0,AzMountLength/2 + MirrorShaftOffset])
      rotate([0,90,0])
		PolyCyl(Tap2_56,AzMountDia/2 + Protrusion);					// setscrew hole

    translate([0,0,AzMountLength - (BearingOverlap + BearingClearance)])
	  PolyCyl(BearingStudDia,
			  BearingOverlap + BearingClearance + Protrusion);		// bearing surface

  }

}

//----------------------
// Elevation Mount

module ElMount() {

  difference() {

	union() {

	  translate([(ElMountDia/4 + ElMountBase/2),0,(ElMountLength/2 + BearingOverlap)])
		rotate([0,90,0])
		  cube([ElMountLength,ElMountDia,(ElMountDia/2 + ElMountBase)],
			  center=true);											// mounting block

	  translate([0,0,BearingOverlap]) {
//		color([0.4,0.3,0.3,0.7])
		cylinder(r=ElMountDia/2,
				 h=ElMountLength - ElMountDia/2,
				 $fn=ElMountFacets);								// cylinder to Az

//		color([0.3,0.4,0.3,0.7])
		translate([0,0,ElMountLength - ElMountDia/2]) {				// curved interface
		  intersection() {
			cylinder(r=ElMountDia/2,h=ElMountDia/2,$fn=ElMountFacets);
			translate([0,ElMountDia/2,0])
			  rotate([90,0,0])
				cylinder(r=ElMountDia/2,h=ElMountDia,$fn=ElMountFacets);
		  }
		}

	  }

	  cylinder(r=(BearingStudDia - HoleWindage)/2,h=BearingOverlap);	// bearing stud
	}

	translate([0,0,-Protrusion])
	  PolyCyl(Tap3_48,(3/4)*ElMountLength + BearingOverlap + Protrusion);	// AzMount screw
  }
}

//----------------------
// Elevation Body

module ElBody() {

  difference() {
	union() {
	  translate([-ElBodyBlockLength,-ElBodyWidth/2,0])
		cube([ElBodyBlockLength,ElBodyWidth,ElBodyThick]);
	  translate([0,0,ElBodyThick])
		cylinder(r=(ElBodyWidth - 2*BearingWidth)/2,h=BearingOverlap);
	  cylinder(r=ElBodyWidth/2,h=ElBodyThick,$fn=ElMountFacets);
	}

	PolyCyl(Clear3_48,ElBodyThick + BearingOverlap + Protrusion);

	translate([0,0,-Protrusion])
	  PolyCyl(Head3_48,Head3_48Thick);

	translate([-ElArcRadius,0,ElBodyThick - ElArcHeight/2])
	  rotate([0,-90,0])
		PolyCyl(Tap2_56,ElBodyBlockLength - ElArcRadius + Protrusion);

	translate([0,0,ElBodyThick - (ElArcHeight + BearingClearance)])
	  difference() {
		cylinder(r=ElArcRadius + (ElArcThick/2 + BearingClearance),
				 h=ElArcHeight + BearingClearance + Protrusion,
				 $fn=ElArcFacets);
		cylinder(r=ElArcRadius - (ElArcThick/2 + BearingClearance),
				 h=ElArcHeight + BearingClearance + Protrusion,
				 $fn=ElArcFacets);
	  }

  }

}

//----------------------
// Elevation Plate

module ElPlate() {

  union() {
	difference() {
	  translate([ElBodyWidth/2 - ElPlateTall/2,0,0])
		scale([ElPlateTall,ElPlateWidth,1.0])
		  cylinder(r=0.5,h=ElPlateThick,$fn=ElPlateFacets);
	  translate([0,0,-Protrusion])
		PolyCyl(Tap3_48,ElPlateThick + 2*Protrusion);
	  translate([0,0,ElPlateThick - (BearingOverlap + BearingClearance)])
		PolyCyl(BearingStudDia,(BearingOverlap + BearingClearance) + Protrusion);
	  translate([0,0,-Protrusion])
		cylinder(r=Nut3_48Dia/2,h=(1.1*Nut3_48Thick + Protrusion),$fn=6);
	}

	translate([0,0,ElPlateThick])
	difference() {
	  cylinder(r=ElArcRadius + ElArcThick/2,
			   h=ElArcHeight,
			   $fn=ElArcFacets);
	  cylinder(r=ElArcRadius - ElArcThick/2,
			   h=ElArcHeight + Protrusion,
			   $fn=ElArcFacets);
	  rotate([0,0,90 - ElArcAngle])
	    translate([ElArcRadius + ElArcThick,0,ElArcHeight/2])
		  cube([2*ElArcRadius + ElArcThick,
				2*ElArcRadius + ElArcThick,
				ElArcHeight + Protrusion],
				center=true);
	  rotate([0,0,-(90 - ElArcAngle)])
	    translate([ElArcRadius + ElArcThick,0,ElArcHeight/2])
		  cube([2*ElArcRadius + ElArcThick,
				2*ElArcRadius + ElArcThick,
				ElArcHeight + Protrusion],
				center=true);
	}
  }
}

//----------------------
// Helmet Interface Plate

module HelmetPlate() {

  difference() {
	scale([ElPlateTall,ElPlateWidth,1.0])
	  cylinder(r=0.5,h=HelmetPlateThick,$fn=ElPlateFacets);

	translate([0,0,HelmetRX + HelmetPlateThick - HelmetPlateM])
	  sphere(r=HelmetRX,$fn=256,$fs=0.1);

  }
}

//----------------------
// Lash it together

if (Examine == "AzMount")
  AzMount();

if (Examine == "ElMount")
  ElMount();

if (Examine == "ElBody")
  ElBody();

if (Examine == "ElPlate")
  ElPlate();

if (Examine == "HelmetPlate")
  HelmetPlate();

if ((Layout == "Build" || Layout == "Show") && Examine == "None") {
  translate([-10,-20,0])
	rotate([0,0,90])					// mis-align top fill from ElMount
	  AzMount();

  translate([-10,20,ElMountLength + BearingOverlap])
	rotate([0,180,-90])
	  ElMount();

  translate([0,0,0])
	rotate([0,0,0])
	  ElBody();

  translate([10,15,0])
	rotate([0,0,215])					// mis-align top fill from ElBody
	  ElPlate();

  translate([20,-20,0])
	rotate([0,0,-45])
	  HelmetPlate();

  if (Layout == "Show")
	ShowPegGrid(PegSize);

}

if ((Layout == "Fit") && Examine == "None") {
  translate([0,0,-(AzMountLength/2 + MirrorShaftOffset)])
	color(MFG) AzMount();

  translate([0,0,AzMountLength/2 - MirrorShaftOffset - BearingOverlap])
	color(DHC) ElMount();
//	color([  0/255, 204/255, 204/255,0.5]) ElMount();

	translate([ElMountDia/2 + ElMountBase,0,0])
	  rotate([0,90,0])
		color(DFC) ElBody();

	translate([ElPlatePlusX,0,0])
	  rotate([180,90,0])
		color(LHC) ElPlate();

	translate([ElPlatePlusX,0,ElPlateTall/2 - ElBodyWidth/2])
	  rotate([0,90,0])
		color(LWM) HelmetPlate();
}

3 thoughts on “Helmet Mirror Mount: Solid Model

  1. > loose enough to move when you bump the mirror and tight enough to stay put in normal use

    Maybe put a compression spring under the heads of the tension screws (concealed in a square countersink), combined with cork or thin rubber at the friction point.

    1. cork or thin rubber

      Along those lines, this may be another good place for rubberdraulics: a dab of silicone rubber in the hole, compressed by the setscrew. I’ve never done anything quite that small, but it should be OK. The first two mounts work OK; I may just be borrowing trouble…

Comments are closed.