# Transforming Tree 3D Printed Toy

12,469

98

15

Twist one way and this toy turns shows a slow spiral pattern. Spin it the other way and you get a very different stairstepping pattern. It's all a matter of playing with angles of rotation. Thanks to parametric design and 3D printing it's a quick path from idea to reality.

This project was inspired by John Edmark's Helicone.

OpenSCAD is a horribly ugly little program that can do wonderful things if you like thinking in arrays and loops. The process of learning it takes a couple hours, but it's free and worth the time. Here's a quick overview of how I got into it.

2. Connect it to a real editor like Sublime Text 2. Here's how.
3. Go through some tutorials.

I'm a math geek so all of this appeals to me, but I understand if you're normal and don't want to do it. The print files are coming up soon, I promise.

OK, parametric folks, let's do this.

## Step 2: The Connector

The basis of this whole toy is the way that each piece connects with the other. There is a rectangular shape that extrudes down from each piece. There is a corresponding indentation on the top of each piece. This indentation determines the pattern for the whole toy. Here it allows for an 8 degree rotation clockwise and a 40 degree rotation counterclockwise.

This one connection is pretty much all that's going on here. With that working it's just a matter of tweaking the angles until it looks good. This allows for a 48 degree range of movement.

If you wanted to, you could alter it to a one-sided extrusion for a larger range like 300 degrees, but that takes a lot longer to spin the whole toy to change states. With 11 pieces in the toy that's 528 total degrees to change states. Change to 300 degrees and that's 3,300 degrees, just over 9 full rotations.

OK, now let's create this in OpenSCAD.

Note: I'm not an expert OpenSCAD user and I'm seeing ways that my code could be cleaned up, but it works right now so... there it is.

Hells yeah, primitives!

Here's the code:

`cylinder(h=ballHeight+margin, r=connectorWidth/2, \$fn=50)`

I'm using variables in this where ballHeight is the vertical radius of the flattened spheres on the end and margin is the margin added as a space between balls so there would be oom if they were right on top of each other. So doubling this and adding 1 gives a 1mm gap between the spheres if they were directly on top of each other. The connectorWidth is the diameter of the cylinder and since cylinders are determined by radius this is cut in half.

The "\$fn=50" refers to the level of detail of the cylinder. The higher the number the more detailed the piece, but it also creates a bigger file and can slow down rendering.

## Step 4: Add the Extrusion

On the bottom a rounded rectangle is added. In OpenSCAD this means intersecting a cylinder with a box.

```intersection(){			cylinder(h=ballHeight, r=connectorWidth/2-2, \$fn=50);
cube(size=[20,8,ballHeight], center=true);
}```

The intersection function returns a shape that is where the two more shapes intersect. Here you can see the result of a rectangular solid (a "cube" in OpenSCAD) and a cylinder intersecting.

## Step 5: Make an Indentation

To make the indentation is to repeat the extrusion process a couple of times and later use the difference function to remove it from the connector.

The only change to each rectangle here is a rotation function. There is the -8 rotation in the first piece and a 40 degree rotation in the second.

```//first group allows for 8 degree twist one way		translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,-8]) cube(size=[20,8,10], center=true);
}
//second group allows 40 degree twist other way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,40]) cube(size=[20,8,10], center=true);
}```

Getting a little more complicated here, but all that's happening is that the same shape as in the last step is being recreated with the intersection of the cylinder and the rectangular solid. This is done twice with a rotation applied to the rectangular solid.

Both of these shapes are then removed from the connector with the difference function (seen later on).

## Step 6: The Result

The final addition is the rectangular bar piece that extends out from each side and the balls on the ends. That is:

```//bar			cube(size=[dist*2,4,3], center=true);
//balls on ends
translate([dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);
translate([-dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);```

Here is the full code for the connector module:

```module spinner(dist){	//central holder for dowel
difference(){
//main section
union(){
//cylinder
translate([0,0,-(ballHeight+margin)/2]) cylinder(h=ballHeight+margin, r=connectorWidth/2, \$fn=50);
//bar
cube(size=[dist*2,4,3], center=true);
//balls on ends
translate([dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);
translate([-dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);
//male connector
translate([0,0,-(ballHeight+margin)/2-extrude])
intersection(){
cylinder(h=ballHeight, r=connectorWidth/2-2, \$fn=50);
cube(size=[20,8,10], center=true);
}
}
//indented space on top
//first group allows for 8 degree twist one way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,-8]) cube(size=[20,8,10], center=true);
}
//second group allows 40 degree twist other way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,40]) cube(size=[20,8,10], center=true);
}
//cylinder to cut out middle for dowel
translate([0,0,-25]) cylinder(h=50, r=3.2, \$fn=50);
}
}```

## Step 7: Putting It All Together

Here's the resulting code for the whole thing with plenty of variables for messing around with it. The OpenSCAD file is also attached here.

