Day 146 – Customizable Print-In-Place Fidget Cube

Day 146 – Customizable Print-In-Place Fidget Cube

Day 146 – Customizable Print-In-Place Fidget Cube 640 480 mathgrrl

Today we finished our customizable print-in-place fidget cube model. By changing just a few parameters in OpenSCAD code, we can decide whether the fidget cube will have a snub configuration (as shown below), set the sizes of the blocks and the hinges, and fine-tune the clearance between moving parts. It still amazes me that this model can print in place, all in one piece, with functioning hinges – especially since during the print some of the hinges are horizontal while others are vertical!

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 = yes
cube_height = 20
stacking_clearance = .3
hinge_radius = 2.5
hinge_clearance = .5

Technical notes: I tried to keep my previous OpenSCAD projects 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:

// 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!

——————

As an Amazon Associate we earn from qualifying purchases, so if you’ve got something you need to pick up anyway, going to Amazon through this link will help us keep Hacktastic running. Thanks! :)


Leave a Reply

Back to top