def rpi_cam_plate(thick=5): "plate for raspberry pi camera, with camera at [0,0,0], facing down" rpi_holes_x_2 = 21 / 2 rpi_holes_y = 12.5 rpi_border = 2 rpi_ysize = 23.86 rpi_ytop = 14.5 rpi_xsize = 25 gap_xsize = 11.5 # width for offset camera connector gap_ysize = 20 plate_ycenter = rpi_ytop - rpi_ysize / 2 rpi_plate = rounded_plate((rpi_xsize, rpi_ysize, thick), rpi_border) rpi_plate = translate([0, plate_ycenter, thick / 2])( rpi_plate) # one pair of holes (and camera) are at y=0 rpi_plate -= translate((0, plate_ycenter, thick / 2))(rounded_plate( (gap_xsize, gap_ysize, 2 * thick), 1)) for x in [rpi_holes_x_2, -rpi_holes_x_2]: for y in [0, rpi_holes_y]: hole = translate([x, y, 0])(sunk_hole()) rpi_plate -= hole return rpi_plate
def crane_45deg_mirror(): """Mount for 45deg movable mirror""" screw_dist_from_center = 30/2/2**.5 # Four holes on circle d=30 mirror_plate_wh = 30 thick = 10 mirror_offset = 35 # TODO: calc dist_to_cam = 300 mirror_angle_deg = -numpy.rad2deg(numpy.arctan(mirror_offset/dist_to_cam))/2 plate = rounded_plate((40, 40, thick), 2) plate -= rounded_plate((30, 30, 2*thick), 2) mirror_plate_blank = rounded_plate((mirror_plate_wh, mirror_plate_wh, thick), 2) mirror_plate_blank += hole()(cylinder(d=20, h=2*thick, center=True)) mirror_plate_threads = mirror_plate_blank for (x,y) in itertools.product((1, -1), (1,-1)): thread = hole()(rotate((0, 180, 0))(sunk_hole())) # from above into z=0 mirror_plate_threads += translate((x*screw_dist_from_center, y*screw_dist_from_center, thick/2))(thread) mirror_plate_threads = rotate((0, mirror_angle_deg, 0))(mirror_plate_threads) mirror_plate_threads = translate((0, 0, 40*numpy.tan(numpy.deg2rad(-mirror_angle_deg))))(mirror_plate_threads) plate += translate((mirror_offset, 0, 0))(mirror_plate_blank) plate += translate((mirror_offset, 0, 0))(mirror_plate_threads) plate += base() return plate
def cage_side_stabilizer(): """stabilizer for both sides of new HolMOS-Cage""" sep_z = 100 sep_x = base.rods30_diag_third_rod strut_width = 10 strut_thick = 3 diagonal = (sep_x**2 + sep_z**2)**.5 strut_angle_deg = numpy.rad2deg(numpy.arctan(sep_x / sep_z)) # angle < 45° diag_strut = rounded_plate( (strut_width, diagonal + strut_width, strut_thick), strut_width / 2) cross = rotate((0, 0, -strut_angle_deg))(diag_strut) cross += rotate((0, 0, strut_angle_deg))(diag_strut) cross = translate((0, 0, -strut_thick / 2))(cross) # to z=0...-thick, mount_strut = cube((sep_x, strut_width, strut_thick), center=True) mount_strut = translate( (0, 0, -strut_thick / 2))(mount_strut) # to z=0...-thick, mount_strut += rotate((-90, 0, 0))(translate((0, 20, 0))(base.base_rods30( rod_sep=sep_x))) # from optical-axis coords to our coords. cross += translate((0, sep_z / 2, 0))(mount_strut) cross += translate((0, -sep_z / 2, 0))(mount_strut) return cross
def objective_mount(): """mount for microscope objective""" mount = rounded_plate([40, 40, 10], r=5) mount -= owis_holes(True) mount -= cylinder(d=20, center=True, h=11) return mount
def crane_mirror(assemble=True, mirror_offset_x=25, crane_only=False): """Mount for 45deg movable mirror assemble=True: put things where they're supposed to go assemble=False: put things on printer bed""" thick = 10 dist_to_cam = 200 arm_width = 5.5 mirror_z = 17 rod_thick = 6 rod_to_mirror = 2*arm_width deflection_angle_rad = numpy.pi/2+numpy.arctan(mirror_offset_x/dist_to_cam) mirror_angle_rad = deflection_angle_rad/2 rod_z = mirror_z - rod_to_mirror*numpy.cos(mirror_angle_rad) # z-height of rod for y-rotation rod_x = mirror_offset_x + rod_to_mirror*numpy.sin(mirror_angle_rad) plate = rounded_plate((40, 40, thick), 2) plate -= translate((10,0,0))(rounded_plate((50, 30, 2*thick), 2)) arm_length = rod_x-20 clip_arm = cube((arm_length+arm_width, thick, arm_width), center=True) # thick <-> width because rotated x<->z clip_arm = rotate((90, 0, 0))(clip_arm) clip_arm = translate((arm_length/2+20, 20-arm_width/2, 0))(clip_arm) clip_arm += translate((rod_x, 20-arm_width/2, rod_z))(rotate((-90, 0, 0))(single_rod_clamp(arm_width))) plate += clip_arm plate += mirror((0, 1, 0))(clip_arm) if not crane_only: mirror_intermediate = crane_mirror_intermediate(rod_thick, arm_width, rod_to_mirror, assemble) if assemble: plate += translate((rod_x, 0, rod_z))( rotate((0, -numpy.rad2deg(mirror_angle_rad), 0))(mirror_intermediate) ) else: plate += translate((mirror_offset_x + 30, 0, -thick/2+rod_thick/2))(mirror_intermediate) plate += base() if assemble: plate = rotate((0, 180, 0))(plate) return plate
def strut_with_holes(hole_dist, strut_thick, strut_width, hole_diam=2): """flat strut with two holes at y=+-hole_dist""" diag_strut = rounded_plate( (strut_width, hole_dist + strut_width, strut_thick), strut_width / 2) for y in (hole_dist / 2, -hole_dist / 2): thread = sunk_hole(length=50, r=hole_diam / 2) thread = hole()(thread) diag_strut += translate((0, y, -strut_thick / 2))(thread) return diag_strut
def single_rod_clamp(z_length=10, tightness=__rods30_tightness): """single clamp to attach to a z-tube. The tube is at xy = (0,5), so that this clamp attaches to things at y=0...height :param tightness: diameter reduction of clamp. larger values give tighter fit.""" diam_hole = 6 - tightness clamp_diff = .5 # how much smaller is the clamp, i.e. how far does it need to bend? mount_height = 10 # height (y) of mount block = rounded_plate((2 * diam_hole, mount_height, z_length), r=2) block += hole()(cylinder(d=diam_hole, h=1.1 * z_length, center=True)) block += hole()(translate((-clamp_diff / 2, -3, 0))(cube( (diam_hole - clamp_diff, 6, 1.1 * z_length), center=True))) # "tunnel" for rod to slide into clip return block()
def rpi_cam_mount(assemble=False): # https://www.raspberrypi.org/documentation/hardware/camera/mechanical/rpi_MECH_Camera2_2p1.pdf # 2016-11-30: printed; works. but: needs 4 spacers to keep the smd components on the back of the camera from touching the plate. rpi_thick = 3 strut_y_end = 14.5 struts_x = [-7.5, 7.5] strut_thick = 3 base_thick = 5 # base_plate = translate([0, -20+base_thick/2, 0])(cube([40, base_thick, 10], center=True)) base_plate = translate([0, -20 + base_thick / 2, 0])(rotate([90, 0, 0])(rounded_plate([30, 10, base_thick], 2))) base_plate += base() plate = translate([0, 0, -5])(rpi_cam_plate(rpi_thick)) for strut_x in struts_x: strut = translate([strut_x, -(20 - strut_y_end) / 2, 0])(cube([strut_thick, 20 + strut_y_end, 10], center=True)) cyl = rotate([0, 90, 0])(cylinder( r=10, h=50, center=True)) # cylinder along x-axis, in origin cyl = scale([1, (strut_y_end + 20 - base_thick) / 10, 1])(cyl) # z=10, y = strut height cyl = translate([0, -20 + base_thick, -5])(cyl) # axis into front top edge of base plate strut *= cyl plate += strut mount = base_plate + plate return mount
def round_mount_light(inner_diam=17.9, ring_thick=3, opening_angle=30, stop_inner_diam=None, cyl_length=10, clip_length=10, assemble=False): """ mount for cylinder centered on optical axis (z). If opening_angle is None, clamping tabs are added. defaults: mount for Kosmos objective :param inner_diam: usually diameter of thing to be mounted :param ring_thick: thickness of ring determines stiffness :param opening_angle: ring is opened from -angle to +angle :param stop_inner_diam: if not None, a smaller second cylinder acts as a stop, i.e. for a lens. :return: Scad object """ base_thick = 5 connector_w = 3 z_thick = 10 # thickness/z-length of entire assembly z_think_inner = 2 do_clamp = False if opening_angle is None: do_clamp = True opening_angle = numpy.arcsin(ring_thick / inner_diam) opening_angle = numpy.rad2deg(opening_angle) base_plate = translate([0, -20 + base_thick / 2, 0])(rotate([90, 0, 0])(rounded_plate([30, 10, base_thick], 4))) base_plate += translate( (0, 0, (clip_length - 10) / 2))(base(z_length=clip_length)) outer_diam = inner_diam + 2 * ring_thick ring = cyl_arc(r=outer_diam / 2, h=cyl_length, a0=90 + opening_angle, a1=90 - opening_angle) ring = translate((0, 0, (cyl_length - z_thick) / 2))(ring) if stop_inner_diam is None: ring -= cylinder(d=inner_diam, h=2 * cyl_length, center=True) else: ring -= cylinder(d=stop_inner_diam, h=2 * cyl_length, center=True) ring -= translate((0, 0, z_think_inner))(cylinder(d=inner_diam, h=z_thick, center=True)) if do_clamp: # clamps with holes extending towards +y hex_diam = 5.5 # M3 nut clamp_extension = hex_diam + 2 hole_diam = 3.5 clamp_length = ring_thick + clamp_extension single_clamp = rounded_plate((clamp_length, z_thick, ring_thick), True) through_nut_hole = cylinder(d=hole_diam, h=2 * ring_thick, center=True) through_nut_hole += translate( (0, 0, ring_thick / 2))(hexagon(hex_diam, ring_thick / 3)) single_clamp -= translate([ring_thick / 2, 0, 0])(through_nut_hole) ring += translate([ring_thick, inner_diam / 2 + clamp_length / 2, 0])(rotate([90, 0, 90])(single_clamp)) ring += translate([-ring_thick, inner_diam / 2 + clamp_length / 2, 0])(rotate([-90, 0, 90])(single_clamp)) connector_h = (40 - inner_diam) / 2 connector_yc = inner_diam / 2 + connector_h / 2 connector = translate([5, -connector_yc, 0])(cube([connector_w, connector_h, z_thick], center=True)) connector += translate([-5, -connector_yc, 0])(cube([connector_w, connector_h, z_thick], center=True)) label = "d = {:.1f}".format(inner_diam) info_text = linear_extrude(height=.5, center=True)(text( label, valign="center", halign="center", size=3., segments=1, font="Liberation Mono:style=Bold")) base_plate += translate( (0, -(20 - base_thick / 2), z_thick / 2))(info_text) mount = base_plate + ring + connector if assemble: mount = rotate((0, 180, 0))(mount) return mount