// ####################################################### // ################## Config Parameters ################## // ####################################################### slot = 30; // or 20 slot_off = 1; // distance between adjacent slots // print area / volume heatbed_width = 400; heatbed_length = 400; heatbed_height = 6; // distance between heatbed edge and inner t-slot frame edge frame_off_x = 20; frame_off_y = 20; outer_width = heatbed_width + (2 * (slot + frame_off_x)); outer_length = heatbed_length + (2 * (slot + frame_off_y)); // TODO depend on print area height outer_height = 500; rail_mount_dist = 12; y_carriage_pos = 175; x_carriage_pos = 180; // distance between heatbed and z-carriage frame bed_x_off = 20; bed_y_off = 20; bed_z_dist = 30; // display heatbed centered in print volume bed_draw_height = (outer_height - heatbed_height) / 2; echo(print_x=heatbed_width, print_y=heatbed_length); echo(frame_x=outer_width, frame_y=outer_length, frame_z=outer_height); // ####################################################### // ###################### Libraries ###################### // ####################################################### include include include include include include include module gt2_belt(length) { difference() { belting("straight", "GT2_2mm", belt_length = length); translate([-5, -5, 6]) cube([length + 10, 10, 10]); } } // ####################################################### // ######################## Frame ######################## // ####################################################### module slot_angle_connector() { color("gray") translate([slot, 0, 0]) rotate([0, -90, 0]) difference() { cube([slot, slot, slot]); translate([0, -5, 0]) rotate([0, 45, 0]) cube([2 * slot, 2 * slot, 2 * slot]); } } module foot() { color("yellow") translate([0, 0, 10]) cylinder(d = 6, h = 20); color("yellow") difference() { sphere(d = 20); translate([-15, -15, -30]) cube([30, 30, 30]); } } module lower_frame(double) { // bottom frame translate([slot + slot_off, 0, 0]) tslot_x(slot, outer_width - (2 * (slot + slot_off))); if (double) { translate([slot + slot_off, outer_length - slot, slot]) rotate([-90, 0, 0]) tslot_2_x(slot, outer_width - (2 * (slot + slot_off))); translate([0, slot + slot_off, 0]) tslot_2_y(slot, outer_length - (2 * (slot + slot_off))); translate([outer_width - slot, slot + slot_off, 0]) tslot_2_y(slot, outer_length - (2 * (slot + slot_off))); } else { translate([slot + slot_off, outer_length - slot, 0]) tslot_x(slot, outer_width - (2 * (slot + slot_off))); translate([0, slot + slot_off, 0]) tslot_y(slot, outer_length - (2 * (slot + slot_off))); translate([outer_width - slot, slot + slot_off, 0]) tslot_y(slot, outer_length - (2 * (slot + slot_off))); } } module frame() { // outer corner pillars tslot_z(slot, outer_height); translate([outer_width - slot, 0, 0]) tslot_z(slot, outer_height); translate([0, outer_length - slot, 0]) tslot_z(slot, outer_height); translate([outer_width - slot, outer_length - slot, 0]) tslot_z(slot, outer_height); lower_frame(false); // top frame translate([0, 0, outer_height - slot]) lower_frame(true); // end caps color("black") translate([0, 0, outer_height]) { cube([slot, slot, 2]); translate([outer_width - slot, 0, 0]) cube([slot, slot, 2]); translate([0, outer_length - slot, 0]) cube([slot, slot, 2]); translate([outer_width - slot, outer_length - slot, 0]) cube([slot, slot, 2]); } // feet translate([slot / 2, slot / 2, -30]) foot(); translate([outer_width - slot / 2, slot / 2, -30]) foot(); translate([slot / 2, outer_length - slot / 2, -30]) foot(); translate([outer_width - slot / 2, outer_length - slot / 2, -30]) foot(); // connecting elements translate([slot + slot_off, 0, slot + slot_off]) slot_angle_connector(); translate([slot + slot_off, outer_length - slot, slot + slot_off]) slot_angle_connector(); translate([slot + slot_off, 0, outer_height - slot - slot_off]) rotate([0, 90, 0]) slot_angle_connector(); translate([slot + slot_off, outer_length - slot, outer_height - slot - slot_off - slot]) rotate([0, 90, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, 0, slot + slot_off]) rotate([0, -90, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, outer_length - slot, slot + slot_off]) rotate([0, -90, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, 0, outer_height - slot - slot_off]) rotate([0, 180, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, outer_length - slot, outer_height - slot - slot_off - slot]) rotate([0, 180, 0]) slot_angle_connector(); translate([slot, slot + slot_off, slot + slot_off]) rotate([0, 0, 90]) slot_angle_connector(); translate([slot, slot + slot_off, outer_height - slot - slot_off - slot]) rotate([0, 90, 90]) slot_angle_connector(); translate([0, outer_length - slot - slot_off, slot + slot_off]) rotate([0, 0, -90]) slot_angle_connector(); translate([0, outer_length - slot - slot_off, outer_height - slot - slot_off - slot]) rotate([0, 90, -90]) slot_angle_connector(); translate([outer_width, slot + slot_off, slot + slot_off]) rotate([0, 0, 90]) slot_angle_connector(); translate([outer_width, slot + slot_off, outer_height - slot - slot_off - slot]) rotate([0, 90, 90]) slot_angle_connector(); translate([outer_width - slot, outer_length - slot - slot_off, slot + slot_off]) rotate([0, 0, -90]) slot_angle_connector(); translate([outer_width - slot, outer_length - slot - slot_off, outer_height - slot - slot_off - slot]) rotate([0, 90, -90]) slot_angle_connector(); translate([slot + slot_off, slot + slot_off, slot]) rotate([-90, 0, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, slot + slot_off, slot]) rotate([-90, 0, 90]) slot_angle_connector(); translate([slot + slot_off, outer_length - slot - slot_off, 0]) rotate([90, 0, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, outer_length - slot - slot_off, 0]) rotate([90, 0, -90]) slot_angle_connector(); /* translate([slot + slot_off, slot + slot_off, outer_height]) rotate([-90, 0, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, slot + slot_off, outer_height]) rotate([-90, 0, 90]) slot_angle_connector(); translate([slot + slot_off, outer_length - slot - slot_off, outer_height - slot]) rotate([90, 0, 0]) slot_angle_connector(); translate([outer_width - slot - slot_off, outer_length - slot - slot_off, outer_height - slot]) rotate([90, 0, -90]) slot_angle_connector(); */ } // ####################################################### // ###################### Mechanics ###################### // ####################################################### module rail(length) { cylinder(d = rail_dia, h = length); echo(rail_dia=rail_dia, rail_len=length); } module y_rails() { // y smooth rail on blue side color("cyan") translate([rail_dia / 2 + rail_y_off_1, 18, -30]) rotate([-90, 0, 0]) rail(outer_length - slot - nema17_size - (2 * rail_mount_dist)); // y carriage on blue side translate([rail_y_off_1 - (lm8uu_outer + lm8uu_dia_add) / 2 + y_carriage_rail_support, y_carriage_pos, -slot]) y_carriage(idler_a_blue, idler_b_blue); // rail mounts for blue side color("green") translate([0, 2 * rail_mount_dist, -2 * slot]) rail_mount(slot); color("green") translate([0, outer_length - (2 * slot) - nema17_size - rail_mount_dist + 5, -2 * slot]) rail_mount(slot); // y smooth rail on red side color("cyan") translate([outer_width - (2 * slot) - rail_dia / 2 - rail_y_off_1, 18, -30]) rotate([-90, 0, 0]) rail(outer_length - slot - nema17_size - (2 * rail_mount_dist)); // y carriage on red side translate([outer_width - slot - y_carriage_width - y_carriage_block_width, y_carriage_pos + y_carriage_length, -slot]) rotate([0, 0, 180]) y_carriage(idler_a_red, idler_b_red); // rail mounts for red side color("green") translate([outer_width - (2 * slot), 2 * rail_mount_dist + rail_mount_len, -2 * slot]) rotate([0, 0, 180]) rail_mount(slot); color("green") translate([outer_width - (2 * slot), outer_length - (2 * slot) - nema17_size - rail_mount_dist + 5 + rail_mount_len, -2 * slot]) rotate([0, 0, 180]) rail_mount(slot); } module x_rails() { // TODO length calculate properly! color("cyan") translate([30, y_carriage_pos, 15]) rotate([0, 90, 0]) rail(outer_width - (4 * slot)); color("cyan") translate([30, y_carriage_pos + x_rail_dist, 15]) rotate([0, 90, 0]) rail(outer_width - (4 * slot)); translate([x_carriage_pos, y_carriage_pos - x_carriage_len_add, slot / 2]) x_carriage(); } module motion_xy() { translate([slot, slot, outer_height]) y_rails(); translate([slot, slot + y_carriage_len_add, outer_height - (1.5 * slot)]) x_rails(); // left ("blue") motor translate([slot, outer_length - slot - nema17_size - nema17_mount_wall, outer_height + nema17_mount_wall]) rotate([180, 0, 90]) { color("blue") translate([0, 0, -65]) nema17(65); color("green") nema17_mount(slot); // blue motor pulley color("magenta") translate([nema17_size / 2, nema17_size / 2, 22.4]) rotate([180, 0, 0]) gt2_pulley(); // blue gt2 belt at motor color("blue") translate([nema17_size / 2, nema17_size / 2 + 6.5, nema17_mount_wall + 1]) rotate([0, 0, 180]) gt2_belt(outer_length - (2 * slot) - nema17_size / 2 - x_rail_dist - y_carriage_pos - 15); color("blue") translate([-outer_length + (3 * slot) + 10 + nema17_size / 2, nema17_size / 2 - 6.5, nema17_mount_wall + 1]) gt2_belt(outer_length - (3 * slot) - 10); } // right ("red") motor translate([outer_width - slot - nema17_size, outer_length - slot - nema17_size - nema17_mount_wall, outer_height + nema17_mount_wall]) rotate([180, 0, 90]) { color("red") translate([0, 0, -65]) nema17(65); color("green") nema17_mount(slot); // red motor pulley color("cyan") translate([nema17_size / 2, nema17_size / 2, 8.2]) gt2_pulley(); // red gt2 belt at motor color("red") translate([nema17_size / 2, nema17_size / 2 + 6.5, nema17_mount_wall + 8]) rotate([0, 0, 180]) gt2_belt(outer_length - (3 * slot) - 10); color("red") translate([nema17_size / 2 - (outer_length - (2 * slot) - nema17_size / 2 - x_rail_dist - y_carriage_pos - 15), nema17_size / 2 - 6.5, nema17_mount_wall + 8]) gt2_belt(outer_length - (2 * slot) - nema17_size / 2 - x_rail_dist - y_carriage_pos - 15); } // x carriage belts on blue side color("blue") translate([slot + 29, slot + x_rail_dist + 7 + y_carriage_pos, outer_height - 1]) rotate([180, 0, 0]) gt2_belt(x_carriage_pos - 20); color("red") translate([slot + 15, slot + 23 + y_carriage_pos, outer_height - 8]) rotate([180, 0, 0]) gt2_belt(x_carriage_pos - 6); // x carriage belts on red side color("red") translate([slot + x_carriage_width + x_carriage_pos - 7, slot + x_rail_dist + 7 + y_carriage_pos, outer_height - 8]) rotate([180, 0, 0]) gt2_belt(outer_width - x_carriage_pos - (2 * slot) - x_carriage_width - 20); color("blue") translate([slot + x_carriage_width + x_carriage_pos - 7, slot + 23 + y_carriage_pos, outer_height - 1]) rotate([180, 0, 0]) gt2_belt(outer_width - x_carriage_pos - (2 * slot) - x_carriage_width - 10); // long back belts color("blue") translate([slot + 15, slot + 10, outer_height - 7]) gt2_belt(outer_width - nema17_size - (2 * slot) + 13); color("red") translate([slot + 15, slot + 10, outer_height - 14]) gt2_belt(outer_width - nema17_size - (2 * slot) + 13); // blue belt on red side color("blue") translate([outer_width - slot - 15, slot + 10, outer_height - 7]) rotate([0, 0, 90]) gt2_belt(y_carriage_pos + 10); // red belt on blue side color("red") translate([slot + 15, slot + 19 + y_carriage_pos, outer_height - 14]) rotate([0, 0, -90]) gt2_belt(y_carriage_pos + 10); // idler on blue side translate([slot + bearing_mount_width + 15, 0, outer_height - slot]) rotate([0, 0, 90]) slot_mount_bracket(slot, true); // idler on red side translate([outer_width - slot - 15, 0, outer_height - slot]) rotate([0, 0, 90]) slot_mount_bracket(slot, true); } // ####################################################### // ####################### Heatbed ####################### // ####################################################### module heatbed_plate() { difference() { color("yellow") cube([heatbed_width, heatbed_length, heatbed_height]); #translate([bed_x_off + (slot / 2), bed_y_off + (slot / 2), -bed_z_dist - slot - 1]) cylinder(d = 4.2, h = bed_z_dist + slot + heatbed_height + 2); #translate([heatbed_width - bed_x_off - (slot / 2), bed_y_off + (slot / 2), -bed_z_dist - slot - 1]) cylinder(d = 4.2, h = bed_z_dist + slot + heatbed_height + 2); #translate([bed_x_off + (slot / 2), heatbed_length - bed_y_off - (slot / 2), -bed_z_dist - slot - 1]) cylinder(d = 4.2, h = bed_z_dist + slot + heatbed_height + 2); #translate([heatbed_width - bed_x_off - (slot / 2), heatbed_length - bed_y_off - (slot / 2), -bed_z_dist - slot - 1]) cylinder(d = 4.2, h = bed_z_dist + slot + heatbed_height + 2); } echo(max_bed_heater_width=heatbed_width - (2 * bed_x_off) - slot - 5); echo(max_bed_heater_length=heatbed_length - (2 * bed_y_off) - slot - 5); } module heatbed() { translate([slot + frame_off_x, slot + frame_off_y, bed_draw_height]) { heatbed_plate(); // t-slots as heatbed frame translate([bed_x_off, bed_y_off, -slot - bed_z_dist]) tslot_y(slot, heatbed_length - (2 * bed_y_off)); translate([heatbed_width - slot - bed_x_off, bed_y_off, -slot - bed_z_dist]) tslot_y(slot, heatbed_length - (2 * bed_y_off)); translate([slot + bed_x_off + slot_off, bed_y_off, -slot - bed_z_dist]) tslot_x(slot, heatbed_width - 2 * (bed_x_off + slot + slot_off)); translate([slot + bed_x_off + slot_off, heatbed_length - slot - bed_y_off, -slot - bed_z_dist]) tslot_x(slot, heatbed_width - 2 * (bed_x_off + slot + slot_off)); translate([bed_x_off + slot, bed_y_off + slot, -slot - bed_z_dist]) rotate([90, 0, 90]) slot_angle_connector(); translate([bed_x_off + slot, heatbed_length - slot - bed_y_off, -slot - bed_z_dist]) rotate([90, 0, 0]) slot_angle_connector(); translate([heatbed_width - slot - bed_x_off, heatbed_length - slot - bed_y_off, -slot - bed_z_dist]) rotate([90, 0, -90]) slot_angle_connector(); translate([heatbed_width - slot - bed_x_off, bed_y_off + slot, -slot - bed_z_dist]) rotate([90, 0, 180]) slot_angle_connector(); } } // ######################################################## // ####################### Assembly ####################### // ######################################################## frame(); motion_xy(); heatbed();