Advertisements

Archive for November 19th, 2011

SX230HS Adapter: Main Tube and Assembly

The main tube connects the camera mounting plate and the snout on the front, so it’s a structural element of a sort. The ID fits over the non-moving lens turret base on the camera and the inner length is a few millimeters longer than the maximum lens turret extension:

Camera mount tube - interior

Camera mount tube - interior

As you might expect by now, the front bulkhead has four alignment peg holes for the snout:

Camera mount tube

Camera mount tube

The OpenSCAD code sets the wall thickness to 3 thread widths, but Skeinforge prints two adjacent threads with no fill at all. I think the polygon corners eliminate the one-thread-width fill and the perimeter threads wind up near enough to merge properly.

I assembled snouts to main tubes first, because it was easier to clamp bare cylinders to the bench:

Microscope eyepiece adapter - snout clamping

Microscope eyepiece adapter - snout clamping

Then glue the tube to the mounting plate using a couple of clamps:

Microscope eyepiece adapter - baseplate clamping

Microscope eyepiece adapter - baseplate clamping

The alignment is pretty close to being right, but if when I do this again I’ll add alignment pegs along the trench in the mounting plate to make sure the tube doesn’t ease slightly to one side, thusly:

SX230HS Macro Lens mount - solid model - exploded with pegs

SX230HS Macro Lens mount - solid model - exploded with pegs

You can see the entrance pupil isn’t quite filled in the last picture there, so a bit more attention to detail is in order. A bigger doublet lens would help, too.

The current version of the OpenSCAD source code with those pegs:

// Close-up lens mount & Microscope adapter for Canon SX230HS camera
// Ed Nisley KE4ZNU - Nov 2011

Mount = "LEDRing";			// End result: LEDRing Eyepiece

Layout = "Show";			// Assembly: Show
							// Parts: Plate Tube LEDRing Camera Eyepiece
							// Build Plates: Build1..4

Gap = 10;					// between "Show" objects

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

//-------
//- Extrusion parameters must match reality!
//  Print with +1 shells, 3 solid layers, 0.2 infill

ThreadThick = 0.33;
ThreadWidth = 2.0 * ThreadThick;

HoleFinagle = 0.2;
HoleFudge = 1.00;

function HoleAdjust(Diameter) = HoleFudge*Diameter + HoleFinagle;

Protrusion = 0.1;			// make holes end cleanly

function IntegerMultiple(Size,Unit) = Unit * ceil(Size / Unit);

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

// doublet lens

LensDia = 25.0;
LensRad = LensDia/2;
LensClearance = 0.2;

LensEdge = 6.7;
LensThick = 8.6;
LensRimThick = IntegerMultiple((2.0 + LensThick),ThreadThick);

// LED ring light

LEDRingOD = 50.0;
LEDRingID = 36.0;
LEDBoardThick = 1.5;
LEDThick = 4.0;
LEDRingClearance = 0.5;
LEDWireHoleDia = 3.0;

// microscope eyepiece

EyepieceOD = 30.0;
EyepieceID = 24.0;
EyepieceLength = 25.0;

// camera
// Origin at base of [0] ring, Z+ along lens axis, X+ toward bottom, Y+ toward left

CameraBodyWidth = 2*10.6;							// 2 x center-to-curve edge
CameraBaseWidth = 15.5;								// flat part of bottom front to back
CameraBaseRadius = (CameraBodyWidth - CameraBaseWidth)/2;	// edge rounding
CameraBaseLength = 60.0;							// centered on lens axis
CameraBaseHeight = 55.0;							// main body height
CameraBaseThick = 0.9;								// downward from lens ring

echo(str("Camera base radius: ",CameraBaseRadius));

TripodHoleOffset = -19.0;							// mount screw wrt lens centerline
TripodHoleDia = Clear025_20;						// clearance hole

TripodScrewHeadDia = 14.5;							// recess for screw mounting camera
TripodScrewHeadRad = TripodScrewHeadDia/2;
TripodScrewHeadThick = 3.0;