The structure for the tree is:

• top cap (only the extrusion)
• spinners (a loop)
• bottom cap (only the indentation)

```spinners=8;				//how many bars spinningstartDist=20;			//initial distance for spinner. Minimum of (ballWidth+connectorWidth)/2
distStep=5;				//increment in distance for each spinner
rotatePreview=8;		//preview rotation effects
ballWidth=14;			//width of balls on each spinner
ballHeight=6;			//height of balls on each spinner
connectorWidth=17;		//width of connector in middle of spinner
indent=3.5;				//depth of indentation in connector
extrude=3;				//depth of extrusion from connector
margin=1;				//extra height between ballsmodule spinner(dist){
//central holder for dowel
difference(){
//main section
union(){
//cylinder
translate([0,0,-(ballHeight+margin)/2]) cylinder(h=ballHeight+margin, r=connectorWidth/2, \$fn=50);
//bar
cube(size=[dist*2,4,3], center=true);
//balls on ends
translate([dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);
translate([-dist,0,0]) scale([1,1,ballHeight/ballWidth]) sphere(r=ballWidth/2, \$fn=50);
//male connector
translate([0,0,-(ballHeight+margin)/2-extrude])
intersection(){
cylinder(h=ballHeight, r=connectorWidth/2-2, \$fn=50);
cube(size=[20,8,10], center=true);
}
}
//indented space on top
//first group allows for 8 degree twist one way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,-8]) cube(size=[20,8,10], center=true);
}
//second group allows 40 degree twist other way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1, \$fn=50);
rotate([0,0,40]) cube(size=[20,8,10], center=true);
}
//cylinder to cut out middle for dowel
translate([0,0,-25]) cylinder(h=50, r=3.2, \$fn=50);
}
}//top cap
difference(){
union(){
//main section
translate([0,0,(ballHeight+margin+extrude+3)-(ballHeight+1)/2]) cylinder(h=ballHeight+margin, r=connectorWidth/2, \$fn=50);
//male connector
translate([0,0,(ballHeight+margin+extrude+3)-(ballHeight+margin)/2-extrude])
intersection(){
cylinder(h=ballHeight, r=connectorWidth/2-2, \$fn=50);
cube(size=[20,8,ballHeight], center=true);
}
}
translate([0,0,-100]) cylinder(h=200, r=3.2,  \$fn=50);
}//spinners
for (i = [0:spinners-1]) {
translate([0,0,-i*(ballHeight+margin+extrude+3)])rotate([0,0,rotatePreview*i]) spinner(i*distStep+startDist);
}//bottom cap
translate([0,0,-(ballHeight+margin+extrude+3)*spinners-3])
difference(){
//main section
translate([0,0,-(ballHeight/2+1)/2]) cylinder(h=ballHeight+margin, r=connectorWidth/2,  \$fn=50);
//indented space on top
//first group allows for 8 degree twist one way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1,  \$fn=50);
rotate([0,0,-8]) cube(size=[20,8,10], center=true);
}
//second group allows 45 degree twist other way
translate([0,0,ballHeight/2-indent+margin/2])
intersection(){
cylinder(h=ballHeight+1, r=connectorWidth/2-1,  \$fn=50);
rotate([0,0,40]) cube(size=[20,8,10], center=true);
}
//dowel cutout
translate([0,0,-180]) cylinder(h=200, r=3.2,  \$fn=50);
}```

## Step 8: Print Up the Pieces

I printed up the pieces for this in white nylon by Shapeways. It's the white strong & flexible option and this cost \$52 for printing and shipping.

To get the STL for printing, pick how many spinners you want here and export the STL or use the file attached to this step.

## Step 9: Sand Down the Dowel

I didn't leave much margin at all in the file for a 1/4" dowel. Since there's a slight variation in thickness in both the print and the dowel I was aiming for a snug fit that could be fixed with a little bit of sanding. Dowels are much cheaper than 3D printed pieces after all.

I marked where I wanted the bottom cap to be and sanded the rest until the pieces could slide easily, but not so much that they could wiggle.

## Step 10: Glue the Top Cap in Place

Using a little bit of cyanoacrylate glue I stuck the top cap in place.

## Step 11: Spin!

Hold the bottom cap with one hand and twist the dowel with the other. The dowel will move the top cap which then moves the rest of the spinner pieces.

That's it! If you have any questions, feel free to ask.

## Recommendations

• ### Autodesk Technology Center SF CNC Workholding Class

192 Enrolled

## 15 Discussions

Thanks. I need to revisit this one as my new 3D printers are a lot better to make more versions at home.

Best of the Best, really well said

It seems like this would make a good demonstration of how dial-type padlocks work. You could align the top few branches with each other, but only if you turn it the right amount.

Don't know if its the right website, but you should put this on kickstarter or some other website to sell them.