STL file: http://www.geekhaus.com/makerhome/day146_fidgetcube_blue.stl
Thingiverse link: http://www.thingiverse.com/thing:230139
Settings: Replicator 2 with MakerWare .2mm/standard in about an hour and a half. In addition to looking cool, the snub sides reduce the print time by about 30 minutes and save some plastic. We used a custom profile to get linear fill instead of hexagons. No raft or support are needed! Customizer settings were as follows below (although I suggest setting hinge_clearance lower for future models).
snub = yesTechnical notes: I tried to keep my previous OpenSCAD projects (Days 96, 112, 113, and 133) well-written and commented so that people could learn from what I was learning. But I'm notoriously bad at rotating and reflecting objects mentally so this code is full of random transformations to put objects where I needed them to be. It isn't efficient and it isn't pretty, but here it is:
cube_height = 20
stacking_clearance = .3
hinge_radius = 2.5
hinge_clearance = .5
// mathgrrl print-in-place fidget cube
//////////////////////////////////////////////////////
// PARAMETERS ////////////////////////////////////////
// Decide whether you want the pieces to be full cubes or snub on one side
snub = "yes"; // [no:Cube Pieces,yes:Snub Pieces]
// Choose a side length for the cubes, in mm
cube_height = 20;
// Choose a stacking clearance factor, in mm (controls distance between cubes)
stacking_clearance = .3;
// Choose a hinge radius, in mm
hinge_radius = 1.5;
// Choose a hinge clearance factor, in mm (controls distance around hinge parts)
hinge_clearance = .45;
// Other variables that people don't get to choose
$fn=24*1;
fudge = .01*1;
corner_radius = .1*cube_height;
outside_height = .4*(cube_height-2*stacking_clearance);
inside_height = (cube_height-2*stacking_clearance)-2*outside_height;
cone_height = 1.4*hinge_radius;
//////////////////////////////////////////////////////
// RENDERS ///////////////////////////////////////////
rotate(-45,[0,0,1])
translate([0,0,2*cube_height])
rotate(90,[0,1,0])
union(){
// one row of four cubes
row_assembly();
// another row of four cubes
translate([0,2*cube_height,2*cube_height])
rotate(-90,[1,0,0])
mirror([0,0,1])
mirror([1,0,0])
row_assembly();
}
//////////////////////////////////////////////////////
// MODULES ///////////////////////////////////////////
// one row of the assembly
module row_assembly(){
union(){
color("blue")
hinged_cube(180,[1,0,0],[1,0,0]);
color("red")
translate([-cube_height/2,cube_height/2,0])
mirror([0,1,0])
translate([-cube_height/2,cube_height/2,0])
rotate(90,[1,0,0])
hinged_cube(0,[1,0,0],[0,0,0]);
color("green")
translate([cube_height,cube_height/2,cube_height/2])
rotate(-90,[0,1,0])
rotate(180,[1,0,0])
mirror([0,1,0])
translate([-cube_height/2,cube_height/2,0])
rotate(90,[1,0,0])
hinged_cube(180,[0,1,0],[0,1,0]);
color("yellow")
translate([-cube_height,cube_height,cube_height])
rotate(-90,[1,0,0])
rotate(90,[0,0,1])
rotate(-90,[1,0,0])
hinged_cube(0,[1,0,0],[0,0,0]);
}
}
// one cube to rule them all
module hinged_cube(the_angle,the_vector,the_mirror){
difference(){
// cube and cylinders to start
union(){
// cube with inside top and bottom cylinders carved out
difference(){
// start with clearance cube in corner
translate([cube_height/2,cube_height/2,cube_height/2])
rotate(the_angle,the_vector)
mirror(the_mirror)
rounded_cube([cube_height,cube_height,cube_height]);
// take away inside top cylinder with clearance
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance+outside_height+inside_height])
cylinder( h=outside_height+fudge,
r1=hinge_radius+fudge+hinge_clearance,
r2=hinge_radius+fudge+hinge_clearance);
// take away inside bottom cylinder with clearance
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance-fudge])
cylinder( h=outside_height+fudge,
r1=hinge_radius+fudge+hinge_clearance,
r2=hinge_radius+fudge+hinge_clearance);
}
// top cylinder on outside hinge
translate([0,0,stacking_clearance+outside_height+inside_height+hinge_clearance])
cylinder( h=outside_height-hinge_clearance-corner_radius/2,
r1=hinge_radius,
r2=hinge_radius);
// bottom cylinder on outside hinge
translate([0,0,stacking_clearance+corner_radius/2])
cylinder( h=outside_height-hinge_clearance-corner_radius/2,
r1=hinge_radius,
r2=hinge_radius);
// inside hinge cylinder
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance+outside_height])
cylinder( h=inside_height,
r1=hinge_radius,
r2=hinge_radius);
// attacher for inside hinge cylinder
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance+outside_height])
rotate(45,[0,0,1])
translate([-.8*hinge_radius,0,0])
cube([1.6*hinge_radius,2*hinge_radius,inside_height]);
// inside hinge top cone
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance+outside_height+inside_height])
cylinder( h=cone_height,
r1=hinge_radius,
r2=0);
// inside hinge bottom cone
translate([cube_height,0,0])
rotate(90,[0,0,1])
rotate(90,[0,1,0])
translate([0,0,stacking_clearance+outside_height-cone_height])
cylinder( h=cone_height,
r1=0,
r2=hinge_radius);
}
// take away middle cylinder with clearance
translate([0,0,stacking_clearance+outside_height-hinge_clearance-fudge])
cylinder( h=inside_height+2*hinge_clearance+2*fudge,
r1=hinge_radius+fudge+hinge_clearance,
r2=hinge_radius+fudge+hinge_clearance);
// take away top cone with clearance
translate([0,0,stacking_clearance+outside_height+inside_height+hinge_clearance-fudge])
cylinder(h=cone_height, r1=hinge_radius, r2=0);
// take away bottom cone with clearance
translate([0,0,stacking_clearance+outside_height-cone_height-hinge_clearance+fudge])
cylinder(h=cone_height, r1=0, r2=hinge_radius);
}
}
// module for making rounded cubes from convex hull of corners
module rounded_cube() {
dist = cube_height/2-corner_radius-stacking_clearance;
hull() {
// seven of the eight vertices of a cube
translate([dist,dist,dist])
sphere(r=corner_radius);
translate([-dist,dist,dist])
sphere(r=corner_radius);
translate([dist,-dist,dist])
sphere(r=corner_radius);
translate([-dist,-dist,dist])
sphere(r=corner_radius);
translate([dist,dist,-dist])
sphere(r=corner_radius);
translate([dist,-dist,-dist])
sphere(r=corner_radius);
translate([-dist,-dist,-dist])
sphere(r=corner_radius);
// don't include the eighth if snub desired
if (snub=="yes"){
}
else{
translate([-dist,dist,-dist])
sphere(r=corner_radius);
}
}
}
UPDATE: Featured on 1/29/2014 as Thing-of-the-Day by AlexHuff at 3dideaform.com.
UPDATE: The print-in-place fidget cube made an appearance on the Adafruit blog with a comment from emmet himself (original creator of the printable snap-together fidget cube):
Guest Curator Emmett Lalish has this to say about this 3DxMechanicals project: “This is why I love Thingiverse: I post a snap-assemble design, then someone figures out how to print it pre-assembled. It definitely pushes the boundaries of what’s printable and how the slicers work. This is how we push the technology forward.”UPDATE: From this post by Kevin Osborn on the Ultimaker forum, I learned that you can pick up prints of my fidget cubes at the MakerBot retail store!