// main lens tube

TubeDia = 		[53.0,	44.0,	40.0,	37.6];		// lens rings, [0] is fixed to body
TubeLength = 	[8.1,	20.6,	17.6,	12.7];

TubeEndClearance = 2.0;								// camera lens end to tube end
TubeEndThickness = IntegerMultiple(1.5,ThreadThick);
TubeInnerClearance = 0.5;

TubeInnerLength = TubeLength[0] + TubeLength[1] + TubeLength[2] + TubeLength[3] +
				  TubeEndClearance;
TubeOuterLength = TubeInnerLength + TubeEndThickness;

TubeID = TubeDia[0] + TubeInnerClearance;
TubeOD = TubeID + 6*ThreadWidth;
TubeWall = (TubeOD - TubeID)/2;
TubeSides = 48;

echo(str("Main tube outer length: ",TubeOuterLength));
echo(str("          ID: ",TubeID," OD: ",TubeOD," wall: ",TubeWall));

// camera mounting base

BaseWidth = IntegerMultiple((CameraBaseWidth + 2*CameraBaseRadius),ThreadThick);
BaseLength = 60.0;
BaseThick = IntegerMultiple((1.0 + Nut025_20Thick + CameraBaseThick),ThreadThick);

// LED ring mount

LEDBaseThick = IntegerMultiple(2.0,ThreadThick);	// base under lens + LED ring
LEDBaseRimWidth = IntegerMultiple(6.0,ThreadWidth);
LEDBaseRimThick = IntegerMultiple(LensThick,ThreadThick);

LEDBaseOD = max((LEDRingOD + LEDRingClearance + LEDBaseRimWidth),TubeOD);

echo(str("LED Ring OD: ",LEDBaseOD));

// alignment pins between tube and LED ring / microscope eyepiece

AlignPinOD = 2.9;

SnoutPins = 4;
SnoutPinCircleDia = TubeOD - 2*TubeWall - 2*AlignPinOD;		// 2*PinOD -> more clearance

// alignment pins between tube and base plate

BasePins = 2;
BasePinOffset = 10.0;
BasePinSpacing = BaseLength/3;

//-------

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=HoleAdjust(FixDia)/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);

}

//-------

//- Camera body segment
//	Including lens base and peg for tripod hole access
//	Z=0 at edge of lens base ring, X=0 along lens axis

module CameraBody() {

  translate([0,0,-CameraBaseThick])
	rotate(90)
	  union() {
		translate([0,0,(CameraBaseHeight/2 + CameraBaseRadius)])
		  minkowski() {
			cube([CameraBaseWidth,
				  (CameraBaseLength + 2*Protrusion),
				  CameraBaseHeight],center=true);
			rotate([90,0,0])
			  cylinder(r=CameraBaseRadius,h=Protrusion,$fn=8);
		  }

		translate([0,0,(TubeDia[0]/2 + CameraBaseThick)])
		  rotate([0,90,0])
			rotate(180/TubeSides)
			  cylinder(r=(TubeDia[0]/2 + CameraBaseThick),
					  h=(CameraBodyWidth/2 + Protrusion),
					  $fn=TubeSides);

		translate([CameraBodyWidth/2,0,(TubeDia[0]/2 + CameraBaseThick)])
		  rotate([0,90,0])
			cylinder(r=TubeDia[0]/2,h=TubeLength[0]);

		translate([(TubeLength[0] + CameraBodyWidth/2),
				  0,(TubeDia[0]/2 + CameraBaseThick)])
		  rotate([0,90,0])
			cylinder(r=TubeDia[1]/2,h=TubeLength[1]);

		translate([(TubeLength[0] + TubeLength[1] + CameraBodyWidth/2),
				  0,(TubeDia[0]/2 + CameraBaseThick)])
		  rotate([0,90,0])
			cylinder(r=TubeDia[2]/2,h=TubeLength[2]);

