Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Models for 3D Printing With OpenSCAD

DZone's Guide to

Models for 3D Printing With OpenSCAD

An important step in 3D printing is moving on to making your own models. For people who prefer to model like programmers, OpenSCAD is there to make things easier.

· IoT Zone
Free Resource

Like many others, I have recently acquired the hobby of maintaining and using a 3D printer (in my case from Printrbot). I was initially impressed with the wide array of models available from various sites, but that feeling wore off quickly. Being restricted to models made by others feels more like observer status rather than a real participant.

I spent a little time with SketchUp, but I'm a programmer, not an artist. Unfortunately, it's been 20 years since I did any substantial work in CAD. Fortunately, there's OpenSCAD, a tool designed for programmers. OpenSCAD builds 3D models from a programming language description. Functions with parameters allow creation of 3D objects and "extrusion" of 2D outlines (applying a transformation to bring a 2D outline into three dimensions). For example, a simple sphere:

// radius=2, fragment angle=5, fragment size=0.1
sphere(2, $fa=5, $fs=0.1);

Quickly produces a model:

More complicated models use C-style blocks with curly braces to apply set transformations and groupings to objects. OpenSCAD is feature-rich, so for new users like me, it is a little daunting. Fortunately, the Edit-Compile-Test loop is very quick, since you can make a small change and immediately see results in the tool.

Of course, this kind of thing is a lot more fun with a real example. So I was almost happy to find that I lost a small plastic part needed to securely hold a patio umbrella in its base. A chance to try out modeling skills and make something real! The piece has to hold the umbrella securely, so the pole forms an inner diameter. The piece then has to fit into the base, so that forms one outer diameter, but it also needs a wider lip to keep it from slipping too far inside the base. Also, it needs to be deep enough to prevent the umbrella from moving around once it is installed.

I started with a simple cylinder that represents the solid part of the holder that fits into the base.

cylinder(r=25.5, h=45, $fa=1);

Next, I added the wider "lip". For the lip the size was somewhat arbitrary.

cylinder(r=32.5, h=5, $fa=1);
cylinder(r=25.5, h=45, $fa=1);

So far we haven't moved from the origin, so these two cylinders are rendered into exactly the same space. So they overlap a lot. This is OK because we are looking for a single solid piece. However, keeping in mind that we are going to export this to an STL and then "slice" it so it can be built up by a 3D printer one layer at a time, it is better if we explicitly combine the shapes. In OpenSCAD we use "union" to do this:

union() {
    cylinder(r=32.5, h=5, $fa=1);
    cylinder(r=25.5, h=45, $fa=1);
}

So far the model looks like this:

We now need to add the hole in the middle. We do this by subtracting out another cylinder using "difference". This is another reason we needed to do a "union", since we want to subtract out the middle of both cylinders.

difference() {
    union() {
        cylinder(r=32.5, h=5, $fa=1);
        cylinder(r=25.5, h=45, $fa=1);
    }
    cylinder(r=19, h=height, $fa=1);
}

The results are not exactly as desired:

The strange stuff in the middle indicates that we are not subtracting out the whole shape like we want. If we export this to STL and slice it, we may have issues with the slicing or the printer may attempt to put material there.

Instead, we want to extend the "negative" cylinder that subtracts out the center so that it goes past both ends of the model. To do this, we need to start the negative cylinder a little below the origin and extend it a little above. So we need a translation:

difference() {
    union() {
        cylinder(r=32.5, h=5, $fa=1);
        cylinder(r=25.5, h=45, $fa=1);
    }
    translate([0, 0, -5])
    #cylinder(r=19, h=55, $fa=1);
}

The results are much better:

For this image I adjusted the view a little to show the cylinder extending above and below. I also used a nice debug feature -- by adding a hash # to the front of the object, we cause OpenSCAD to draw it in a translucent red color so we can see it. Otherwise it would be transparent since it is subtracted from the rest of the shape.

Up until now OpenSCAD looked very similar to a general-purpose language. Even the use of "union" and "difference" looks like passing a code block to a function. However, now we can see some differences. First, notice that within the "difference" block the order of the child nodes is important. The second object is subtracted from the first, but there's no explicit syntax to show that. Second, notice that the "translate" is not a complete statement. That makes sense because its operation is applied to the cylinder that comes after it, but the syntax is a little different from the method chaining that would be used in a general-purpose language. Finally, the use of a prefix symbol like # only really works in a special-purpose language, because the grammar is simple enough that the parser doesn't get confused.

To complete the model, we can break out the numeric values into variables to improve readability. My final file looked like this:

center = 19;
inner = 25.5;
outer = 32.5;

lip_height = 5;
height = 45;

difference() {
    union() {
        cylinder(r=outer, h=lip_height, $fa=1);
        cylinder(r=inner, h=height, $fa=1);
    }
    translate([0, 0, -5])
    cylinder(r=center, h=height+10, $fa=1);
}

And the final model, exported to STL and loaded into Cura, looks like:

Ready to slice and print, and a few hours later I have the thing in my hands.

Topics:
3d printing ,modeling

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}