The deal was, if my Shop Assistant repaired my pocket camera, she could have it. She did, which meant I lost the ability to take pix through the microscope. While I was conjuring up a replacement, it occurred to me that I should also build a gadget to hold a close-up lens in front of the camera for tighter macro shots that don’t quite require a microscope’s magnification.
The solid model of the microscope adapter:

The close-up macro adapter, with an LED ring light around the snout:

They have a common camera mounting plate, with a hex recess for a 1/4-20 nut that mates with a standard tripod screw and some support material sticking up through the hole for the screw that holds the camera to the plate:

The main tube glues into the plate’s cutout and is long enough to accommodate the fully extended lens turret, with four shallow holes for filament snippet locating pins to align the snout:

An exploded view shows how everything fits together, with the stud below the camera representing its tripod mounting screw:

More details on the parts will appear over the next few days, but here’s the view through the macro adapter:

Yeah, some slight vignetting, but overall it’s pretty good.
The OpenSCAD source code that builds both adapters:
// Close-up lens mount & Microscope adapter for Canon SX230HS camera // Ed Nisley KE4ZNU - Nov 2011 Mount = "Eyepiece"; // End result: LEDRing Eyepiece Layout = "Show"; // Assembly: Show // Parts: Plate Tube LEDRing Camera Eyepiece // Build Plates: Build1..4 Gap = 12; // 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.02; 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 AlignPins = 4; AlignPinOD = 2.9; AlignPinCircleDia = TubeOD - 2*TubeWall - 2*AlignPinOD; // 2*PinOD -> more clearance //------- 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:AlignPins-1]) rotate(Index*90) translate([(AlignPinCircleDia/2),0,-ThreadThick]) rotate(180) // flat sides outward PolyCyl(AlignPinOD,TubeEndThickness); } } //- 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); 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:AlignPins-1]) rotate(Index*90) translate([(AlignPinCircleDia/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:AlignPins-1]) rotate(Index*90) translate([(AlignPinCircleDia/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,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(); }
The original doodles & dimensions:

11 thoughts on “Canon SX230HS Microscope and Close-up Macro Adapters”
Comments are closed.