		translate([(TubeLength[0] + TubeLength[1] + TubeLength[2] + CameraBodyWidth/2),
				  0,(TubeDia[0]/2 + CameraBaseThick)])
		  rotate([0,90,0])
			cylinder(r=TubeDia[3]/2,h=TubeLength[3]);

		translate([0,TripodHoleOffset,-BaseThick])
		  PolyCyl(TripodHoleDia,(BaseThick + 2*Protrusion));

	  }
}

//- Main tube

module Tube() {

  difference() {
	cylinder(r=TubeOD/2,h=TubeOuterLength,$fn=TubeSides);

	translate([0,0,TubeEndThickness])
	  PolyCyl(TubeID,(TubeInnerLength + Protrusion),TubeSides);

	translate([0,0,-Protrusion]) {
	  if (Mount == "LEDRing")
		cylinder(r=LensRad,h=(TubeEndThickness + 2*Protrusion));
	  if (Mount == "Eyepiece")
		cylinder(r=EyepieceID/2,h=(TubeEndThickness + 2*Protrusion));
	}

	for (Index = [0:SnoutPins-1])
	  rotate(Index*90)
		translate([(SnoutPinCircleDia/2),0,-ThreadThick])
		  rotate(180)			// flat sides outward
			PolyCyl(AlignPinOD,TubeEndThickness);

	for (Index = [0:BasePins-1])
		translate([0,-(TubeOD/2 + Protrusion),
				  (TubeOuterLength - BasePinOffset - Index*BasePinSpacing)])
		  rotate([-90,90,0])					// y = flat toward camera
			PolyCyl(AlignPinOD,(TubeWall + 2*Protrusion));
  }

}

//- Base plate

module BasePlate() {

  union() {
	difference() {
		linear_extrude(height=BaseThick)
		  hull() {
			translate([-(BaseLength/2 - BaseWidth/2),0,0])
			  circle(BaseWidth/2);
			translate([ (BaseLength/2 - BaseWidth/2),0,0])
			  circle(BaseWidth/2);
			translate([0,(0.75*BaseLength),0])
			  circle(BaseWidth/2);
		  }

		translate([0,0,BaseThick])
		  CameraBody();

		translate([0,(TubeOuterLength + CameraBodyWidth/2),
				  (BaseThick + TubeDia[0]/2)])
		  rotate([90,0,0])
			PolyCyl(TubeOD,TubeOuterLength,$fn=TubeSides);

		for (Index = [0:BasePins-1])
			translate([0,(CameraBodyWidth/2 + BasePinOffset + Index*BasePinSpacing),
					  3*ThreadThick])
			  rotate(90)										// flat toward camera
				PolyCyl(AlignPinOD,BaseThick);

		translate([0,0,3*ThreadThick])
		  PolyCyl((Nut025_20Dia*sqrt(3)/2),2*Nut025_20Thick,6);	// dia across hex flats

		translate([0,0,-Protrusion])
		  PolyCyl(Clear025_20,(BaseThick + 2*Protrusion));

		translate([TripodHoleOffset,0,3*ThreadThick])
		  PolyCyl((Nut025_20Dia*sqrt(3)/2),2*Nut025_20Thick,6);	// dia across hex flats

		translate([TripodHoleOffset,0,-Protrusion])
		  PolyCyl(Clear025_20,(BaseThick + 2*Protrusion));

		translate([-TripodHoleOffset,0,-Protrusion])
		  PolyCyl(TripodScrewHeadDia,(TripodScrewHeadThick + Protrusion));
	}

	translate([-TripodHoleOffset,0,0]) {				// support for tripod screw hole
	  for (Index=[0:3])
		rotate(Index*45)
		  translate([-ThreadWidth,-TripodScrewHeadRad,0])
			cube([2*ThreadWidth,TripodScrewHeadDia,TripodScrewHeadThick]);

	  cylinder(r=0.4*TripodScrewHeadRad,h=(BaseThick - CameraBaseThick),$fn=9);
	}
  }
}

