When preparing this article, I wanted to find out what people have problems with openSCAD. To my surprise, the most common question was about creating a cylinder. There is a cylinder command that you will learn the details about first. After that, you will see innovative ways to create cylinders to your liking. You can also take away cylinders from other pieces to create more interesting things. Most readers, who come here probably wants to see a hollow cylinder or a tube of some kind. Keep reading, we have lots in store for you.

The cylinder command

If you use the simplest version of the cylinder command, you only need one parameter. This makes one solid uniform cylinder and nothing more. You should note that that cylinder will be of standard radius and the height of the value in the parenthesis. The command has many options though, let’s dig through them.

cylinder( r1 = 20 );
cylinder( r1 = 20, r2 = 5 );
cylinder( r1 = 20, h = 40 );
cylinder( r = 20, h = 40 );
cylinder( r1 = 20, r2 = 5, h = 40, center = true );

The first two cylinders in the code above make no sense because they have no height. A common mistake is when you forget the value and it does not look the way you intended. When you use variables, the same thing happens if you use an undefined variable. In this case for height, but check the console log when you run it.

A Cone

The third one is a cone, the reason is that the r2 value has a standard size. Try the fourth one, and see what happens. The last one creates a cone where you have full control of the dimensions. This one is simple to use for solid cones. You set the two radii and the height and you are done. You can also use the diameter if that suits you better.

The center = true value is valid for the z axle, leaving the cone halfway up from the “ground”. Default is false, which makes the bottom of the cone end up on the “ground” so to speak. You can also choose how close the cones walls are to being circular with the ‘\$fn’ parameter.

Hollow cylinder

Hey, wait a minute! This only creates solid pieces, how do I drill holes in them? You ask, thank you! I will tell you. The answer is all in the difference. The command that is. Consider the code below, it contains two cylinders which are embraced with curly brackets and the difference command.

difference(){
cylinder(r = 30, h = 40);
cylinder(r = 28, h = 41);
}

Simply put, when you have several pieces, then you cut away material from the first piece using all the following pieces. In this case, you cut a cylinder out of a cylinder. If you want to cut any other shape out, you can do that also. Try a cube or a sphere! Note the interesting, and sometimes devastating effects the \$fn value can have on this code.

Hollow Cone

You can also do this with a cone, just use the double radius values. Since you are defining both cones, you have a lot of control on the final result. The simplest hollow cone is just two cones inside each other with a thickness for the material.

difference() {
cylinder( r1 = 30, r2 = 12, h = 50);
cylinder( r1 = 25, r2 = 7, h = 45);
}

This cone is covered at the top, you can open it by simply setting the second height higher than the first. Since you have two cylinders, you can change any of the two. As an example, you can cut a straight hole through it by changing the second cylinder. You can also choose a cube, but be aware this can cut too much material out of the cone.

Pyramid

This may seem irrelevant but it is a useful trick you need to keep in mind as you continue using openSCAD. All cylinders, and other elements, are an approximation of a shape. You read about the \$fn parameter earlier, here you take advantage of it. With this in mind, you may think: A Pyramid is a cone with four sides. Correct! use \$fn = 4 and you have a cone with four sides, meaning a pyramid.

difference() {
cylinder(r1 = 30, r2 = 12, h = 40, \$fn = 4);
cylinder(r1 = 25, r2 = 7, h = 35, \$fn = 4);
}

The inner cylinder cuts the same cylinder as the outer one. Until you start playing with the \$fn parameter. To get familiar with the effects of this parameter, try to make a four-legged stool. How does the \$fn parameter affect the result? Also, how can you cover the top or the bottom?

Combining many

To have a lot of use of cylinders, you should learn how to combine many of them. The final result can be very complex and sometimes even useful. Putting a top on your cylinder is one option. To do this well, you must start using variables. Make it a habit to put them at the top of what you are designing. It makes it easier to make modules later.

thickn = 5;
baser = 30;
topr = 12;
height = 50;

