/* * Resources used: * https://www.thingiverse.com/thing:16627 * https://www.chiefdelphi.com/t/timing-pulley-design-tutorial/383204 * * Hardware required: * https://www.banggood.com/15pcs-Transparent-Pulley-Wheel-with-625zz-Double-Bearing-for-V-slot-3D-Printer-p-1575067.html?cur_warehouse=CN&rmmds=search * 2x NEMA17 stepper * 2040 extrusions, lengths see console output * 2020 extrusions, lengths see console output * GT2 belt, lengths see console output */ include ; use ; use ; $fn = 42; /*********************************** ********** Printed Parts ********** ***********************************/ module belt_pulley(tc, dia, for_motor = 1) { difference() { union() { cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2); translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2]) gt2_2mm_pulley(tc, belt_pulley_tooth_width); cylinder(d = dia, h = (belt_pulley_width - belt_pulley_tooth_width) / 2); translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2 + belt_pulley_tooth_width]) cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2); } if (for_motor) { // motor shaft hole translate([0, 0, -1]) cylinder(d = belt_pulley_axis_hole, h = belt_pulley_width + 2); // grub screw for (i = [0, 90]) translate([0, 0, belt_pulley_width / 2]) rotate([90, 0, i]) cylinder(d = belt_pulley_fix_dia, h = dia / 2 + 1); } else { // bearing hole translate([0, 0, -1]) cylinder(d = bearing_outer, h = belt_pulley_width + 2); // grub screw for (i = [0, 90, 180, 270]) translate([0, 0, (i > 90 ? 1 : -1) * 2]) translate([0, 0, belt_pulley_width / 2]) rotate([90, 0, i]) cylinder(d = belt_pulley_fix_dia, h = dia / 2 + 1); } } } module belt_tensioner_diff() { translate([-50, -belt_tensioner_diff_len, -belt_tensioner_diff_height / 2]) cube([100, belt_tensioner_diff_len, belt_tensioner_diff_height]); translate([-belt_tensioner_diff_width / 2, -belt_tensioner_diff_len, -50]) cube([belt_tensioner_diff_width, belt_tensioner_diff_len, 100]); } module belt_tensioner_mount_rail(height) { echo("belt tensioner", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm")); difference() { if (height == 1) { for (i = [ 10, -10 - belt_tensioner_wall ]) translate([i, 0, 0]) cube([belt_tensioner_wall, belt_tensioner_mount_depth, 20 + belt_tensioner_wall]); } else { for (i = [ 10, -10 - belt_tensioner_wall ]) translate([i, 0, -20]) cube([belt_tensioner_wall, belt_tensioner_mount_depth, 40 + belt_tensioner_wall]); } for (i = [ 10, -10 ]) translate([-10 - belt_tensioner_wall - 1, belt_tensioner_mount_depth / 2, i]) rotate([0, 90, 0]) cylinder(d = motor_mount_hole_size, h = 20 + 2 * belt_tensioner_wall + 2); } } module belt_tensioner_mount(height) { echo("belt tensioner", "screw", "1x", str("M", belt_tensioner_screw), str(">", belt_tensioner_diff_len + belt_tensioner_wall + 5 - real_belt_pulley_dia, "mm")); echo("belt tensioner", "nut", "1x", str("M", belt_tensioner_screw)); belt_tensioner_mount_rail(height); difference() { hull() { if (height == 1) { for (i = [ 10, -10 - belt_tensioner_wall ]) translate([i, 0, 0]) cube([belt_tensioner_wall, 1, 20 + belt_tensioner_wall]); } else { for (i = [ 10, -10 - belt_tensioner_wall ]) translate([i, 0, -20]) cube([belt_tensioner_wall, 1, 40 + belt_tensioner_wall]); } translate([-10, -belt_tensioner_diff_len - belt_tensioner_wall - 5, 25 - 21]) cube([20, belt_tensioner_wall, 20 + 1]); } translate([-10 - belt_tensioner_wall - 1, 0, -22]) cube([20 + 2 * belt_tensioner_wall + 2, 50, 50]); translate([-10, 0, -22]) cube([20, 50, 50]); translate([0, 0, 10 + belt_pulley_off]) belt_tensioner_diff(); translate([0, -belt_tensioner_diff_len - belt_tensioner_wall - 5 + 30 - 1, real_belt_pulley_dia / 2 + 0.175]) rotate([90, 0, 0]) cylinder(d = belt_tensioner_screw_hole, h = 30); } } module belt_tensioner_moving() { %color("red") translate([-belt_pulley_width / 2, 0, 0]) rotate([0, 90, 0]) rotate([0, 0, -acos(anim_pos_x * -2 + 1)]) belt_pulley(teethcount, real_belt_pulley_dia, 0); color("cyan") difference() { for (i = [-1, 1]) scale([i, 1, 1]) translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_moving_overlap - belt_tensioner_moving_len, -belt_tensioner_moving_height / 2]) cube([belt_tensioner_wall, belt_tensioner_moving_len, belt_tensioner_moving_height]); translate([-belt_pulley_width / 2 - belt_tensioner_wall - belt_tensioner_moving_gap - 1, 0, 0]) rotate([0, 90, 0]) cylinder(d = axis_hole_diameter, h = belt_pulley_width + 2 * (belt_tensioner_wall + belt_tensioner_moving_gap) + 2); } color("cyan") translate([-belt_pulley_width / 2 - belt_tensioner_moving_gap, -belt_tensioner_moving_len + belt_tensioner_moving_overlap, -belt_tensioner_moving_height / 2]) difference() { cube([belt_pulley_width + 2 * belt_tensioner_moving_gap, belt_tensioner_wall, belt_tensioner_moving_height]); translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_wall + 1, belt_tensioner_moving_height / 2]) rotate([90, 0, 0]) cylinder(d = belt_tensioner_screw_hole, h = belt_tensioner_wall + 2); } } module belt_tensioner(height, length = 100, visual = 1) { if (visual) %translate([-10, 0, 0]) if (length > 0) { if (height == 1) { rail_2020_y(length, "only for visualization"); } else { rail_2040_y(length, "only for visualization"); } } translate([0, -belt_tensioner_travel * $t, 0]) translate([0, -real_belt_pulley_dia / 2, 10 + belt_pulley_off]) belt_tensioner_moving(); color("orange") belt_tensioner_mount(height); %color("yellow") translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 + real_belt_pulley_dia / 2 + belt_pulley_off - belt_thickness / 2]) cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]); %color("yellow") translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 - real_belt_pulley_dia / 2 - belt_thickness / 2 + belt_pulley_off]) cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]); } module motor_mount(height) { echo("motor mount", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm")); echo("motor mount", "screw", "4x", str("M", nema17_hole_size), str(motor_mount_height + 2, "-", motor_mount_height + 4, "mm")); %color("yellow") translate([-nema17_len, 0, nema17_size - belt_pulley_off]) rotate([0, 90, 0]) nema17(nema17_len); %color("red") translate([motor_mount_height - belt_pulley_width / 2 + 10, nema17_size / 2, nema17_size / 2 - belt_pulley_off]) rotate([0, 90, 0]) rotate([0, 0, -acos(anim_pos_x * -2 + 1)]) belt_pulley(teethcount, real_belt_pulley_dia, 1); color("cyan") difference() { hull() { translate([0, 0, -belt_pulley_off]) cube([motor_mount_height, nema17_size, nema17_size]); translate([0, nema17_size, (nema17_size - 20) / 2]) cube([motor_mount_height, motor_mount_length, height * 20]); } translate([0, 0, -belt_pulley_off]) translate([-nema17_len, 0, nema17_size]) rotate([0, 90, 0]) { nema17_holes_face(nema17_len, motor_mount_height + 5, nema17_hole_size + screw_gap); translate([nema17_size / 2, nema17_size / 2, nema17_len - 1]) cylinder(d = nema17_center_size + 2, h = motor_mount_height + 2); } for (i = [0, motor_mount_hole_off]) for (j = [0, 20 * (height - 1)]) translate([0, i, j]) translate([-1, nema17_size - motor_mount_hole_off / 2 + motor_mount_length / 2, nema17_size / 2]) rotate([0, 90, 0]) { cylinder(d = motor_mount_hole_size, h = motor_mount_height + 2); } } } /*********************************** ************** Plate ************** ***********************************/ module plate_holes(h) { for (i = [-1, 1]) for (j = [-1, 1]) translate([i * plate_mount_screws_distance_x / 2, j * plate_mount_screws_distance_y / 2, -1]) cylinder(d = plate_mount_screw_hole, h = h + 2); } module plate() { echo("alu plate", "bed", plate_x, plate_y, "holes", plate_mount_screws_distance_x, plate_mount_screws_distance_y); difference() { cube([plate_x, plate_y, plate_z]); translate([plate_x / 2, plate_y / 2, 0]) plate_holes(plate_z); } } /************************************ ************** Y-Axis ************** ************************************/ module endstop_pcb() { difference() { cube([endstop_pcb_width, endstop_pcb_depth, endstop_pcb_height]); for (i = [0, 1]) translate([endstop_pcb_hole_dist_x, -1, endstop_pcb_height - endstop_pcb_hole_dist_y - i * endstop_pcb_hole_dist]) rotate([-90, 0, 0]) cylinder(d = endstop_pcb_hole, h = endstop_pcb_depth + 2); } translate([0, 0, endstop_pcb_height - endstop_pcb_switchpoint]) rotate([0, -90, 0]) cylinder(d = endstop_pcb_hole, h = endstop_pcb_switchpoint); } module endstop_mount_v1() { %color("yellow") translate([-endstop_pcb_mount_off_w, -endstop_pcb_depth - endstop_pcb_mount_off_d, endstop_pcb_mount_off_h]) endstop_pcb(); color("blue") difference() { cube([endstop_mount_width, endstop_mount_depth, 40]); for (i = [0, 1]) translate([endstop_mount_width / 2, -1, 10 + 20 * i]) rotate([-90, 0, 0]) cylinder(d = motor_mount_hole_size, h = endstop_mount_depth + 2); } color("blue") difference() { union() { hull() { translate([-endstop_mount_slot_length, 0, 40 - endstop_mount_add_height]) cube([endstop_mount_slot_length, endstop_mount_depth, endstop_mount_add_height]); translate([0, 0, endstop_pcb_height - endstop_pcb_hole_dist_y - endstop_pcb_hole_dist]) translate([-endstop_pcb_mount_off_w, -endstop_pcb_mount_off_d, endstop_pcb_mount_off_h - endstop_mount_slot_width / 2]) cube([endstop_mount_slot_length, endstop_mount_slot_depth, endstop_mount_slot_width]); for (i = [0, 1]) translate([0, 0, endstop_pcb_height - endstop_pcb_hole_dist_y - i * endstop_pcb_hole_dist]) translate([-endstop_pcb_mount_off_w, -endstop_pcb_mount_off_d, endstop_pcb_mount_off_h - endstop_mount_slot_width / 2]) cube([endstop_mount_slot_length, endstop_mount_slot_depth, endstop_mount_slot_width]); } } translate([-endstop_pcb_mount_off_w, -endstop_pcb_depth - endstop_pcb_mount_off_d, endstop_pcb_mount_off_h]) for (i = [0, 1]) translate([endstop_pcb_hole_dist_x, -1, endstop_pcb_height - endstop_pcb_hole_dist_y - i * endstop_pcb_hole_dist]) rotate([-90, 0, 0]) { cylinder(d = endstop_pcb_hole, h = endstop_pcb_depth + 20); translate([0, 0, 1 + endstop_pcb_depth + endstop_mount_slot_depth]) cylinder(d = endstop_mount_nut_hole, h = 20, $fn = 6); } } } module endstop_mount_v2() { %color("yellow") translate([-endstop_pcb_mount_off_w, -endstop_pcb_depth - endstop_pcb_mount_off_d, endstop_pcb_mount_off_h]) endstop_pcb(); color("blue") difference() { cube([endstop_mount_width, endstop_mount_depth, 40]); for (i = [0, 1]) translate([endstop_mount_width / 2, -1, 10 + 20 * i]) rotate([-90, 0, 0]) cylinder(d = motor_mount_hole_size, h = endstop_mount_depth + 2); } color("blue") difference() { union() { hull() { translate([-endstop_mount_slot_length, 0, 40 - endstop_mount_add_height]) cube([endstop_mount_slot_length, endstop_mount_depth, endstop_mount_add_height]); translate([0, 0, endstop_pcb_height - endstop_pcb_hole_dist_y - endstop_pcb_hole_dist]) translate([-endstop_pcb_mount_off_w, -endstop_pcb_mount_off_d, endstop_pcb_mount_off_h - endstop_mount_slot_width / 2]) cube([endstop_mount_slot_length, endstop_mount_slot_depth, endstop_mount_slot_width]); } hull() { for (i = [0, 1]) translate([0, 0, endstop_pcb_height - endstop_pcb_hole_dist_y - i * endstop_pcb_hole_dist]) translate([-endstop_pcb_mount_off_w, -endstop_pcb_mount_off_d, endstop_pcb_mount_off_h - endstop_mount_slot_width / 2]) cube([endstop_mount_slot_length, endstop_mount_slot_depth, endstop_mount_slot_width]); } } translate([-endstop_pcb_mount_off_w, -endstop_pcb_depth - endstop_pcb_mount_off_d, endstop_pcb_mount_off_h]) for (i = [0, 1]) translate([endstop_pcb_hole_dist_x, -1, endstop_pcb_height - endstop_pcb_hole_dist_y - i * endstop_pcb_hole_dist]) rotate([-90, 0, 0]) { cylinder(d = endstop_pcb_hole, h = endstop_pcb_depth + 20); translate([0, 0, 1 + endstop_pcb_depth + endstop_mount_slot_depth]) cylinder(d = endstop_mount_nut_hole, h = 20, $fn = 6); } } } module endstop_mount() { if (use_endstop_mount_v2) { endstop_mount_v2(); } else { endstop_mount_v1(); } } module belt_mount(h) { difference() { hull() { translate([-belt_mount_width / 2, -belt_mount_depth / 2, 0]) cube([belt_mount_width, belt_mount_depth, h]); translate([-belt_mount_full_width / 2, belt_mount_depth / 2, 0]) cube([belt_mount_full_width, 1, h]); } translate([-belt_slot_width / 2, -belt_slot_depth / 2, -1]) cube([belt_slot_width, belt_slot_depth, h + 2]); translate([-belt_mount_full_width / 2, -belt_mount_depth / 2 - 0.1, h / 2]) rotate([-90, 0, 0]) prism(belt_mount_full_width, h / 2 + 0.1, belt_mount_depth + 0.1); } } module eccentric() { translate([0, 0, eccentric_height_add]) { cylinder(d = eccentric_dia_main, h = eccentric_height_main); translate([0, 0, -eccentric_height_inset]) cylinder(d = eccentric_dia_inset, h = eccentric_height_inset); } } module y_carriage_post() { rotate([0, 0, 90]) difference() { cylinder(d = y_carriage_post_dia, h = y_carriage_post_len, $fn = 6); translate([0, 0, -1]) cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1); translate([y_carriage_post_hole_off, 0, (y_carriage_post_len + y_carriage_post_center) / 2]) cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1); } } module y_carriage_posts() { for (i = [-1, 1]) for (j = [-1, 1]) translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, 0]) { if (use_custom_eccentric) { color("yellow") eccentric(); %color("yellow") translate([0, eccentric_hole_off, y_carriage_pulley_off]) rail_wheel(); } else { color("blue") y_carriage_post(); %color("yellow") translate([0, y_carriage_post_hole_off, y_carriage_pulley_off]) rail_wheel(); } } } module carriage_spacer() { difference() { cube([y_carriage_x, y_carriage_y, carriage_spacer_height]); translate([y_carriage_x / 2, y_carriage_y / 2, 0]) plate_holes(carriage_spacer_height); translate([carriage_spacer_cut_x / 2 * sqrt(2) + y_carriage_x / 2, -1, -1]) rotate([0, -90, 45]) prism(carriage_spacer_height + 2, carriage_spacer_cut_x, carriage_spacer_cut_x); translate([-carriage_spacer_cut_x / 2 * sqrt(2) + y_carriage_x / 2, y_carriage_y + 1, -1]) rotate([0, -90, 225]) prism(carriage_spacer_height + 2, carriage_spacer_cut_x, carriage_spacer_cut_x); translate([-1, y_carriage_y / 2 - carriage_spacer_cut_y / 2 * sqrt(2), -1]) rotate([0, -90, -45]) prism(carriage_spacer_height + 2, carriage_spacer_cut_y, carriage_spacer_cut_y); translate([y_carriage_x + 1, y_carriage_y / 2 + carriage_spacer_cut_y / 2 * sqrt(2), -1]) rotate([0, -90, -225]) prism(carriage_spacer_height + 2, carriage_spacer_cut_y, carriage_spacer_cut_y); } } // also used as base for x-carriage // axis = 0 --> all holes, usable for both // axis = 1 --> holes for x-carriage // axis = 2 --> holes for y-carriage module y_carriage(axis = 0) { if (axis == 1) { echo("t-nut", "x-carriage", "2"); } if (use_custom_eccentric) { echo("eccentric", "carriage", "4"); echo("screw", "carriage", "M5x30", "4"); echo("nut", "carriage", "M5", "4"); } color("green") difference() { union() { cube([y_carriage_x, y_carriage_y, y_carriage_h]); translate([y_carriage_x / 2, y_carriage_y / 2, 0]) for (i = [-1, 1]) translate([0, i * (y_carriage_y + belt_mount_depth) / 2, 0]) scale([1, -i, 1]) belt_mount(y_carriage_h); // additional "meat" for eccentric inset translate([y_carriage_x / 2, y_carriage_y / 2, y_carriage_h]) for (i = [-1, 1]) for (j = [-1, 1]) translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, 0]) if (use_custom_eccentric) cylinder(d = eccentric_inset_wall, h = eccentric_height_add); } translate([y_carriage_x / 2, y_carriage_y / 2, 0]) plate_holes(y_carriage_h); // holes to mount y-axis to x-carriage if ((axis == 0) || (axis == 1)) { translate([(y_carriage_x - plate_mount_screws_distance_x) / 2, 0, 0]) for (i = [0, 1]) translate([i * plate_mount_screws_distance_x, y_carriage_y / 2, -1]) cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2); for (i = [x_carriage_holder_l - x_carriage_holder_hole_off, y_carriage_y - x_carriage_holder_l + x_carriage_holder_hole_off]) translate([y_carriage_x / 2, i, -1]) cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2); } // holes for wheel posts translate([y_carriage_x / 2, y_carriage_y / 2, 0]) for (i = [-1, 1]) for (j = [-1, 1]) translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, -1]) if (use_custom_eccentric) { cylinder(d = eccentric_screw_hole, h = y_carriage_h + 2); translate([0, 0, y_carriage_h + eccentric_height_add + 1 - eccentric_inset_hole]) cylinder(d = eccentric_dia_inset, h = eccentric_inset_hole + 1); cylinder(d = eccentric_screw_hole_dia, h = eccentric_screw_hole_h + 1); } else { cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2); } } %translate([y_carriage_x / 2, y_carriage_y / 2, y_carriage_h]) y_carriage_posts(); } module y_axis() { translate([y_carriage_x / 2, y_axis_animation_position, 20 + y_carriage_h + y_carriage_rail_dist]) rotate([0, 180, 0]) { y_carriage(2); color("cyan") translate([0, 0, -carriage_spacer_height - 0.01]) carriage_spacer(); } color("grey") translate([-10, 0, 0]) rail_2040_y(y_axis_rail_len, "y-axis"); translate([- motor_mount_height - 10, y_axis_rail_len + nema17_size, nema17_size / 2 + 10]) rotate([180, 0, 0]) motor_mount(2); translate([10 + endstop_mount_depth, y_axis_rail_len - endstop_mount_width, -20]) rotate([0, 0, 90]) endstop_mount(); belt_tensioner(2, y_axis_rail_len, 0); } /************************************ ************** X-Axis ************** ************************************/ module x_carriage_holder() { echo("t-nut", "x-carriage-holder", "2"); difference() { union() { cube([x_carriage_holder_l, x_carriage_holder_w, x_carriage_holder_h]); cube([x_carriage_holder_h, x_carriage_holder_w, 20]); } translate([0, (x_carriage_holder_w - x_carriage_holder_rail_hole_dist) / 2, 0]) for (i = [0, x_carriage_holder_rail_hole_dist]) translate([-1, i, 10]) rotate([0, 90, 0]) cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2); translate([-(y_carriage_y - plate_mount_screws_distance_y) / 2, y_carriage_x / 2, 0]) rotate([0, 0, 90]) plate_holes(x_carriage_holder_h); translate([x_carriage_holder_hole_off, x_carriage_holder_w / 2, -1]) cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2); } } module x_carriage() { translate([0, -y_carriage_x / 2, y_carriage_h + y_carriage_rail_dist + 20]) rotate([0, 180, -90]) y_carriage(1); /* color("purple") for (i = [-1, 1]) translate([y_carriage_y / 2, 0, 0]) scale([i, 1, 1]) translate([y_carriage_y / 2 - x_carriage_holder_l, 0, 0]) translate([0, -x_carriage_holder_w / 2, 20 + y_carriage_h + y_carriage_rail_dist]) x_carriage_holder(); */ } module x_axis() { translate([x_axis_animation_position + 10, 0, 0]) x_carriage(); color("grey") translate([0, -10, 0]) rail_2040_x(x_axis_rail_len, "x-axis"); translate([x_axis_rail_len + nema17_size, motor_mount_height + 10, nema17_size / 2 + 10]) rotate([0, 180, 90]) motor_mount(2); translate([x_axis_rail_len - endstop_mount_width, -10 - endstop_mount_depth, -20]) endstop_mount(); rotate([0, 0, -90]) belt_tensioner(2, x_axis_rail_len, 0); } /************************************ ************* Assembly ************* ************************************/ module assembly_y_axis_plate() { translate([0, -y_carriage_y / 2 - y_axis_animation_position, 0]) y_axis(); %translate([-plate_x / 2, -plate_y / 2, 20 + y_carriage_h + y_carriage_rail_dist + carriage_spacer_height]) plate(); } module assembly_x_axis() { x_axis(); translate([x_axis_animation_position + y_carriage_y / 2, -y_axis_rail_len / 2, 20 + y_carriage_h + y_carriage_rail_dist]) translate([10, y_axis_animation_position + y_carriage_y / 2, 20]) assembly_y_axis_plate(); } module rail_foot() { difference() { union() { sphere(d = foot_dia); translate([0, 0, foot_dia / 2]) sphere(d = foot_nut_base_dia); } translate([-foot_dia / 2 - 1, -foot_dia / 2 - 1, -foot_dia / 2 - 1]) cube([foot_dia + 2, foot_dia + 2, foot_dia / 2 + 1]); translate([-foot_nut_base_dia / 2 - 1, -foot_nut_base_dia / 2 - 1, foot_dia / 2]) cube([foot_nut_base_dia + 2, foot_nut_base_dia + 2, foot_nut_base_dia / 2 + 1]); translate([0, 0, -1]) cylinder(d = foot_screw_dia, h = foot_dia / 2 + 2); translate([0, 0, -1]) cylinder(d = foot_screw_head_dia, h = foot_screw_head_height + 1); } } module assembly() { translate([-x_axis_rail_len / 2, 0, 20]) { assembly_x_axis(); if (use_double_supports) { color("grey") for (i = [1, -1]) scale([1, i, 1]) translate([left_support_off, -left_support_len - 10, -20]) rail_2020_y(left_support_len, "left support"); color("grey") for (i = [1, -1]) scale([1, i, 1]) translate([x_axis_rail_len - 20 - right_support_off, -right_support_len - 10, -20]) rail_2020_y(right_support_len, "right support"); for (i = [0, 1]) for (j = [1, -1]) translate([i * x_axis_rail_len - (i * 2 - 1) * (right_support_off + 10), j * (right_support_len - 10), -40 - 0]) { %color("grey") cylinder(d = 5.0, h = 25); %color("green") rail_foot(); } } else { color("grey") translate([x_axis_rail_len / 2, 0, -40]) for (i = [1, -1]) scale([i, 1, 1]) translate([x_axis_rail_len / 2 - bottom_support_off, -bottom_support_len / 2, 0]) rail_2020_y(bottom_support_len, "bottom supports"); for (i = [0, 1]) for (j = [1, -1]) translate([i * x_axis_rail_len - (i * 2 - 1) * (bottom_support_off - 10), j * (bottom_support_len / 2 - 40), -40 - 20]) { %color("grey") cylinder(d = 5.0, h = 25); %color("green") rail_foot(); } } } } module xy_table() { translate([-point_that_reaches_everywhere_x, -point_that_reaches_everywhere_y, -40 + -40 + (y_carriage_rail_dist + y_carriage_h) * -2 + -plate_z - carriage_spacer_height]) assembly(); } /*********************************** ************ Rendering ************ ***********************************/ //dispenser(); //rail_2020_x(100); //rail_wheel(); //rail_foot(); //motor_mount(1); //motor_mount(2); //belt_pulley(teethcount, real_belt_pulley_dia, 1); //belt_tensioner_mount(2); //belt_tensioner_moving(); //belt_tensioner(1); //belt_tensioner(2); //belt_pulley(teethcount, real_belt_pulley_dia, 0); //y_carriage_post(); //x_carriage_holder(); //translate([0, -50, 0]) //y_carriage(0); //y_carriage(1); //y_carriage(2); //x_carriage(); //carriage_spacer(); //y_axis(); //x_axis(); //assembly(); xy_table();