/* DELTA options */ arm_sep = 50; arm_length = 240; tower_radius = 120; effector_radius = 25; /* DISPLAY/ANIMATION options */ plate = 0; // set to 0 for view, or 1..3 for plates of parts circle_r = 105; print_height = 200; nozzle_length = 20; /* shouldn't need to touch anything below here */ $fa = 1; $fs = 1; module vslot(sections=3, length=100, negative=0) { cutext = [[12.00,4.50],[10.00,4.50],[8.20,2.7],[8.20,5.50],[6.56,5.50],[3.90,2.84],[3.90,0.21],[3.69,0.00],[3.90,-0.21],[3.90,-2.84],[6.56,-5.50],[8.20,-5.50],[8.20,-2.7],[10.00,-4.50],[12.00,-4.50]]; cutint = [[16.10,0.21],[16.10,2.84],[12.70,6.24],[12.70,8.78],[7.30,8.78],[7.30,6.24],[3.90,2.84],[3.90,0.21],[3.69,0.00],[3.90,-0.21],[3.90,-2.84],[7.30,-6.24],[7.30,-8.78],[12.70,-8.78],[12.70,-6.24],[16.10,-2.84],[16.10,-0.21],[16.31,0.00],]; cutcorner = [[8.20,8.20],[6.57,8.20],[6.57,7.66],[7.66,6.57],[8.20,6.57]]; epsilon = 0.05; render(convexity=5) linear_extrude(height=length, convexity=5) offset(r=negative * 0.15) difference() { hull() { for (i=[0:1]) for (j=[0:1]) translate([sections * -10 + sections * 20 * i + 1.5 - 3 * i, -8.5 + 17 * j, 0]) circle(r=1.5, h=length, $fn=16); } for(i = [0,180]) rotate(i) translate([10 * (sections - 1), 0]) { polygon(cutext); translate([5,-2.89]) square([10,5.78]); } for(i = [90,270]) rotate(i) for(j = [0:sections-1]) translate([0, (sections - 1) * 10 - 20 * j]) { polygon(cutext); translate([5,-2.89]) square([10,5.78]); } if(sections > 1) for(i = [0:sections-2]) translate([(sections - 3) * 10 - i * 20, 0]) polygon(cutint); if (negative == 0) { for(i = [0:sections-1]) translate([i * 20 - 10 * (sections - 1),0]) circle(2.1); for(i = [90,270]) rotate(-i) translate([0,(sections - 1) * 10]) polygon(cutcorner); for(i = [ 0,180]) rotate(-i) translate([(sections - 1) * 10,0]) polygon(cutcorner); } } } module carriage() { translate([10, -40, -40]) cube([30, 80, 50]); difference() { hull() { rotate([0, -45, 0]) translate([-1, -40, -10]) cube([2, 80, 23.15]); translate([29, -40, -10]) cube([1, 80, 20]); } for (i=[0:1]) translate([0, arm_sep / -2 + i * arm_sep, 0]) sphere(5.1); } } module effector() { difference() { hull() { for (i=[0:2]) { for (j=[0:1]) { rotate([0, 0, i * 120]) translate([effector_radius, 0, 0]) { rotate([0, 45, 0]) translate([0, arm_sep / -2 + j * arm_sep, -1]) { hull() { cylinder(r=7.5, h=2); translate([7.5 - 1, 7.5/-2, 0]) cube([1, 7.5, 2]); } } } } } } for (i=[0:2]) { for (j=[0:1]) { rotate([0, 0, i * 120]) translate([effector_radius, 0, 0]) { rotate([0, 45, 0]) translate([0, arm_sep / -2 + j * arm_sep, -1]) { translate([0, 0, -6.5]) { hull() { cylinder(r=5.2, h=2.2); translate([20, -5.2, 0]) cube([1, 10.4, 2.2]); } cylinder(r=1.5, h=3); } } } } } for (i=[0:2]) { for (j=[0:1]) { rotate([0, 0, i * 120]) translate([effector_radius, arm_sep / -2 + j * arm_sep, 0]) sphere(5.1); } } cylinder(r=12, h=100, center=true); } render() { difference() { union() { hull() { translate([0, 0, -nozzle_length ]) cylinder(r=0.6, h=1, $fn=12); translate([0, 0, -nozzle_length + 4]) cylinder(r=5, h=50); } translate([0, 0, -nozzle_length + 20]) cylinder(r=8, h=40); translate([0, 0, -nozzle_length + 55.5 - 4.75 - 4.5 - 15]) cylinder(r=8 / cos(180/6), h=15, $fn=6); } translate([0, 0, -nozzle_length + 55.5 - 4.75]) difference() { cylinder(r=50, h=4.5); cylinder(r=6, h=100, center=true); } for (i=[0:4]) translate([0, 0, -nozzle_length + 55.5 - 4.75 - 4.5 - 2 - i * 2]) { difference() { cylinder(r=50, h=1); cylinder(r=5, h=10, center=true); } } } } } module tower(angle = 0, h = 650) { rotate([0, 0, angle]) { translate([tower_radius + effector_radius, 0, 0]) { //translate([20, -30, -100]) cube([20, 60, h]); translate([30, 0, -100]) color([0.7, 0.7, 0.7, 1]) rotate(90) vslot(length=h); } } } module arm(p0 = [0, 0, 0], p1 = [0, 0, 0]) { d = p1 - p0; translate(p0) rotate([0, acos(d[2] / norm(d)), atan2(d[1], d[0])]) { sphere(5); translate([0, 0, arm_length]) sphere(5); cylinder(r=3, h=arm_length); } echo(str("arm len: ", norm(p1 - p0))); } function sq(x) = (x * x); function unit(x) = (x / norm(x)); // from https://github.com/Smoothieware/Smoothieware/blob/edge/src/modules/robot/arm_solutions/LinearDeltaSolution.cpp#L48-62 function carriage_heights(pos) = [ sqrt(sq(arm_length) - sq((tower_radius * cos( 0)) - pos[0]) - sq((tower_radius * sin( 0)) - pos[1])) + pos[2], sqrt(sq(arm_length) - sq((tower_radius * cos(120)) - pos[0]) - sq((tower_radius * sin(120)) - pos[1])) + pos[2], sqrt(sq(arm_length) - sq((tower_radius * cos(240)) - pos[0]) - sq((tower_radius * sin(240)) - pos[1])) + pos[2] ]; if (plate == 0) { rot0 = [ [1, 0, 0], [0, 1, 0], [0, 0, 1]]; rot120 = [ [cos(120), -sin(120), 0], [sin(120), cos(120), 0], [ 0, 0, 1]]; rot240 = [ [cos(240), -sin(240), 0], [sin(240), cos(240), 0], [ 0, 0, 1]]; rot = [rot0, rot240, rot120]; // I don't know why these must be swapped, but they must pos = [cos($t * 360) * circle_r, sin($t * 360) * circle_r, print_height]; ch = carriage_heights(pos); translate([0, 0, -8]) { color([0, 0, 0]) translate([215/-2, 215/-2, 0]) cube([215, 215, 3]); %#cylinder(r=circle_r, h=208); } translate([0, 0, -100]) cylinder(r=effector_radius + tower_radius + 45, h=90); echo(str("Base Diameter: ", (effector_radius + tower_radius + 45) * 2)); translate([0, 0, 550]) { difference() { hull() { for (i=[0:2]) rotate([0, 0, i * 120]) translate([effector_radius + tower_radius, -40, 0]) cube([45, 80, 5]); } for (i=[0:2]) rotate([0, 0, i * 120]) for (j=[0:2]) translate([effector_radius + tower_radius + 30, -20 + j * 20, 0]) cylinder(r=2.1, h=20, center=true); } } for (i=[0:2]) { tower(i * 120); #rotate(i * 120) translate([0, 0, -90]) linear_extrude(height=80) translate([-effector_radius - tower_radius -10, 0]) square([16, 200], center=true); } for (i=[0:2]) { translate([0, 0, pos[2] + nozzle_length]) { rotate([0, 0, i * 120]) translate([tower_radius + effector_radius, 0, ch[i] - pos[2]]) carriage(); for (j=[0:1]) { arm([pos[0], pos[1], 0] + ([effector_radius, arm_sep / -2 + j * arm_sep, 0] * rot[i]), [tower_radius + effector_radius, arm_sep / -2 + j * arm_sep, ch[i] - pos[2]] * rot[i]); } } } translate(pos + [0, 0, nozzle_length]) effector(); } else { %cube([200, 200, 0.1], center=true); // TODO: plate of parts if (plate == 1) { translate([0, 0, 6]) effector(); for (i=[0:2]) rotate(i * 120) translate([45, 0, 10]) rotate([180, 0, 0]) carriage(); } }