union() {
// The bottom cone
difference() {
cylinder(r1 = baser, r2 = topr, h = height);
cylinder(r1 = baser-thickn, r2 = topr - thickn, h = height + thickn);
}
// The top ball
translate([0, 0, height])
difference(){
sphere(r = topr);
sphere(r = topr -thickn);
translate([0, 0, -topr])
cube(size = topr*2, center = true);
}
}

Starting from the top, you have variables. They are for the thickness, base radius, top radius, and height. The union statement brings the pieces together. Inside the braces, you have the cone and then the top ball. Because they are inside the union, they will become one piece at the end. You can do even more when you use many cylinders in many angles.

Making a test tube

Moving on from cones, make a test tube. First, you need to consider what shapes make a test tube. The main part is a cylinder, nothing fancy, just the regular difference between two cylinders. If you set the length as a variable, you can use that value as a reference. You need to know where the tube ends and becomes the half-sphere at the bottom. You will also use the radius for the tube to define the sphere.

tubr = 20;
tubl = 80;
thickn = 2;

difference() {
cylinder(r1 = tubr, r2 = tubr, h = tubl);
cylinder(r1 = tubr - thickn, r2 = tubr - thickn, h = tubl);
}

Try this and you will have only a simple cylinder, to make the whole tube you need to melt it together with the half sphere. There is no half-sphere in the default openSCAD, you must make it. Use the difference between two spheres to create a hollow sphere, then remove another cube that cuts off the sphere.

difference() {
sphere(tubr);
sphere(tubr - thickn);
translate([0, 0, -tubr])
cube(size=tubr*2, center = true);
}

Now, you have two separate pieces. The next step is to put them together. Here, you can use the union command. Like the difference command, the union takes all the pieces in order. In union, the order is not as important since it is an addition. The code will look a little ugly because we do not use modules here.

union() {
// Main Tube
difference() {
cylinder(r1 = tubr, r2 = tubr, h = tubl);
cylinder(r1 = tubr - thickn, r2 = tubr - thickn, h = tubl);
}
// Bottom sphere
translate([0, 0, tubl]) {
difference() {
sphere(tubr);
sphere(tubr - thickn);
translate([0, 0, -tubr])
cube(size=tubr*2, center = true);
}
}
// Top ring
difference() {
cylinder(r = tubr + thickn, h = thickn);
cylinder(r = tubr, h = thickn);
}
}

Here we design it upside down, this is up to you. Do what is convenient for the particular case. You can always rotate it when you use it. The top ring has sharp edges, you can remedy this by using a circle and rotate_extrude it. There are other ways to do it, explore, and experiment!

rotate_extrude(convexity = 10, \$fn = 100)
translate([tubr, 0, 0])
circle(r = thickn, \$fn =100);

Combining Many cylinders

Once you have made a tube out of several cylinders, you may also want to connect them in different ways. To do this, you can use a union again. Let’s say you want one tube in a forty-five-degree angle to the other tube. To make this, you position the angled tube halfway up the large tube.

union() {
tube(50, 4, 300);
translate([0, 0, totlength/2]) rotate([45, 0, 0]) {
tube(50, 4, 150);
}
}

When you try this, it looks great from the outside. When you look inside, you see that you have both entire tubes. The short one is blocking the flow in the long tube. To remedy this, you need to erase both cylinders inside the tubes. You can consider the whole union one piece and put the corresponding cylinders after it inside a difference.

difference() {
union() {
tube(50, 4, 300);
translate([0, 0, totlength/2]) rotate([45, 0, 0]) {
tube(50, 4, 150);
}
}
cylinder(r = 50 - 4, h = totlength);
translate([0, 0, totlength/2]) rotate([45, 0, 0]){
cylinder(r = 50 - 4, h = totlength/2);
}
}

As you can see, the first cylinder stretches the whole length of the tube. This will erase anything inside the large tube but the small tube that is leaning also needs to be erased. The translate command moves the tube up halfway, it then rotates and put the cylinder inside the tube. In fact, the code is copied from above and the tube is replaced with a cylinder.