//- LED mounting ring

module LEDRing() {

  difference() {
	cylinder(r=LEDBaseOD/2,h=LensRimThick,$fn=48);

	translate([0,0,-Protrusion])
	  PolyCyl((LensDia + LensClearance),
			  (LensRimThick + 2*Protrusion));

	translate([0,0,LEDBaseRimThick])
	  difference() {
		PolyCyl(LEDBaseOD,LensThick);
		PolyCyl(LEDRingID,LensThick);
	  }

	translate([0,0,LEDBaseThick])
	  difference() {
		PolyCyl((LEDRingOD + LEDRingClearance),LensThick);
		cylinder(r1=HoleAdjust(LEDRingID - LEDRingClearance)/2,
				 r2=HoleAdjust(LensDia + LensClearance)/2 + 2*ThreadWidth,
				 h=LensThick);
	  }

	for (Index = [0:SnoutPins-1])
	  rotate(Index*90)
		translate([(SnoutPinCircleDia/2),0,-ThreadThick])
		  rotate(180)			// flat sides outward
			PolyCyl(AlignPinOD,LEDBaseThick);

	rotate(45)
	  translate([0,LEDRingID/2,(LEDBaseThick + 1.2*LEDWireHoleDia/2)])
		rotate([0,-90,0])			// flat side down
		  rotate([-90,0,0])
			PolyCyl(LEDWireHoleDia,2*LEDBaseRimWidth);
  }

}

//- Microscope eyepiece adapter

module EyepieceMount() {

  difference() {
	cylinder(r1=TubeOD/2,
			 r2=(EyepieceOD + 8*ThreadWidth)/2,
			 h=EyepieceLength,
			 $fn=TubeSides);

	translate([0,0,-Protrusion])
	  PolyCyl(EyepieceOD,(EyepieceLength + 2*Protrusion));

	for (Index = [0:SnoutPins-1])
	  rotate(Index*90)
		translate([(SnoutPinCircleDia/2),0,-ThreadThick])
		  rotate(180)			// flat sides outward
			PolyCyl(AlignPinOD,6*ThreadThick);
  }

}

//-------
// Build it!

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

if (Layout == "Tube")
  Tube();

if (Layout == "LEDRing")
  LEDRing();

if (Layout == "Plate")
  BasePlate();

if (Layout == "Camera")
  CameraBody();

if (Layout == "Eyepiece")
  EyepieceMount();

if (Layout == "Build1")
  translate([0,-BaseLength/3,0])
	BasePlate();

if (Layout == "Build2")
  Tube();

if (Layout == "Build3")
  LEDRing();

if (Layout == "Build4")
  EyepieceMount();

if (Layout == "Show") {
  translate([0,TubeOuterLength,TubeDia[0]/2]) {
	rotate([90,0,0])
	  color(LTC) Tube();
	translate([0,(Gap/2 - TubeEndThickness - Protrusion),0])
	  rotate([-90,0,0])
		for (Index = [0:SnoutPins-1])
		  rotate(Index*90)
			translate([(SnoutPinCircleDia/2),0,0])
			  rotate(180)			// flat sides outward
				PolyCyl(AlignPinOD,(TubeEndThickness + LEDBaseThick));

	translate([0,Gap,0])
	  rotate([-90,0,0]) {
		if (Mount == "LEDRing")
		  color(OOR) LEDRing();
		if (Mount == "Eyepiece")
		  color(OOR) EyepieceMount();
	  }
  }

  translate([0,-CameraBodyWidth/2,0])
	color(PG) CameraBody();

  color(PDA)
	render()
	translate([0,-CameraBodyWidth/2,-(BaseThick + Gap)])
	  BasePlate();

  for (Index = [0:BasePins-1])
	  translate([0,(BasePinOffset + Index*BasePinSpacing),
				-Gap/2])
		rotate([180,0,90])										// flat toward camera
		  PolyCyl(AlignPinOD,BaseThick/2);

}
Advertisements

Leave a comment