OpenSCAD tutorial
intro
OpenSCAD is advertised as The Programmers Solid 3D CAD Modeller. First released in 2001, it has a very active developing community on github and is used a lot for parametric design of parts and components, for example on thingiverse. Some of the strong points of OpenSCAD:
- relatively small package (21MB)
- file storage in plain text
- parametric design by default
- open source, multiplatform
- export directly to printable STL
- import of STL, vector drawings
downside:
- no easy ‘mating’ of assemblies
- no easy tooling for chamfered edges and complex shapes.
The first one of these downsides is one of the most powerful strong points in SolidWorks (and other CAD packages). In the following example (eye mechanism) all the parts are separate modules, for an assembly they have to be positioned by manually assigning the correct position. For single parts, parametric components (think gears, pulleys, LEGO bricks) it works very well.
Getting Started
A bottom-up level to get started is just following the manual (tutorial) - or better, the cheatsheet which I still use at every occasion. A top-down approach would be to go to thingiverse (or OpenSCAD website), download an example, try out and reverse-engineer.
For this tutorial the simplest useful shape I can think of: a rectangular box:
difference(){ //substract second shape from first shape
cube([50,60,20]);
translate([2,2,2])cube([46,56,20]);
}
I start often like this: shapes with hard-coded values. Also very often the modifier you start with is a difference()
of two shapes. After the ‘preview’ you need to render the drawing (takes a bit longer) in order to be able to save it as *.stl file.
Now, the function drawing the box (like c code) can take parameters. You can declare them ‘global’ at the top of the code, or pass them in the function:
width = 60;
depth = 50;
height = 20;
difference(){ //substract second shape from first shape
cube([width,depth,height]);
translate([2,2,2])cube([width-4,depth-4,height]);
}
Passing everything as parameters (variables) in the function would give the following, (setting also the wall thickness, a very useful parameter for things you’ll print. Also, it might be better to set the INSIDE size rather than outside size of a box)
box(50,60,20,2); // make a box with width, depth, height, wall thickness
module box(width, depth, height, wall){
difference(){ //substract second shape from first shape
cube([width+2*wall,depth+2*wall,height+wall]);
translate([wall,wall,wall])cube([width,depth,height+2*wall]);
}
}
The next very useful command is a hull
. This will create an envelope of a set of shapes, and is the next best thing OpenSCAD can do towards rounded edges or organic shapes. The following box function uses a hull around 4 cylinders instead of a box:
module box(width, depth, height, wall){
difference(){ //substract second shape from first shape
hull(){
translate([0,0,0])cylinder(h=height,r=wall);
translate([width,0,0])cylinder(h=height,r=wall);
translate([width,depth,0])cylinder(h=height,r=wall);
translate([0,depth,0])cylinder(h=height,r=wall);
}
translate([0,0,wall])cube([width,depth,height+2*wall]);
}
}
When using cylinders and spheres in OpenSCAD it makes sense to set the rendering resolution (or number of segments in a circular shape), in order to reduce rendering time. You can do this by setting the $fn = 40;
function at the top of the code.
Workflows
The VScode plugin
The VScode plugin for OpenSCAD offers syntax highlighting and function completion (and all the other nice features). It also adds three buttons to the top-bar for rendering your design (for which a separate OpenSCAD window will be opened).
The plugin:
Saving the *.scad code in VSCode will sync it with the OpenSCAD instance (which you have to have running in the background):
The separate renderwindow will open when one of the buttons for preview or render is pressed:
importing STL
A very useful function for (for example) making a well fitting enclosure for your electronic design is the option to import an *.stl file. In the following example a board design (rendered using KiCAD, the STEP file converted using FreeCAD to an *stl file). With the instruction:
color("white")translate([-24.5,77,4])import("board.stl",convexity = 10);
an STL file is imported, placed at the right spot (convexity is necessary to set for complex shape rendering). In this case color("white")
will render the entire STL white.
3D shape to 2D
The magic command here is projection
. The following example takes a simple 3D shape of an elliptic lamp shade:
module lampshade() difference(){
scale([1,1,0.5])sphere(150);
scale([1,1,0.55])sphere(130);
translate([0,0,-75])cylinder(d=40,h=200);
//translate([-200,-200,-200])cube([400,200,400]);
}
This function is put into a projection ’loop’ which will shift the shape ’through’ the x-y plane and draws its outline (projected shape). This drawing could be exported as *.svg file and cut on a laser (more programming would be neede to make automatic laset-bed-size design files):
module slice(){
for(i=[-75:8:75])
translate([i*40,0,0])
rotate([0,0,i*15])
projection(cut=true)
translate([0,0,-i])
lampshade();
}
Similar to the ’lampshade’ shape, also an *.stl file of any object could be sliced and made into a cuttable drawing. The drawing (without the 3D shape) can indeed be exported as *.svg for cutting:
2D to 3D
A common workflow in Fusion360 and other packages is to make a 2D drawing as basis, which is subsequently extruded and processed further. Complex shapes, such as aluminum extrusion profile would take quite long to model using cylinders and boxes. A different workflow is the following:
For an aluminum extrusion profile, I take a (fairly random, sharp looking) drawing from an image search, in this case a *.jpg file:
I open this file in inkscape:
trace the bitmap in inkscape path menu -> trace bitmap
,
scale and adjust color (so it is now a line drawing) and save as *.svg file.
With the following line the file can now be used as extrusion template:
linear_extrude(height = 100, center = true, convexity = 10)
import(file = "profile.svg");
Note: in some situations (i.e. older versions of inkscape/OpenSCAD) sizes used in the *.svg might not correspond to the sizes used in OpenSCAD. This might be a whole metric-imperial-pixel-locale settings thing.
Also, when using a file to extrude or save, it is best to save the *.scad file in the same directory (or save it somewhere you can easily use relative paths)
Other resources
-
openjscad: online parametric modelling
-
tinkercad offers similar programming style (but more ‘scratch’ like)
-
you can ask chatGTP for openSCAD scripts:
could you provide me an scad script for an enclosure for an Arduino board
results in the following script (which is really simple, but might do the trick):
// Arduino Enclosure
// Dimensions of the Arduino Uno board
arduino_width = 68.6;
arduino_length = 53.4;
arduino_height = 11.8;
// Add some clearance for the board
clearance = 2;
// Dimensions of the enclosure
enclosure_width = arduino_width + 2 * clearance;
enclosure_length = arduino_length + 2 * clearance;
enclosure_height = arduino_height + clearance;
// Create the enclosure
difference() {
// Outer shell
cube([enclosure_width, enclosure_length, enclosure_height]);
// Subtract the space for Arduino board
translate([clearance, clearance, 0])
cube([arduino_width, arduino_length, arduino_height]);
}