Plumbing

If you want to make more tubes, you can use the module in the example above and start expanding. The code is available at https://github.com/matstage/openSCAD-Cylinders.git, At the time of writing, there are only these two but check back often to see more. You may be able to create more exciting stuff.

Inside a block

If you are aiming to make an internal combustion engine, you need a cylindrical hole in a solid piece. Below is an example, the simplest possible, for cooling channels and pistons there is a lot more to add. That is for another day though.

module cylinderblock(
cylinderR = 3,
Edge = 1,
numCylinders = 8)
{
difference() {
cube([cylinderR*2 + Edge * 2,
cylinderR*2*numCylinders+Edge*numCylinders + Edge,10]);
for(x = [0:1:numCylinders-1])
translate([cylinderR + Edge, cylinderR*x*2+Edge*x+ cylinderR+Edge,0])
cylinder(r = cylinderR, h = 12);
}
}

Here, you have a cube that grows according to the number of cylinders you want inside the block. All values in the module are the default so you can use it without values. To use it, use the ‘use <cylinderBlock.scad>’ statement at the top of your file and then add cylinderblock(numCylinders = 8). You can use or omit any value, when you do omit them, it will take the default. In short, the inside the module starts with the values and then creates a cube to be long enough to fit the cylinders. It then continues by removing the cylinders with a for statement. Thanks to the for statement, you can make a bigger or smaller block. For more advanced modules, you can put constraints in that change the design when certain values are reached. Maybe you want to make it a V if it is 8 or more cylinders.

Extruding from a flat shape

Another way to create a cylinder is to make a circle and extrude it. A solid cylinder is only two lines:

linear_extrude(15)
circle(20);

This creates a 15 (no units in openSCAD) long, with a 20 radius. You can use the diameter using the d parameter. Just creating a cylinder is not very useful but you can use the same technique for any 2D shape. You will see this later. While a hollow cylinder the code is a little longer.

linear_extrude(15)
difference() {
circle(20);
circle(18);
}

This is the same but, as we have done earlier, you remove the centre circle. You can also bend it in a circle with the rotate_extrude version. This is great for making donuts, the simplest version looks like one.

rotate_extrude(angle =180, convexity =10) {
translate([30,0,0])
difference() {
circle(20);
circle(10);
}
}

This code creates a half-circle that is hollow. A note that you should be careful with is the translate is necessary or you will get an error: “ERROR: all points for rotateextrude() must have the same X coordinate sign (range is -2.09 -> 20.00)”. The numbers will depend on the value in the circle. Since this creates the same shape as a cylinder it may seem useless. It is not! The best use of this command is to make flat shape functional somehow. The manual has a simple polygon as an example, it creates a round shape where you can run a belt. You also can twist it around. The below code creates a corkscrew.

translate([-80,0,0])
linear_extrude(80, twist = 900, scale = 2.0, slices = 100)
translate([2, 0, 0])
square(10);

The example in the manual shows a polygon that can be useful. The below code can be whatever you like but illustrates the power of doing it this way.

translate([0, -80, 0])
rotate_extrude(angle = 275)
translate([12,3,2])
polygon(points = [[0,0], [20,17], [34,12], [25,22], [20, 30]]);

You can experiment with the shape of the polygon until you get it right for your application. If it feels a little daunting using just numbers, you can create the profile in other CAD programs and import the dxf result using the import() command.

Conclusion

Making a cylinder is simple but just the start of the process. The tricky part is to make something useful with it. You also need to incorporate it into your design and maybe create more complex issues than cylinders. Find ways and challenges for your ongoing expansion of knowledge using openSCAD. Remember to use the documentation and lean on other software when it cannot be easily achieved with numbers and such. Something not covered in this post is that you can draw stuff in Inkscape and Blender and import it to openSCAD. Exporting from openSCAD to stl and other formats is well supported and if you are really curious, check out the creations over on Thingiverse. They have a bundle of enthusiasts contributing things to their site.