include include include include frame_size = 20; wall_thickness = 2; corner_size = 30; // The length along each edge that the corner bracket takes. I.e., if // you construct a frame of four corner brackets and 4 tubes of length // $L-$corner_size, the distance between opposite tubes' centerlines // will be $L. corner_offset = frame_size / 2 + wall_thickness; rail_diam = 8; // distance between centerline of rail and centerline of frame Y tube. yrail_offset = (frame_size + corner_size) / 2; ysled_extralen = frame_size; // on each end // Both of these are distance from frame centerline belt_height1 = frame_size / 2 + wall_thickness + belt_width / 2 + 2; belt_height2 = belt_height1 + belt_width + 2; // calculated ysled_rail_spacing = (sled_ysize); motor_shaft_xoffset = (corner_size - wall_thickness) / 2; motor_mount_length_adjustment = 4; motor_mount_length = nema17_face + wall_thickness + motor_mount_length_adjustment; // Generates bar of length $l, centered on origin extending in +Z module tslot(l) { bom_item(printable = false, label = str("tslot(", l, "mm)")); colorize(stock_color) { translate([ -frame_size / 2, -frame_size / 2, 0 ]) cube([ frame_size, frame_size, l ]); } } // A corner, with tubes extending in +x and +y. module corner_base() { odim = frame_size / 2 + wall_thickness; ldim = frame_size / 2 + corner_size; cap_points = [ [ -odim, -odim ], [ -odim, ldim ], [ odim, ldim ], [odim, odim], [ ldim, odim ], [ ldim, -odim ] ]; difference() { translate([ 0, 0, -odim ]) linear_extrude(odim * 2) polygon(points = cap_points); // two bars... translate([ -frame_size / 2, corner_offset, -frame_size / 2 ]) cube([ frame_size, ldim, frame_size ]); translate([ corner_offset, -frame_size / 2, -frame_size / 2 ]) cube([ ldim, frame_size, frame_size ]); translate([ corner_offset, corner_offset, -frame_size / 2 ]) cube([ ldim, ldim, frame_size ]); // translate([-odim - 1, -odim - 1, 0]) // cube(ldim*2); } } module rail_holder(in_x) { odim = frame_size / 2 + wall_thickness; ldim = frame_size / 2 + corner_size; tube_offset = (corner_size) / 2 + wall_thickness; tube_rotation = in_x ? 90 : 0; translated_rail_offset = yrail_offset - frame_size / 2 - wall_thickness; translate([ frame_size / 2 + wall_thickness, frame_size / 2 + wall_thickness, -frame_size / 2 - wall_thickness ]) { difference() { cube([ !in_x ? corner_size - wall_thickness : 10, !in_x ? 10 : corner_size - wall_thickness, wall_thickness * 2 + frame_size ]); translate( [ translated_rail_offset, translated_rail_offset, frame_size / 2 + wall_thickness ]) rotate([ tube_rotation - 90, tube_rotation, 0 ]) translate([ 0, 0, -corner_size ]) cylinder(d = rail_diam, corner_size * 4); } } } // centered on the rail. module ysled_slider(spread, associated_parts = $preview, is_left=true) { bom_item(label = str("ysled_slider(", spread, ")")); sled_len = spread + frame_size; sled_height = frame_size; idler_spacing = spread / 3; colorize("green") render() translate([ 0, -sled_len / 2, 0 ]) rotate([ -90, 0, 0 ]) { difference() { union() { translate([ -frame_size / 2, -frame_size / 2, 0 ]) cube([ frame_size + 5, frame_size, sled_len ]); translate([ pulley_sbend_offset - yrail_offset + motor_shaft_xoffset - pulley_clearance_rad - 4, -frame_size / 2, 0 ]) cube([ frame_size + 5, frame_size, sled_len ]); } cylinder(d = bushing_id * 1.1, h = sled_len); translate([ 0, 0, -1 ]) cylinder(d = bushing_od, h = bushing_len + 1); translate([ 0, 0, sled_len - bushing_len ]) cylinder(d = bushing_od, h = bushing_len + 1); for (zpos = [ frame_size / 2, sled_len - frame_size / 2 ]) { translate([ sled_height / 2, 0, zpos ]) rotate([ 0, 90, 0 ]) { cylinder(h = sled_height + 1, d = rail_diam); } } } } // TODO: add posts for the idlers // color("#f00") translate( [ pulley_sbend_offset - yrail_offset + motor_shaft_xoffset, 0, frame_size/2 ]) { translate([ 0, idler_spacing / 2, 0 ]) { idler_post(belt_height = belt_height1 - frame_size/2, toothed = is_left); } translate([ 0, -idler_spacing / 2, 0 ]) { *cylinder(d = 3, h = 30, $fs = 1); *idler(belt_height2); rotate([ 0, 0, -90 ]) { idler_post(belt_height = belt_height2 - frame_size/2, toothed = !is_left); } } } translate([ 0, -sled_len / 2, 0 ]) rotate([ -90, 0, 0 ]) if (associated_parts) { bushing(); translate([ 0, 0, sled_len - bushing_len ]) bushing(); } } module nema17_housing() { hwidth = corner_size + frame_size + wall_thickness; hheight = nema17_face + wall_thickness * 2; hdepth = frame_size + wall_thickness * 2; screw_dxy = 31 / 2; translate([ 0, -nema17_face / 2 - frame_size / 2 - wall_thickness, 0 ]) slotify([0, -motor_mount_length_adjustment, 0]) { translate([ 0, 0, -2 ]) cube([ nema17_face + 1, nema17_face + 1, hdepth ], center = true); cylinder(d = 23, frame_size); translate([ -screw_dxy, -screw_dxy, frame_size / 2 + wall_thickness ]) rotate([ 180, 0, 0 ]) { cylinder(d = 5, h = 3); } translate([ screw_dxy, -screw_dxy, frame_size / 2 + wall_thickness ]) rotate([ 180, 0, 0 ]) { cylinder(d = 5, h = 3); } translate([ -screw_dxy, screw_dxy, frame_size / 2 + wall_thickness ]) rotate([ 180, 0, 0 ]) { cylinder(d = 5, h = 3); } translate([ screw_dxy, screw_dxy, frame_size / 2 + wall_thickness ]) rotate([ 180, 0, 0 ]) { cylinder(d = 5, h = 3); } } } // belt height is the center of the belt. // Roration is in Z axis, from +x/+y module idler_post(belt_height, toothed = true) { gap = 0.5; post_radius = pulley_clearance_rad + 4; top_shelf_thickness = 4; total_height = idler_zmargin.y + belt_height + top_shelf_thickness + gap; slot_radius = pulley_clearance_rad; slot_height = idler_zmargin.x + idler_zmargin.y + gap * 2; difference() { union() { // outer shell cylinder(h = total_height, r = post_radius); translate([ 0, -post_radius, 0 ]) cube([ post_radius, post_radius, total_height ]); translate([ -post_radius, 0, 0 ]) cube([ post_radius, post_radius, total_height ]); } translate([ 0, 0, belt_height - idler_zmargin.x - gap ]) { cylinder(r = slot_radius, slot_height); translate([ -slot_radius, 0, 0 ]) cube([ post_radius * 2, post_radius * 2, slot_height ]); translate([ 0, -slot_radius, 0 ]) cube([ post_radius * 2, post_radius * 2, slot_height ]); } cylinder(d = 3, h = total_height + 1, $fn = 60); translate([ 0, 0, total_height - 2 ]) cylinder(r = 3, h = 3); } idler(height = belt_height, toothed=toothed); } module flcorner() { bom_item(); render() { rotate([ 0, 0, 0 ]) { corner_base(); rail_holder(false); } difference() { translate([ -frame_size/2 - wall_thickness, -frame_size/2 - wall_thickness - motor_mount_length, -frame_size/2 - wall_thickness ]) cube([ frame_size + wall_thickness + corner_size, motor_mount_length, frame_size + wall_thickness * 2 ]); translate([ motor_shaft_xoffset, 0, 0 ]) nema17_housing(); } // translate([motor_shaft_xoffset, 0, 0 ]) nema17_housing(); } if ($preview) translate([ motor_shaft_xoffset, -nema17_face / 2 - frame_size / 2 - wall_thickness, frame_size / 2 ]) { nema17(); translate([ 0, 0, -frame_size / 2 + belt_height2 ]) { active_pulley(); } } } module frcorner() { bom_item(); render() { rotate([ 0, 0, 90 ]) { corner_base(); rail_holder(true); } difference() { translate([ -frame_size/2 - corner_size, -frame_size/2 - wall_thickness - motor_mount_length, -frame_size/2 - wall_thickness ]) cube([ frame_size + wall_thickness + corner_size, motor_mount_length, frame_size + wall_thickness * 2 ]); translate([ -motor_shaft_xoffset, 0, 0 ]) nema17_housing(); } } if ($preview) translate([ -motor_shaft_xoffset, -nema17_face / 2 - frame_size / 2 - wall_thickness, frame_size / 2 ]) { nema17(); translate([ 0, 0, belt_height1 - frame_size / 2 ]) { rotate([ 180, 0, 0 ]) active_pulley(); } } } module blcorner() { bom_item(); render() rotate([ 0, 0, 270 ]) { corner_base(); rail_holder(true); } translate([motor_shaft_xoffset + pulley_sbend_offset, 0, 0]) rotate([0,0,-90]) idler_post(belt_height = belt_height1, toothed=true); translate([0, -(motor_shaft_xoffset + pulley_sbend_offset), 0]) rotate([0,0,-90]) idler_post(belt_height = belt_height2, toothed=true); } module brcorner() { bom_item(); render() rotate([ 0, 0, 180 ]) { corner_base(); rail_holder(false); } translate([-(motor_shaft_xoffset + pulley_sbend_offset), 0, 0]) rotate([0,0,180]) idler_post(belt_height = belt_height2, toothed=true); translate([0, -(motor_shaft_xoffset + pulley_sbend_offset), 0]) rotate([0,0,180]) idler_post(belt_height = belt_height1, toothed=true); } module xsled_slider() { slider_len = bushing_len + 10; screw_tab_len = 20; screw_tab_thickness = 10; render() // translate([screw_tab_len, 0, 0]) difference() { union() { rotate([ 0, 90, 0 ]) { cylinder(d = frame_size, h = slider_len); } translate([ 0, -frame_size / 2, 0 ]) cube([ slider_len, frame_size, frame_size / 2 ]); *translate([ -screw_tab_len, -frame_size / 2, frame_size / 2 ]) cube( [ screw_tab_len * 2 + slider_len, frame_size, screw_tab_thickness ]); } rotate([ 0, 90, 0 ]) { cylinder(d = bushing_od, h = bushing_len); cylinder(d = rail_diam * 1.1, slider_len * 2); } } if ($preview) rotate([ 0, 90, 0 ]) bushing(); } module sled_cornera() { bom_item(); corner_base(); translate([ -frame_size / 2 - wall_thickness, 0, -frame_size ]) xsled_slider(); } module sled_cornerb() { bom_item(); corner_base(); rotate([ 0, 0, 90 ]) translate([ -frame_size / 2 - wall_thickness, 0, -frame_size ]) xsled_slider(); } module xsled_frame() { translate([ -sled_xsize / 2 + corner_offset, -ysled_rail_spacing / 2, 0 ]) rotate([ 0, 90, 0 ]) tslot(sled_xsize - corner_offset * 2); translate([ -sled_xsize / 2 + corner_offset, ysled_rail_spacing / 2, 0 ]) rotate([ 0, 90, 0 ]) tslot(sled_xsize - corner_offset * 2); translate([ -sled_xsize / 2, -ysled_rail_spacing / 2 + corner_offset, 0 ]) rotate([ -90, 0, 0 ]) tslot(sled_ysize - corner_offset * 2); translate([ sled_xsize / 2, -ysled_rail_spacing / 2 + corner_offset, 0 ]) rotate([ -90, 0, 0 ]) tslot(sled_ysize - corner_offset * 2); translate([ -sled_xsize / 2, -sled_ysize / 2, 0 ]) sled_cornera(); translate([ sled_xsize / 2, sled_ysize / 2, 0 ]) rotate([ 0, 0, 180 ]) sled_cornera(); translate([ sled_xsize / 2, -sled_ysize / 2, 0 ]) rotate([ 0, 0, 90 ]) sled_cornerb(); translate([ -sled_xsize / 2, sled_ysize / 2, 0 ]) rotate([ 0, 0, 270 ]) sled_cornerb(); // simulate a piece of film if (false) { color("#0008") cube([ 5 * inch, 4 * inch, 1 ], center = true); } } module xsled2() { bom_item(); tab_len = bushing_len * 2; tab_thickness = bushing_od + wall_thickness * 2; glass_thickness = 3; // TODO: Update when an actual size is available inner_ysize = sled_ysize - tab_thickness; film_height = belt_height2 + belt_width / 2; ledge_width = 15; inside_ledge_width = 8; outside_ledge_width = ledge_width - inside_ledge_width; film_thickness = 0.25; finger_notch_diam = 25; finger_notch_smdepth = 2; glass_holder_points = [ [0, -tab_thickness/2], [0, film_height + glass_thickness], [wall_thickness, film_height + glass_thickness], [wall_thickness, film_height], [outside_ledge_width, film_height], [outside_ledge_width, film_height - glass_thickness], [ledge_width, film_height - glass_thickness], [wall_thickness * 2, -tab_thickness / 2] ]; echo("Ledge width: ", ledge_width - outside_ledge_width); for (xsign = [ 1, -1 ], ysign = [ 1, -1 ]) { translate([ sled_xsize / 2 * xsign, sled_ysize / 2 * ysign, 0 ]) rotate([ 0, -90 * xsign, 0 ]) { difference() { union() { cylinder(d = tab_thickness, h = tab_len); translate( [ -tab_thickness / 2, ysign > 0 ? -tab_thickness / 2 : 0, 0 ]) cube([ tab_thickness, tab_thickness / 2, tab_len ]); } translate([ 0, 0, -0.5 ]) { cylinder(d = bushing_od, h = bushing_len + 0.5); cylinder(d = rail_diam * 1.1, h = tab_len + 1); } } if ($preview) { bushing(); } } // cube([sled_xsize, inner_ysize, tab_thickness/2], center=true); difference() { union() { translate([ -sled_xsize / 2, -inner_ysize / 2, 0]) rotate([ 0, 90, 0 ]) rotate([ 0, 0, 90 ]) linear_extrude(sled_xsize) polygon(glass_holder_points); translate([ sled_xsize / 2, inner_ysize / 2, 0 ]) rotate([ 0, 90, 180 ]) rotate([ 0, 0, 90 ]) linear_extrude(sled_xsize) polygon(glass_holder_points); translate([ sled_xsize / 2, -inner_ysize / 2, 0 ]) rotate([ 0, 90, 90 ]) rotate([ 0, 0, 90 ]) linear_extrude(inner_ysize) polygon(glass_holder_points); translate([ -sled_xsize / 2, inner_ysize / 2, 0 ]) rotate([ 0, 90, -90 ]) rotate([ 0, 0, 90 ]) linear_extrude(inner_ysize) polygon(glass_holder_points); } for (x = [ -1, 1], y = [ -1, 1]) { translate([x * (sled_xsize/2 - outside_ledge_width - inside_ledge_width / 2), y * (inner_ysize/2 - outside_ledge_width - inside_ledge_width / 2), film_height]) rotate([180,0,0]) { cylinder(d=4, h = 50); cylinder(d=5, h = 4 + glass_thickness ); } } translate([ -10, -inner_ysize / 2, film_height - glass_thickness + 0.5 - finger_notch_smdepth + finger_notch_diam / 2 ]) rotate([90, 0, 0]) cylinder(d=finger_notch_diam, h = ledge_width * 3, center=true); } } color("#fff3") if ($preview) { // draw glass sheets translate( [ 0, 0, film_height - glass_thickness / 2 + 0.5 ]) cube( [ sled_xsize - outside_ledge_width * 2, inner_ysize - outside_ledge_width * 2, glass_thickness ], center = true); *translate( [ 0, 0, film_height + film_thickness * 2 + glass_thickness / 2 + 0.5 ]) cube( [ sled_xsize - wall_thickness * 2, inner_ysize - wall_thickness * 2, glass_thickness ], center = true); } if($preview) { color("#0003") translate([0, 0, film_height + 0.5]) { cube([5*inch, 4*inch, film_thickness], center=true); } } } // render() // xsled2();