$fn=64; // --- Parameters --- base_radius = 50; base_thickness = 15; ball_radius = 6.0; socket_radius = 6.2; // Slightly larger for snap-fit clearance arm_length = 20; alligator_hole_diameter = 4.2; // Standard alligator clip friction fit // --- Print Layout --- // Lays out all parts flat on the build plate for easy 3D printing base(); // Generate 4 arms, each with 4 segments and 1 end effector for(arm=[0:3]) { for(seg=[0:3]) { translate([base_radius + 20 + seg*22, -33 + arm*22, 0]) arm_segment(); } translate([base_radius + 20 + 4*22, -33 + arm*22, 0]) end_effector(); } // --- Modules --- module base() { union() { difference() { // Main base body (Hexagon) cylinder(r=base_radius, h=base_thickness, $fn=6); // Center tray for parts/sponge translate([0,0,base_thickness - 4]) cylinder(r=base_radius*0.6, h=4.1, $fn=6); } // Ball mounts for arms for(i=[30 : 90 : 300]) { rotate([0,0,i]) translate([base_radius*0.75, 0, base_thickness-0.1]) { cylinder(r=ball_radius*0.8, h=8.1); translate([0,0,8]) sphere(r=ball_radius); } } } } module arm_segment() { difference() { union() { // Socket body cylinder(r=socket_radius+2.5, h=socket_radius+6); // Neck translate([0,0,socket_radius+6 - 0.1]) cylinder(r=ball_radius*0.65, h=arm_length+0.2); // Top Ball translate([0,0,socket_radius+6+arm_length]) sphere(r=ball_radius); } // Socket internal cavity translate([0,0,5]) sphere(r=socket_radius); // Bottom chamfer for easy insertion translate([0,0,-0.1]) cylinder(r1=socket_radius+0.5, r2=5.2, h=2.1); // Slits for snapping (flexibility) translate([-(socket_radius+3.5), -1, -0.1]) cube([(socket_radius+3.5)*2, 2, socket_radius+6.2]); translate([-1, -(socket_radius+3.5), -0.1]) cube([2, (socket_radius+3.5)*2, socket_radius+6.2]); } } module end_effector() { difference() { union() { // Socket body cylinder(r=socket_radius+2.5, h=socket_radius+6); // Top cylinder for clip translate([0,0,socket_radius+6 - 0.1]) cylinder(r=socket_radius+2.5, h=10.1); } // Socket internal cavity translate([0,0,5]) sphere(r=socket_radius); // Bottom chamfer translate([0,0,-0.1]) cylinder(r1=socket_radius+0.5, r2=5.2, h=2.1); // Slits for snapping translate([-(socket_radius+3.5), -1, -0.1]) cube([(socket_radius+3.5)*2, 2, socket_radius+6.2]); translate([-1, -(socket_radius+3.5), -0.1]) cube([2, (socket_radius+3.5)*2, socket_radius+6.2]); // Hole for alligator clip translate([0,0,socket_radius+6 + 2]) cylinder(r=alligator_hole_diameter/2, h=10); } }