...
 
Commits (24)
......@@ -12,10 +12,12 @@
docs/*.zip
# Ignore automatically built files
Makefile
builds/
docs/Output/
*.stl.d
ninja.build
build.ninja
.ninja_deps
.ninja_log
......
......@@ -19,6 +19,7 @@ build:
# Build STL files with OpenSCAD
- mkdir -p /root/.local/share
- ./build.py
- rm builds/*.stl.d
artifacts:
expire_in: 1 week
......
This diff is collapsed.
......@@ -149,7 +149,7 @@ module band_tool_2(handle=true){
}
//cut out to get nice rounded corners at the bottom of the slot for the hook
hull() reflect([1,0,0]) prong_frame(){
translate(blade_anchor + [-2.25,3,h]) sphere(r=1.5,h=99);
translate(blade_anchor + [-2.25,3,h]) sphere(r=1.5);
translate(blade_anchor + [-1.5,10,0.5]) cube([1.5/2,999,999]);
}
}
......
......@@ -33,7 +33,6 @@ dt_bottom = -2; //where the dovetail starts (<0 to allow some play)
camera_mount_top = dt_bottom - 3 - (optics=="rms_f50d13"?11:0); //the 50mm tube lens requires the camera to stick out the bottom.
bottom = camera_mount_top-camera_mount_height(); //nominal distance from PCB to microscope bottom
fl_cube_bottom = optics=="rms_f50d13"?-8:0; //bottom of the fluorescence filter cube
fl_cube_w = 16; //width of the fluorescence filter cube
fl_cube_top = fl_cube_bottom + fl_cube_w + 2.7; //top of fluorescence cube
fl_cube_top_w = fl_cube_w - 2.7;
d = 0.05;
......
/******************************************************************
* *
* OpenFlexure Microscope: Optics unit *
* *
* This is part of the OpenFlexure microscope, an open-source *
* microscope and 3-axis translation stage. It gets really good *
* precision over a ~10mm range, by using plastic flexure *
* mechanisms. *
* *
* The optics module holds the camera and whatever lens you are *
* using as an objective - current options are either the lens *
* from the Raspberry Pi camera module, or an RMS objective lens *
* and a second "tube length conversion" lens (usually 40mm). *
* *
* See the section at the bottom of the file for different *
* versions, to suit different combinations of optics/cameras. *
* NB you set the camera in the variable at the top of the file. *
* *
* (c) Richard Bowman, January 2016 *
* Released under the CERN Open Hardware License *
* *
******************************************************************/
use <utilities.scad>;
include <microscope_parameters.scad>; // NB this defines "camera" and "optics"
module chamfer_bottom_edge(chamfer=0.3, h=0.5){
difference(){
children();
minkowski(){
cylinder(r1=2*chamfer, r2=0, h=2*h, center=true);
linear_extrude(d) difference(){
square(9999, center=true);
projection(cut=true) translate([0,0,-d]) hull() children();
}
}
}
}
module fl_cube_outer(){
// The outer body for fl_cube()
roc = 0.6;
w = fl_cube_w;
foot = roc*0.7;
bottom_t = roc*3;
$fn=8;
chamfer_bottom_edge() union(){
reflect([1,0,0]){
// outer "arms" that are responsible for the tight fit
sequential_hull(){
translate([w/2-2-roc*0.8/sqrt(2), w+2-roc*1.2, 0]) cylinder(r=roc, h=w);
translate([w/2-roc, w-roc/sqrt(2), 0]) cylinder(r=roc, h=w);
translate([w/2-roc, foot+bottom_t+roc, 0]) cylinder(r=roc, h=w);
}
translate([w/2-3*roc, foot+bottom_t+roc, 0]) difference(){
// the curved bits at the bottom
resize([0,(bottom_t+roc)*2,0]) cylinder(r=3*roc, h=w, $fn=24);
// cut out the inner radius
cylinder(r=roc, h=999, center=true);
// restrict it to a quarter-turn
mirror([1,0,0]) translate([-roc,0,-99]) cube(999);
mirror([1,0,0]) translate([0,-roc,-99]) cube(999);
}
}
// join the two arms together at the bottom
translate([0,foot+bottom_t/2, w/2]) cube([w - roc*3*2 + 2*d, bottom_t, w], center=true);
// feet at the bottom (and also in the middle of the top part)
for(p = [[-w/2+roc*3, roc, roc+0.5],
[w/2-roc*3, roc, roc+0.5],
[0, roc, w-roc],
[w/2-2-roc*0.3/sqrt(2), w+2-roc*1.2, w/2],
[-(w/2-2-roc*0.3/sqrt(2)), w+2-roc*1.0, w/2]
]){
translate(p) sphere(r=roc,$fn=8);
}
}
}
module fl_cube(){
// Filter cube that slots into a suitably-modified optics module
// This prints with the Y axis vertical - to save rotating all the
// cylinders, it's written here as printed.
roc = 0.6;
w = fl_cube_w;
foot = roc*0.7;
bottom_t = roc*3;
dichroic = [12,16,1.1];
dichroic_t = dichroic[2];
emission_filter = [10,14,1.5];
beamsplit = [0, w/2+2, w/2];
inner_w = w - 6*roc;
bottom = bottom_t + foot;
$fn=8;
difference(){
union(){
fl_cube_outer();
// mount for 45 degree dichroic, with bottom retaining clip
by = beamsplit[1] + dichroic[1]/2/sqrt(2) + 0.3; //coated tip of dichroic + wiggle room
bz = beamsplit[2] - dichroic[1]/2/sqrt(2) + 0.3; //coated tip of dichroic + wiggle room
bby = beamsplit[1] + dichroic[1]/2/sqrt(2) - dichroic[2]/sqrt(2); //back tip of dichroic
bbz = beamsplit[2] - dichroic[1]/2/sqrt(2) - dichroic[2]/sqrt(2); //back tip of dichroic
sequential_hull(){
translate([-inner_w/2, bottom, 0]) cube([inner_w, d, beamsplit[2] + beamsplit[1] - bottom - dichroic_t*sqrt(2)]); // tall back of triangle
translate([-inner_w/2, bby, 0]) cube([inner_w, d, bbz]); //pointy end of triangle
translate([-inner_w/2+2, by, 0]) cube([inner_w-4, 1.5, bz]); //far end
translate([-inner_w/2+2, by, bz]) cube([inner_w-4, 1.5, d]); //start of retaining clip
translate([-inner_w/2, by - 4, 4 + 2*dichroic_t]) cube([inner_w, 2, d]); //end of retaining clip
translate([-inner_w/2, by - 5, 4 + 2*dichroic_t]) cube([inner_w, 2, 1]); //overhanging bit
}
// attachment for the excitation filter and LED
reflect([1,0,0]) translate([-w/2, bottom + 4, w]) sequential_hull(){
depth = w-bottom-4-roc;
translate([0,0,-roc]) cube([2*roc, depth, d]);
translate([0.5,0,roc]) cube([2*roc, depth, 1.5]);
translate([0.5+2*roc + 1.5 - 0.2*(1+sqrt(2)),0,roc+1.5-0.2]) rotate([-90,0,0]) cylinder(r=0.2, h=depth);//cube([2*roc + 1.5, depth, d]);
}
}
// hole for the beam
translate(beamsplit) rotate([90,0,0]) cylinder(r=5,h=999, center=true, $fn=32);
// hole for the emission filter
translate([-emission_filter[0]/2, bottom - roc*1.5, beamsplit[2]-emission_filter[1]/2]) cube([emission_filter[0], emission_filter[2], 999]);
// access hole for the dichroic
translate(beamsplit) rotate([-45,0,0]) translate([0,-dichroic[1]/2,0]) scale([1.1,1,1.9]) cube(dichroic, center=true);
}
}
fl_cube();
\ No newline at end of file
......@@ -110,7 +110,7 @@ module thumbwheel(r=10,h=5,knobble_r=1,knobble_angle=45,chamfer=0.5){
for( n = [0 : n_lobe-1] )
{
deg = 360*n/n_lobe;
translate([lobe_r*sin(deg),lobe_r*cos(deg),base_h]){cone_cyl(r=lobe_r,lobe_h=5);}
translate([lobe_r*sin(deg),lobe_r*cos(deg),base_h]){cone_cyl(r=lobe_r,h=lobe_h);}
}
}
translate([0,0,1.5]) nut(3,shaft=true,fudge=1.2,h=999);
......
......@@ -20,6 +20,7 @@ use <./z_axis.scad>;
use <./gears.scad>;
use <./wall.scad>;
use <./main_body_transforms.scad>;
use <./reflection_illuminator.scad>;
include <./microscope_parameters.scad>; //All the geometric variables are now in here.
......@@ -113,7 +114,8 @@ module xy_limit_switch_mount(d=3.3*2, h=6){
// The "wall" that forms most of the microscope's structure
module wall_inside_xy_stage(){
module wall_inside_xy_stage(beamsplitter=false){
front_wall_height = beamsplitter ? zawall_h : wall_h;
// First, go around the inside of the legs, under the stage.
// This starts at the Z nut seat. I've split it into two
// blocks, because the shape is not convex so the base
......@@ -125,9 +127,10 @@ module wall_inside_xy_stage(){
inner_wall_vertex(45, -leg_outer_w/2, zawall_h);
z_anchor_wall_vertex();
inner_wall_vertex(135, leg_outer_w/2, zawall_h);
inner_wall_vertex(135, -leg_outer_w/2, wall_h);
inner_wall_vertex(-135, leg_outer_w/2, wall_h);
}
inner_wall_vertex(135, -leg_outer_w/2, front_wall_height);
inner_wall_vertex(-135, leg_outer_w/2, front_wall_height);
};
}
module wall_outside_xy_actuators(){
......@@ -161,6 +164,21 @@ module wall_between_actuators(){
}
}
// Cut out hole for reflection illuminator
module fl_cube_cutout(){
// size of cutout for fl cube
top_cutout_w = 17.8; // As big as we can get at height 'wall_h' without bridging a corner
mid_cutout_w = illuminator_width() + 1;
bottom_cutout_w = illuminator_width() + 4;
// Create a trapezoid with min width (cube_width) at top
hull() {
translate([-(bottom_cutout_w)/2, -49, -0.5]) cube([bottom_cutout_w, 49, 1]);
translate([-(mid_cutout_w)/2, -49, 10]) cube([mid_cutout_w, 49, 1]); // Highest we usually need
translate([-top_cutout_w/2, -49, wall_h]) cube([top_cutout_w, 49, 1]);
}
}
///////////////////// MAIN STRUCTURE STARTS HERE ///////////////
exterior_brim(r=enable_smart_brim ? smart_brim_r : 0)
difference(){
......@@ -216,7 +234,7 @@ union(){
union(){
////////////// Reinforcing wall and base /////////////////
//Add_hull_base generates the flat base of the structure.
add_hull_base(base_t) wall_inside_xy_stage();
add_hull_base(base_t) wall_inside_xy_stage(beamsplitter=beamsplitter);
// add mounts for the optical end-stops for X and Y
reflect([1,0,0]) hull(){
inner_wall_vertex(45, -9, zawall_h);
......@@ -241,6 +259,11 @@ union(){
}
////// Things we need to cut out holes for... ///////////
// Beamsplitter cube
if (beamsplitter) {
fl_cube_cutout();
}
// XY actuator cut-outs
each_actuator(){
actuator_silhouette(xy_actuator_travel+actuator[2]);
......
......@@ -124,4 +124,6 @@ endstop_hole_offset=0;
//without this with 15mm hole the stage hits the objective
//the stage can move ~3mm in each direction, so the actuator only moves
//~1.7 mm
avoid_objective_xyfoot_offset=xy_actuator_travel-1.8;
\ No newline at end of file
avoid_objective_xyfoot_offset=xy_actuator_travel-1.8;
fl_cube_w = 16; //width of the fluorescence filter cube
\ No newline at end of file
......@@ -231,6 +231,9 @@ module microscope_stand(){
mounting_holes();
// if we are building for reflection illumination, cut out the front to allow access
if(beamsplitter) translate([0,0,h+foot_height]) rotate([90,0,0]) cylinder(d=30,h=999);
}
}
......
This diff is collapsed.
use <./utilities.scad>;
use <./optics.scad>;
include <./microscope_parameters.scad>;
use <./dovetail.scad>;
base_r = 8.5; // must be >= lens_r+1
module fl_led_mount(led_d=5){
// This part clips on to the filter cube, to allow a light source (generally LED) to be coupled in using the beamsplitter.
roc = 0.6;
w = fl_cube_w - 1; //nominal width of the mount (is the width between the outsides of the dovetail clip points)
dovetail_pinch = fl_cube_w - 4*roc - 1 - 3; //width between the pinch-points of the dovetail
h = fl_cube_w - 1; //should probably be fl_cube_w
led_z = fl_cube_w/2;//+2;
filter = [10,14,1.5];
beamsplit = [0, 0, w/2]; //NB different to fl_cube because we're printing with z=z here.
$fn=8;
front_t = 2;
back_y = fl_cube_w/2 + roc + 1.5; //flat of dovetail (we actually start 1.5mm behind this)
led_y = back_y+3; //don't worry about precise imaging (is this OK?)
front_y = led_y + front_t;
union() translate([0,0,0]){
difference(){
union(){
translate([0, back_y, 0]) mirror([0,1,0]) dovetail_m([w, 1, h], t=2*roc);
hull(){
translate([-w/2,back_y,0]) cube([w,d,h]);
reflect([1,0,0]) translate([w/2-3*roc, front_y - 3*roc, 0]) cylinder(r=3*roc, h=h, $fn=16);
}
hull(){
l=3.5;
translate([-w/2+2.5,back_y-1.5+d,led_z-led_d/2-2-l]) cube([w-5,d,led_d+4+l]);
translate([-w/2+2.5,back_y-1.5+d-l,led_z-led_d/2-2]) cube([w-5,d,led_d+4]);
}
}
// add a hole for the LED
translate([0,led_y,led_z]){
cylinder_with_45deg_top(h=999, r=led_d/2*1.05, $fn=16, extra_height=0, center=true); //LED
cylinder_with_45deg_top(h=999, r=(led_d+1)/2*1.05, $fn=16, extra_height=0);
}
}
}
}
module lens_holder(led_d=5){
// A simple one-lens condenser, re-imaging the LED onto the sample.
led_h = 8; //distance from bottom to the top of the LED
aperture_h = 2;
aperture_to_lens = 6.5; //distance from aperture stop to lens
aperture_stop_r = 0.6;
lens_z = led_h + aperture_to_lens + aperture_h;
pedestal_h = 3;
lens_r = 13/2;
lens_t = 1;
led_r = led_d/2;
difference(){
union(){
//lens gripper to hold the plastic asphere
translate([0,0,lens_z-pedestal_h]){
// gripper
trylinder_gripper(inner_r=lens_r, grip_h=pedestal_h + lens_t/3,h=pedestal_h+lens_t+1.5, base_r=base_r, flare=0.5);
// pedestal to raise the tube lens up within the gripper
cylinder(r=lens_r-0.5,h=pedestal_h);
}
cylinder(r=base_r, h=lens_z-pedestal_h+d);
}
//beam
hull(){ // todo: make this a light trap?
translate([0,0,led_h+aperture_h-d]) cylinder(r=d,h=d);
translate([0,0,led_h+aperture_h+1]) cylinder(r=4,h=d);
//translate([0,0,lens_z]) cube([3,4,d], center=true);
translate([0,0,lens_z]) cylinder(r=lens_r-2,h=d);
}
//LED
deformable_hole_trylinder(led_r-0.1,led_r+0.6,h=2*led_h+d, center=true);
translate([0,0,led_h]) cylinder(r1=led_r+0.6, r2=aperture_stop_r,h=aperture_h-0.5+d);
translate([0,0,led_h+aperture_h]) cylinder(r=aperture_stop_r,h=2,center=true);
cylinder(r=led_r+0.5, h=1.5, center=true);
}
}
module field_stop(aperture=[3,4], illuminator_d=2*base_r, h=5){
// a cylindrical plug with a rectangular aperture in it
difference(){
cylinder(d=illuminator_d, h=h);
hull(){
linear_extrude(0.5, center=true) square(aperture, center=true);
translate([0,0,h]) cylinder(d=illuminator_d - 5, h=1);
}
}
}
// Function we can import to get width of illuminator holder
function illuminator_width() = (2*base_r) + 4;
// Geometry of illuminator holder
module illuminator_holder(){
illuminator_d = 2*base_r; // Illuminator diameter
h = fl_cube_width() - 1; // Illuminator holder height
w = illuminator_width(); // Illuminator holder width
difference(){
union(){
fl_led_mount();
translate([-illuminator_d/2-2,10.5,0]) cube([w,40,h]); //80 was 40 in the one I made earlier...
}
//translate([0,13,0]) rotate([-90,0,0]) cylinder(h=999,r=999,$fn=5);
// grip the illuminator
translate([0,16, h/2]) rotate([-90,0,0]) cylinder(h=999,d=illuminator_d);
translate([-w/2+2,15,-1]) cube([w-4, 4+d,999]); // cut out flexible bits
translate([-w/2+5,19,-1]) cube([w-5*2, 999,999]); // cut out flexible bits
// cable tie grooves to squeeze it
repeat([0,12,0],4) translate([0,22,h/2]) rotate([-90,0,0]) difference(){
cylinder(d=999,h=4.5,$fn=5);
cylinder(d=illuminator_d + 2*3, h=999, center=true);
}
// beam
translate([0,0,h/2]) rotate([-90,0,0]) cylinder(d=7, h=999, center=true);
}
}
translate([20,20,0]) rotate(90) illuminator_holder();
translate([-20,0,0]) field_stop();
lens_holder();
//difference(){
// lens_holder();
// //rotate([90,0,0]) //mirror([0,0,1])
// translate([0,0,10]) cylinder(r=99,h=999,$fn=5);
//}
//for(i=[0:3]) translate([i*15,-20, 0]) difference(){
// cylinder(h=0.5 * pow(2,i), d=12);
// cylinder(h=999,d=6,center=true);
//}
\ No newline at end of file