Using an External Editor
- Open OpenSCAD
- Select View>Hide Editor
- Select Design>Automatic Reload and Compile
- Select your favorite editor
- If you're using BBEdit or TextWrangler download this plist from Thingiverse:
OpenSCAD and BBedit or TextWrangler - Install the plist in ~/Library/Application Support/your_app/Language Modules.
You might have to create the Language Modules folder.
Introduction
OpenSCAD is software for creating solid 3D CAD objects. It is free software and available for Linux/UNIX, MS Windows and Mac OS X.
OpenSCAD focuses on the CAD aspects of 3D modeling and is good for creating 3D models of machine parts or any part where you want to specify parameters.
OpenSCAD is not an interactive modeller. Instead it reads in statements that describes the object and it renders the 3D model from that code. This gives you full control over the modelling process and enables you to easily change any step in the process or make designs that are defined by configurable parameters.
OpenSCAD provides two main modelling techniques:
- Constructive Solid Geometry
- Extrusion of 2D outlines
Numbers in OpenSCAD are in millimeters. So circle(5); or circle(r=5); draws a circle with a radius of 5mm.
Basics
- If you do not have OpenSCAD installed yet, download the latest Development Snapshot from openscad.org
- When you open OpenSCAD you will see the interface:
- To display the axes in the model view press Command+2 (MAC) or CTRL+2 (Windows and Linux).
- Statements in OpenSCAD end with a semi-colon.
cube([10,10,20]);
- OpenSCAD does not automatically indent your code, but you are encouraged to use indents for readability
difference(){ cylinder(h = 5, r = 20); translate(v=[0,0,-1]) cylinder(h = 7, r = 4); }
- To comment out a single line begin the comment with a double-slash (//)
//this is a comment myVar=10;//this is also a single-line comment
- To comment out multiple lines, begin the comment with slash-star and end the comment with star-slash:
/* This is a multi-line comment. I started the comment on the line above. I will complete the comment on the line below. */
- Press F5 to render. This will show you what your model looks like in the model view
- Press F6 to compile and render. This will create a model that is ready to export as an stl file:
- You can use %(the Background Modifier) to ignore the subtree for the normal rendering process and draw it in transparent gray. In other words to ghost an object. This is handy when you want to see what is being differenced:
- There is also * (the Disable Modifier), which will ignore the entire subtree.
difference() { cylinder (h = 4, r=1, center = true, $fn=100); *rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100); }
- $fn sets the resolution. This can be at the top of your file.
Here is how to set the resolution to 128.$fn=128;
- You can move the rendered object by:
-
Dragging with left mouse button to rotate the view. You can see the rotate values at the bottom of the window.
- Also try dragging with the left mouse while holding down the SHIFT key.
- Dragging with the right mouse button to translate (move) the view. You can see the translate values in the bottom of the window.
- Also try dragging north and south with the right mouse while holding down the SHIFT key.
- Using the mouse scroll to zoom in and out. The Viewport line at the bottom of the window will show a change in the distance value.
- Use the following quick key combinations to control the view:
-
Dragging with left mouse button to rotate the view. You can see the rotate values at the bottom of the window.
- Statements in OpenSCAD end with a semi-colon.
View Options
Show Edges (CTRL/⌘+1)
If Show Edges is enabled, both OpenCSG and CGAL mode will render edges as well as faces, CGAL will even show vertices. In CGAL grid mode, this option has no effect.Enabling this option shows the difference between OpenCSG and CGAL quite clearly: While in CGAL mode you see an edge drawn everywhere it belongs, OpenCSG will not show edges resulting from boolean operations – this is because they were never explicitly calculated but are just where one object's Z clipping begins or ends.
Show Axes (CTRL/⌘+2)
If Show Axes is enabled, the origin of the global coordinate system will be indicated by an orthogonal axes indicator. Additionally, a smaller axes indicator with axes names will be shown in the lower left corner of the viewing area. The smaller axes indicator is marked x, y, z and coloured red, green, blue respectively.Show Crosshairs (CTRL/⌘+3)
If Show Crosshairs is enabled, the center of the viewport will be indicated by four lines pointing in the room diagonal directions of the global coordinate system. This is useful when aligning the viewing area to a particular point in the model to keep it centered on screen during rotation.Animation
The Animate option adds an animation bar to the lower edge of the screen. As soon as FPS and Steps are set (reasonable values to begin with are 10 and 100, respectively), the current Time is incremented by 1/Steps, FPS times per second, until it reaches 1, when it wraps back to 0.Every time Time is changed, the program is re-evaluated with the variable $t set to the current time.
To see how animate works, download spiderbot and run the main.scad files
Primitives
cube
Creates a cube at the origin of the coordinate system. When center is true the cube will be centered on the origin, otherwise it is created in the first octant. The argument names are optional if the arguments are given in the same order as specified in the parametersCube Parameters
sizeSize can be a decimal or a 3 value array. If a single number is given, the result will be a cube with sides of that length. If a 3 value array is given, then the values will correspond to the lengths of the X, Y, and Z sides. Default value is 1.
center
This is a Boolean, so it either set to true or false. This property determines the positioning of the object. If set to true, the object is centered at (0,0,0). Otherwise, the the object is placed in the positive quadrant with one corner at (0,0,0). The default is set to false. Usage examples:
cube(size = 1, center = false); cube(size = [1,2,3], center = true);
sphere
Creates a sphere at the origin of the coordinate system. The argument name is optional.Sphere Parameters
rr is a decimal. This is the radius of the sphere. The resolution of the sphere will be based on the size of the sphere and the $fa, $fs and $fn variables. Usage examples:
sphere(r = 1); sphere(r = 5); sphere(r = 10); sphere(2, $fn=100); // this will create a high resolution sphere with a 2mm radius sphere(2, $fa=5, $fs=0.1); // will also create a 2mm high resolution sphere but this one does not have as many small triangles on the poles of the sphere
cylinder
Creates a cylinder at the origin of the coordinate system. When both radii are same it is also possible to specify a single radius using the argument name r. The argument names are optional if the arguments are given in the same order as specified above.Cylinder Parameters
hh is a decimal. This is the height of the cylinder. Default value is 1.
r1
r1 is a decimal. This is the radius of the cylinder/cone on bottom end. Default value is 1.
r2
r2 is a decimal. This is the radius of the cylinder/cone on top end. Default value is 1.
r
Decimal. The radius of both top and bottom ends of the cylinder. Use this parameter if you want a non-cone shaped cylinder. Default value is 1.
$fa
$fa is angle in degrees
$fs
$fs is angle in mm Usage examples:
cylinder(h = 10, r1 = 10, r2 = 20, center = false); cylinder(h = 10, r1 = 20, r2 = 10, center = true); cylinder(h = 10, r=20); cylinder(h = 10, r=20, $fs=6);
Helpful Tip: The $fn parameter dictates how many facets the circumference of your cylinder will have. A cylinder with 8 facets will look like an octagon and a cylinder with 128 facets would probably look almost perfectly circular. You can make triangles by creating cylinders with $fn=3 or just three facets. This is a quick and simple way to get an equilateral triangle.
cylinder(h=10,r=10,$fn=3, center=true);
polyhedron
Creates a cylinder at the origin of the coordinate system. When both radii are same it is also possible to specify a single radius using the argument name r. The argument names are optional if the arguments are given in the same order as specified above. Usage examples:polyhedron(points = [ [x, y, z], ... ], triangles = [ [p1, p2, p3..], ... ], convexity = N); polyhedron(points=[[0,0,0],[100,0,0],[0,100,0],[0,100,100]], triangles=[[0,1,2],[1,0,3],[0,2,3],[2,1,3]]); polyhedron ( points = [[0, -10, 60], [0, 10, 60], [0, 10, 0], [0, -10, 0], [60, -10, 60], [60, 10, 60]], triangles = [[0,3,2], [0,2,1], [3,0,4], [1,2,5], [0,5,4], [0,1,5], [5,2,4], [4,2,3], ]);
Your First Model
- Open OpenSCAD.
- Type the following into the editor window:
cube([5,5,4]);
- Make sure that when you render, you see the axes. If you do not see them, turn on Show Axes under the View Menu or press Command+2 (MAC) or CTRL+2 (Windows and Linux).
- You should notice that the object is rendered in the first quadrant. By adding center=true to the first statement, you can center the cube on the axes lines:
- To create another cube, you could copy and paste the line of code. You won't see the second cube.
Why not?
You won't see the second cube because both cubes are occupying the same space.
To move the second cube away, you have to call translate().
This line is a bit weird because it doesn't end in a semi-colon.
Why not?
It doesn't have a semi-colon because the translate() call is part of the cube statement:cube([5,5,4]); translate([6,0,0]) cube([5,5,4], center=true);
- color() like translate()
is part of the object statement.
Here is how you would make the second object red:cube([5,5,4]); translate([6,0,0]) color([1,0,0]) cube([5,5,4]);
While the color of your model in OpenSCAD does not determine how your model will print, it is nice to be able to control the colors. To change the color use the following syntax:or//using color names color("name_of_color_from_list_below") cube([5,5,4], center=true);
A chart of the color names is as follows://using RGB values from 0-1.0 color([1,0,0]) cube([5,5,4]);
Purples Lavender Thistle Plum Violet Orchid Fuchsia Magenta MediumOrchid MediumPurple BlueViolet DarkViolet DarkOrchid DarkMagenta Purple Indigo DarkSlateBlue SlateBlue MediumSlateBlue Pinks Pink LightPink HotPink DeepPink MediumVioletRed PaleVioletRed Blues Aqua Cyan LightCyan PaleTurquoise Aquamarine Turquoise MediumTurquoise DarkTurquoise CadetBlue SteelBlue LightSteelBlue PowderBlue LightBlue SkyBlue LightSkyBlue DeepSkyBlue DodgerBlue CornflowerBlue RoyalBlue Blue MediumBlue DarkBlue Navy MidnightBlue Reds IndianRed LightCoral Salmon DarkSalmon LightSalmon Red Crimson FireBrick DarkRed Greens GreenYellow Chartreuse LawnGreen Lime LimeGreen PaleGreen LightGreen MediumSpringGreen SpringGreen MediumSeaGreen SeaGreen ForestGreen Green DarkGreen YellowGreen OliveDrab Olive DarkOliveGreen MediumAquamarine DarkSeaGreen LightSeaGreen DarkCyan Teal Oranges LightSalmon Coral Tomato OrangeRed DarkOrange Orange Yellows Gold Yellow LightYellow LemonChiffon LightGoldenrodYellow PapayaWhip Moccasin PeachPuff PaleGoldenrod Khaki DarkKhaki Browns Cornsilk BlanchedAlmond Bisque NavajoWhite Wheat BurlyWood Tan RosyBrown SandyBrown Goldenrod DarkGoldenrod Peru Chocolate SaddleBrown Sienna Brown Maroon Whites White Snow Honeydew MintCream Azure AliceBlue GhostWhite WhiteSmoke Seashell Beige OldLace FloralWhite Ivory AntiqueWhite Linen LavenderBlush MistyRose Grays Gainsboro LightGrey Silver DarkGray Gray DimGray LightSlateGray SlateGray DarkSlateGray Black - Replace the cubes with the following lines of code and render:
union(){ difference() { cube(30, center=true); sphere(20, $fn=100); } translate([0, 0, -15]) cylinder(h=40, r=13.5); }
- Now add this line to the very beginning:
And re-render:
$fn=64;
union(), difference() and intersection() are examples of boolean operations
union() creates a union of all the child nodes.union() { cylinder (h = 4, r=1, center = true, $fn=100); rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100); }
difference() subtracts the second (and all further) child nodes from the first.difference() { cylinder (h = 4, r=1, center = true, $fn=100); rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100); }
intersection() creates the intersection of all child nodes and keeps the overlapping portion:intersection() { cylinder (h = 4, r=1, center = true, $fn=100); rotate ([90,0,0]) cylinder (h = 4, r=0.9, center = true, $fn=100); }
Exercise
- The following lines of code will create a cylinder 5mm high with a diameter of 40.
An 8mm cylinder is cut out of the center. Notice that the second cylinder has a height of 7 and is translated by -1 on the z-axis. This ensures that the cut is not exactly aligned with the first cylinder and the cut is clean:$fn=64; difference(){ cylinder(h = 5, r = 20); translate(v=[0,0,-1]) cylinder(h = 7, r = 4); }
- Use translate to move the smaller cylinder to the right:
- Cut out another cylinder on the left:
- Create 4 holes:
- Now make this shape:
You'll have to remove a sphere: sphere(r=5,$fn=100); - Compile and Render (F6)
- Export as STL (Design>Export as STL). Save the file when it tells you to.
Modules
A module in OpenSCAD is similar to a macro or function in other languages. Creating a module allows you to easily reuse code and to create parametric models. To define a module:module Name_of_module(param1,param2,...){ //statements... }
You can specify default values in your definition like this:
module house(roof="flat", paint=[1,0,0]){
color(paint)
if(roof=="flat"){
translate([0,-1,0])
cube();
}else if( roof=="pitched"){
rotate([90,0,0])
linear_extrude(height=1)
polygon(points=[[0,0],[0,1],[0.5,1.5],[1,1],[1,0]],paths=[ [0,1,2,3,4] ]);
}else if(roof=="domical"){
translate([0,-1,0])
union(){
translate([0.5,0.5,1])
sphere(r=0.5,$fn=20);
cube();
}
}
}
To use the module:
house(); translate([1,0,0]) house("pitched", [0,1,0]);
Creating a Module
- Open OpenSCAD
- In the editor add code to define the name of a module. The module should be called join_two_points. This module will take the following parameters:
- x1
- y1
- z1
- x2
- y2
- z2
- diameter
- You will use the distance formula to create the value for a variable called length.
Inside the module, create a variable called length and set it to
sqrt( pow(x1 - x2, 2) + pow(y1 - y2, 2) + pow(z1 - z2, 2) );
- Tertiary syntax allows you to test a conditional and assign a value based on the evaluation in one line:
You want to determine if the difference between the y1 and y2 is not 0. If this condition is met than you want to set alpha to the inverse tangent (arctangent) of (z2 - z1) / (y2 - y1).
//if a is less than b then set the string to "hello" //if a is not less than b then set the string to "good bye" ((a<b) ? string="hello": string="good bye");
The arctangent is used to calculate the angles of a right triangle. It will return the angle of the given ratio.
To illustrate arctangent, start with a right triangle with sides a and b. The typical way to use the tangent function is to calculate the ratio of the two non-hypotenuse sides of a right triangle, such as a and b, from the angle (θ) between b and the hypotenuse. This is indicated as tan(θ) = b / a.
arctangent works in the opposite direction; you can use the ratio b / a to find the angle θ, such that θ = atan(b / a).
Create a variable named beta and if x2- x1 does not equal 0 than set beta to 90-atan( (z2 - z1) / (x2 - x1) ) otherwise set it to 90- 0.
- Create a variable named gamma and if x2- x1 does not equal 0 than
set gamma to atan( (y2 - y1) / (x2 - x1)
Otherwise
set gamma to ( (y2 - y1 >= 0) ? 90 : -90 ) ) + ( (x2 - x1 >= 0) ? 0 : -180 )
- To display values of variables, you use the keyword echo
echo(Length = length, Alpha = alpha, Beta = beta, Gamma = gamma);
- Call translate() and translate the object by
x1, y1, z1
- Call rotate() and rotate the object by
0, beta, gamma
- Create a cylinder where the height = length and radius = diameter/2
- To use the module you specify the starting x, y and z and the ending x, y and z:
join_two_points(0, 0, 0, 50, 0, 0, 5 ); // +X join_two_points( 50, 0, 0, 50, 50, 0, 5 ); // -X join_two_points( 50, 50, 0, 0, 50, 0, 5 ); // +Y join_two_points( 0, 50, 0, 0, 0, 0, 5 ); // -Y join_two_points( 0, 0, 0, -50, -50,0, 5 ); // -X -Y join_two_points( 0, 0, 0, 50, 50, 50, 5 ); // +XYZ
- Here is the module to add rounded corners:
module corner(x, y, z, diameter){ translate([x, y, z]) sphere( r = diameter/2 ); }
- This code:
produces this:
diameter=2; cubeHeight=10; width=50; length=50; innerWidth=20; innerLength=10; translate([-25,-25,-10]){ cube([width,length,cubeHeight]); for(z=[0:2]){ perimeter(width,length,cubeHeight+z*diameter,diameter); } translate([(width-innerWidth)/2,(length-innerLength)/2,0]){ for(z=[0:2]){ perimeter(innerWidth,innerLength,cubeHeight+z*diameter,diameter); } } }
- Complete the program by creating the module perimeter.
- View the model by pressing F5.
- Render and Compile by pressing F6. Then select Design>Export as STL
Using Variables
You could rewrite the module so that it would be parametric:module house(roof="flat", paint=[1,0,0], s=20){ color(paint) if(roof=="flat"){ translate([0,-s,0]) cube(s); }else if( roof=="pitched"){ rotate([90,0,0]) linear_extrude(height=s) polygon(points=[[0,0],[0,s],[s/2,3*s/2],[s,s],[s,0]],paths=[ [0,1,2,3,4] ]); }else if(roof=="domical"){ translate([0,-s,0]) union(){ translate([s/2,s/2,s]) sphere(r=s/2,$fn=20); cube(s); } } } house(); translate([40,0,0]) house("pitched"); translate([80,0,0]) house("domical",[0,1,1]); translate([0,40,0]) house(roof="pitched",paint=[0,0,1]); translate([20,20,0]) house(paint=[0,0,0],roof="pitched"); translate([60,40,0]) house(roof="domical"); translate([80,60,0]) house(paint=[0,.5,.2]);
Loops
A for loop is a programming language statement which allows code to be repeatedly executed. Unlike a while loop, the for loop is distinguished by an explicit loop counter or loop variable. You can use a for loop when you can provide the number of iterations. For loops in OpenSCAD allow you to iterate over the values in a vector or range:for (i = [-1, 1]){ translate([0, 0, i]) cube(size = 1, center = false); }
$fn=64; for ( i = [0 : 5] ){ rotate( i * 60, [1, 0, 0]) translate([0, 10, 0]) sphere(r = 10); }
$fn=64; for ( i = [0 : 0.2 : 6] ){ rotate( i * 60, [1, 0, 0]) translate([0, 10, 0]) sphere(r = 1); }
for (i = [0:5]) { echo(360*i/6, sin(360*i/6)*80, cos(360*i/6)*80); translate([sin(360*i/6)*80, cos(360*i/6)*80, 0 ]) cylinder(h = 10, r=10); } for (i = [0 : 0.1 : 6]) { echo(360*i/6, sin(360*i/6)*80, cos(360*i/6)*80); translate([sin(360*i/6)*80, cos(360*i/6)*80, 0 ]) cylinder(h = 10, r=5); }
To simplify your code you can use the assign keyword:
for (i = [10:50]){ assign (angle = i*360/20, distance = i*10, r = i*2){ rotate(angle, [1, 0, 0]) translate([0, distance, 0]) sphere(r = r); } }
Here is an example that uses a module to line up objects by number and space. In order to use this module with an object, you must use child(0). child is referring to the cube() in this example:
module lineup(num, space) { for (i = [0 : num-1]) translate([ space*i, 0, 0 ]) child(0); } lineup(7, 22) cube(20);
If you need to make your module iterate over all children you need to make use of the $children variable
module elongate(){ for (i = [0 : $children-1]){ scale([10 , 1, 1 ]) child(i); } } elongate() { sphere(30); cube([10,10,10]); cylinder(r=10,h=50); }
Another example that uses $children:
//this code is from example018.scad in the application's example directory module step(len, mod) { for (i = [0:$children-1]) translate([ len*(i - ($children-1)/2), 0, 0 ]) child((i+mod) % $children); } for (i = [1:4]) { translate([0, -250+i*100, 0]) step(100, i) { sphere(30); cube(60, true); cylinder(r = 30, h = 50, center = true); union() { cube(45, true); rotate([45, 0, 0]) cube(50, true); rotate([0, 45, 0]) cube(50, true); rotate([0, 0, 45]) cube(50, true); } } }
Libraries
OpenSCAD allows you to create files that contain a series of modules. You can then use one of two keywords use or include to incorporate those modules into another file.Here is an example. member Tony Buser created a scad file called pins.scad. This file contains several modules:
- pinhole(h=10, r=4, lh=3, lt=1, t=0.3, tight=true)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
t = tolerance
tight = set to false if you want a joint that spins easily
- pin(h=10, r=4, lh=3, lt=1, side=false)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
side = set to true if you want it printed horizontally
- pintack(h=10, r=4, lh=3, lt=1, bh=3, br=8.75)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
bh = base_height
br = base_radius
- pinpeg(h=20, r=4, lh=3, lt=1)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
- pin_vertical(h=10, r=4, lh=3, lt=1)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness - pin_horizontal(h=10, r=4, lh=3, lt=1)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
- pin_solid(h=10, r=4, lh=3, lt=1)
Where:h = shaft height
r = shaft radius
lh = lip height
lt = lip thickness
- test()
// Pin Connectors V2 // Tony Buser <tbuser@gmail.com> module test() { tolerance = 0.3; translate([-12, 12, 0]) pinpeg(h=20); translate([12, 12, 0]) pintack(h=10); difference() { union() { translate([0, -12, 2.5]) cube(size = [59, 20, 5], center = true); translate([24, -12, 7.5]) cube(size = [12, 20, 15], center = true); } translate([-24, -12, 0]) pinhole(h=5, t=tolerance); translate([-12, -12, 0]) pinhole(h=5, t=tolerance, tight=false); translate([0, -12, 0]) pinhole(h=10, t=tolerance); translate([12, -12, 0]) pinhole(h=10, t=tolerance, tight=false); translate([24, -12, 15]) rotate([0, 180, 0]) pinhole(h=10, t=tolerance); } } module pinhole(h=10, r=4, lh=3, lt=1, t=0.3, tight=true) { // h = shaft height // r = shaft radius // lh = lip height // lt = lip thickness // t = tolerance // tight = set to false if you want a joint that spins easily union() { pin_solid(h, r+(t/2), lh, lt); cylinder(h=h+0.2, r=r); // widen the cylinder slightly // cylinder(h=h+0.2, r=r+(t-0.2/2)); if (tight == false) { cylinder(h=h+0.2, r=r+(t/2)+0.25); } // widen the entrance hole to make insertion easier translate([0, 0, -0.1]) cylinder(h=lh/3, r2=r, r1=r+(t/2)+(lt/2)); } } module pin(h=10, r=4, lh=3, lt=1, side=false) { // h = shaft height // r = shaft radius // lh = lip height // lt = lip thickness // side = set to true if you want it printed horizontally if (side) { pin_horizontal(h, r, lh, lt); } else { pin_vertical(h, r, lh, lt); } } module pintack(h=10, r=4, lh=3, lt=1, bh=3, br=8.75) { // bh = base_height // br = base_radius union() { cylinder(h=bh, r=br); translate([0, 0, bh]) pin(h, r, lh, lt); } } module pinpeg(h=20, r=4, lh=3, lt=1) { union() { translate([0, -h/4+0.05, 0]) pin(h/2+0.1, r, lh, lt, side=true); translate([0, h/4-0.05, 0]) rotate([0, 0, 180]) pin(h/2+0.1, r, lh, lt, side=true); } } // just call pin instead, I made this module because it was easier to do the rotation option this way // since openscad complains of recursion if I did it all in one module module pin_vertical(h=10, r=4, lh=3, lt=1) { // h = shaft height // r = shaft radius // lh = lip height // lt = lip thickness difference() { pin_solid(h, r, lh, lt); // center cut translate([-r*0.5/2, -(r*2+lt*2)/2, h/4]) cube([r*0.5, r*2+lt*2, h]); translate([0, 0, h/4]) cylinder(h=h+lh, r=r/2.5, $fn=20); // center curve // translate([0, 0, h/4]) rotate([90, 0, 0]) cylinder(h=r*2, r=r*0.5/2, center=true, $fn=20); // side cuts translate([-r*2, -lt-r*1.125, -1]) cube([r*4, lt*2, h+2]); translate([-r*2, -lt+r*1.125, -1]) cube([r*4, lt*2, h+2]); } } // call pin with side=true instead of this module pin_horizontal(h=10, r=4, lh=3, lt=1) { // h = shaft height // r = shaft radius // lh = lip height // lt = lip thickness translate([0, h/2, r*1.125-lt]) rotate([90, 0, 0]) pin_vertical(h, r, lh, lt); } // this is mainly to make the pinhole module easier module pin_solid(h=10, r=4, lh=3, lt=1) { union() { // shaft cylinder(h=h-lh, r=r, $fn=30); // lip // translate([0, 0, h-lh]) cylinder(h=lh*0.25, r1=r, r2=r+(lt/2), $fn=30); // translate([0, 0, h-lh+lh*0.25]) cylinder(h=lh*0.25, r2=r, r1=r+(lt/2), $fn=30); // translate([0, 0, h-lh+lh*0.50]) cylinder(h=lh*0.50, r1=r, r2=r-(lt/2), $fn=30); // translate([0, 0, h-lh]) cylinder(h=lh*0.50, r1=r, r2=r+(lt/2), $fn=30); // translate([0, 0, h-lh+lh*0.50]) cylinder(h=lh*0.50, r1=r+(lt/2), r2=r-(lt/3), $fn=30); translate([0, 0, h-lh]) cylinder(h=lh*0.25, r1=r, r2=r+(lt/2), $fn=30); translate([0, 0, h-lh+lh*0.25]) cylinder(h=lh*0.25, r=r+(lt/2), $fn=30); translate([0, 0, h-lh+lh*0.50]) cylinder(h=lh*0.50, r1=r+(lt/2), r2=r-(lt/2), $fn=30); // translate([0, 0, h-lh]) cylinder(h=lh, r1=r+(lt/2), r2=1, $fn=30); // translate([0, 0, h-lh-lt/2]) cylinder(h=lt/2, r1=r, r2=r+(lt/2), $fn=30); } }
To fix this error you need to call one of the modules:
pintack(10);
To use the pins.scad file in another file
- Save both files in the same directory.
- The first line in your second file should use include or use
include <pins.scad>
If you just want to use a module from one file in another consider using:
use <pins.scad>
MCAD Libraries
If you have downloaded the latest Development Snapshot, the application folder will contain the MCAD library:There are several files within the MCAD folder:
In order to use an MCAD file, you need to specify which file in the first lines of your OpenSCAD file:
use <MCAD/boxes.scad> roundedBox([30, 30, 40], 5, true);
bearing.scad
test_bearing() displays a 608 bearing inside a test_bearing_hole.
test_bearing_hole() displays a a cube (size=[30, 30, 7-10*epsilon] ) to hold a bearing.
bearingDimensions(model) Sets the dimensions for the following bearing numbers. 608 (Skatebearing) is the model default.
608 = [8*mm, 22*mm, 7*mm]
623 = [3*mm, 10*mm, 4*mm]
624 = [4*mm, 13*mm, 5*mm]
627 = [7*mm, 22*mm, 7*mm]
688 = [8*mm, 16*mm, 4*mm]
698 = [8*mm, 19*mm, 6*mm]
bearing(pos=[0,0,0], angle=[0,0,0], model=SkateBearing, outline=false, material=Steel, sideMaterial=Brass)
example
bearing([0,0,10],[90,0,0]);
boxes.scad
roundedBox([width, height, depth], float radius, bool sidesonly)example
roundedBox([20, 30, 40], 5, true)
gridbeam.scad
zBeam(segments) create a vertical gridbeam strut 'segments' longxBeam(segments) create a horizontal gridbeam strut along the X axis
yBeam(segments) create a horizontal gridbeam strut along the Y axis
topShelf(width, depth, corners) create a shelf suitable for use in gridbeam structures width and depth in 'segments', corners == 1 notches corners
bottomShelf(width, depth, corners) like topShelf, but aligns shelf to underside of beams
backBoard(width, height, corners) create a backing board suitable for use in gridbeam structures width and height in 'segments', corners == 1 notches corners
frontBoard(width, height, corners) like backBoard, but aligns board to front side of beams
translateBeam([x, y, z]) translate gridbeam struts or shelves in X, Y, or Z axes in units 'segments'
example
xBeam(3)
metric_fastners.scad
cap_bolt(dia,len)csk_bolt(dia,len)
washer(dia)
flat_nut(dia)
bolt(dia,len)
cylinder_chamfer(r1,r2)
chamfer(len,r)
example
translate([-20,0,0]) csk_bolt(3,14); translate([-10,0,0]) washer(3); translate([0,0,0]) flat_nut(3); translate([10,0,0]) bolt(4,14); translate([-15,-12,0]) cylinder_chamfer(8,1); translate([0,-15,0]) chamfer(10,2);
motors.scad
example
regular_shapes.scad
triangle(radius);reg_polygon(sides,radius);
hexagon(radius);
heptagon(radius);
octagon(radius);
nonagon(radius);
decagon(radius);
hendecagon(radius);
dodecagon(radius);
ellipse(width, height);
egg_outline(width, length);
cone(height, radius, center = false) ;
oval_prism(height, rx, ry, center = false) ;
oval_tube(height, rx, ry, wall, center = false) ;
cylinder_tube(height, radius, wall, center = false) ;
tubify(radius,wall);
triangle_prism(height,radius);
triangle_tube(height,radius,wall);
pentagon_prism(height,radius);
pentagon_tube(height,radius,wall);
hexagon_prism(height,radius) ;
heptagon_prism(height,radius) ;
octagon_prism(height,radius) ;
nonagon_prism(height,radius);
decagon_prism(height,radius);
hendecagon_prism(height,radius);
dodecagon_prism(height,radius);
torus(outerRadius, innerRadius);
triangle_pyramid(radius);
square_pyramid(base_x, base_y,height);
hardware.scad
rod(length, threaded)screw(length, nutpos, washer, bearingpos = -1)
bearing(position)
nut(position, washer)
washer(position)
rodnut(position, washer)
rodwasher(position)
example
rod(20); translate([rodsize * 2.5, 0, 0]) rod(20, true); translate([rodsize * 5, 0, 0]) screw(10, true); translate([rodsize * 7.5, 0, 0]) bearing(); translate([rodsize * 10, 0, 0]) rodnut(); translate([rodsize * 12.5, 0, 0]) rodwasher(); translate([rodsize * 15, 0, 0]) nut(); translate([rodsize * 17.5, 0, 0]) washer();
screw.scad
helix(pitch, length, slices=500);auger(pitch, length, outside_diameter, inner_diameter);
test_auger();
ball_groove(pitch, length, diameter, ball_radius=10);
test_ball_groove();
ball_groove2(pitch, length, diameter, ball_radius, slices=200);
test_ball_groove2();
example
translate([-180,0,0]) auger(100, 300); ball_groove2(100, 300, 100, 10); translate([170,0,0]) ball_groove(100, 300, 10);
triangles.scad
triangle(o_len, a_len, depth)a_triangle(tan_angle, a_len, depth)
example
triangle(5, 5, 5); translate([10,0,0]) a_triangle(30, 5, 5); translate([20,0,0]) a_triangle(60, 5, 5);
teardrop.scad
This script generates a teardrop shape at the appropriate angle to prevent overhangs greater than 45 degrees. The angle is in degrees, and is a rotation around the Y axis. You can then rotate around Z to point it in any direction. Rotation around X or Y will cause the angle to be wrong.teardrop(radius, length, angle)
example
teardrop(10, 10, 60);
stepper.scad
motor(model=Nema23, size=NemaMedium, dualAxis=false, pos=[0,0,0], orientation = [0,0,0])example
rotate([0,180,0]) motor(Nema17);
shapes.scad
box(width, height, depth);roundedBox(width, height, depth, radius);
cone(height, radius, center = false) ;
ellipticalCylinder(w,h, height, center = false);
ellipsoid(w, h, center = false);
tube(height, radius, wall, center = false);
tube2(height, ID, OD, center = false);
ovalTube(height, rx, ry, wall, center = false);
ngon(sides, radius, center=false);
hexagon(size, height);
octagon(size, height);
dodecagon(size, height);
hexagram(size, height);
rightTriangle(adjacent, opposite, height);
equiTriangle(side, height);
12ptStar(size, height);
dislocateBox(w, h, d);
servo.scad
For the Align DS420 digital servoalignds420(position, rotation, screws = 0, axle_lenght = 0)
example
alignds420(screws=1);
involute_gears.scad
bevel_gear_pair ( gear1_teeth = 41, gear2_teeth = 7, axis_angle = 90, outside_circular_pitch=1000)bevel_gear ( number_of_teeth=11, cone_distance=100, face_width=20, outside_circular_pitch=1000, pressure_angle=30, clearance = 0.2, bore_diameter=5, gear_thickness = 15, backlash = 0, involute_facets=0, finish = -1)
nvolute_bevel_gear_tooth ( back_cone_radius, root_radius, base_radius, outer_radius, pitch_apex, cone_distance, half_thick_angle, involute_facets)
gear ( number_of_teeth=15, circular_pitch=false, diametral_pitch=false, pressure_angle=28, clearance = 0.2, gear_thickness=5, rim_thickness=8, rim_width=5, hub_thickness=10, hub_diameter=15, bore_diameter=5, circles=0, backlash=0, twist=0, involute_facets=0, flat=false)
gear_shape ( number_of_teeth, pitch_radius, root_radius, base_radius, outer_radius, half_thick_angle, involute_facets)
involute_gear_tooth ( pitch_radius, root_radius, base_radius, outer_radius, half_thick_angle, involute_facets)
example
gear (circular_pitch=700, gear_thickness = 12, rim_thickness = 15, hub_thickness = 17, circles=8);
Polygons
You can create customized polygons in OpenSCAD by specifying points and paths. The path is either a single vector, enumerating the points in a list and the order to traverse the points, or, a vector of vectors, ie a list of point lists for each seperate curve of the polygon. You would need to use a vector of vectors if your polygon has holes. The parameter is optional and if you omit it OpenSCAD assumes that the points are in order. syntax:polygon(points = [ [x, y], ... ], paths = [ [p1, p2, p3..], ...], convexity = N);
polygon(points=[[0,0],[100,0],[0,100],[10,10],[80,10],[10,80]], paths=[[0,1,2],[3,4,5]]);
In order to get a 3D object, you either extrude a 2D polygon (linear or (rotation ) or directly use the polyhedron primitive solid. When using extrusion to form solids, its important to realize that the winding direction of the polygon is significant. If a polygon is wound in the wrong direction with respect to the axis of rotation, the final solid (after extrusion) may end up invisible. This problem can be checked for by flipping the polygon using scale([-1,1]) (assuming that extrusion is being done about the Z axis as it is by default).
Working with Polygons in OpenSCAD can get confusing, but there are some helper applications that can simplify the proces for you.
Click on the links below to explore each option:
- Create your polygons in Inkscape or import svgs into Inkscape and export your shapes with an extension
- Use OpenSCAD Polygon Generator
OpenSCAD Polygon Generator
The Polygon Generator is a visual helper for generating polygons. The application was written by member PieterBos in Action Script 3.0 and is a small air app. The application does not have any undo functionality and you can only draw on a grid. To use this application, download PolygonHelper.air.-
Download the PolygonHelper.air application from Thingiverse by clicking here.
- Install and open the application.
- Click on the Add Point Mode to begin
- Click on the green dot if you want your polygon to begin at the central axis point
- Click on the grid to make the next point:
- Continue to add nodes. When you want to finish the shape click back on the first point.
- You can add holes by clicking on the Add Point Mode and creating another closed shape:
- You can continue in this manner to create more holes:
- When you want to export click on the save button and name it. This file will automatically be saved in the scad directory in your Documents directory
- Just exporting it will create a 2D polygon in OpenSCAD:
- You can also save an extruded shape. Click on Extrude and Rotate:
- Or click on Extrude, Linear and supply a value to extrude by:
Inkscape and OpenSCAD extension
- Download the src file for the inkscape-openscad-poly extension.
- Copy the contents of the src directory to your Inkscape extensions/ directory.
Typical locations for the extensions folders include:
- OS X - Applications:Inkscape.app:Contents:Resources/extensions
- Linux - /usr/share/inkscape/extensions
- Windows - C:\Program Files\Inkscape\share\extensions
- Open Inkscape (www.inkscape.org — free, open-source vector based drawing program ) and create a new document (CTRL+N).
- Under the file menu, go to Document Properties and change the default units in the upper right hand corner to millimeters (SHIFT+CTRL+D). This will change the rulers from pixels to millimeters.
- Create a drawing
- There should be square and round handles on the object, which indicates the drawing is an .svg object.
- You need to convert the drawing object to a path. [Shift+Ctrl+C]
- Select the node tool [N]. The handles on the object now look like gray squares. This indicates you have a path.
- Select every node (CTRL+A), and click on Insert new nodes into selected segments.
Press a few times if you want a smoother object, but don't overdo it. - With all the nodes still selected, click on the straighten segments. The lines are straight, but due to the sheer numbers, you see a curve!
- Select everything, then go to Document Properties [Shift+Ctrl+D] and click on Resize page to content:
- Click on Resize page to drawing or selection.
Don't panic if your dots seem like they are outside the page, it will all be fine in the end. - Navigate to File>Save As (SHIFT+CTRL+S) and save the drawing.
- You want to save the drawing as as OpenSCAD Polygons
- Open the file in OpenSCAD
- Before the module definition, include a call to linear_extrude:
syntax:
example:
linear_extrude(height=xx) pathxxxx();
linear_extrude(height=4){ path3001(); }
- Compile (F5)
Importing an SVG into Inkscape.
- Find an svg file you'd like to use.
I'm downloading a kiwi bird from:clipartist - Open Inkscape
- Navigate to File>Open (CTRL+O) and find your SVG
- Under the file menu, go to Document Properties and change the default units in the upper right hand corner to millimeters (SHIFT+CTRL+D). This will change the rulers from pixels to millimeters.
- Change the Fill to No Fill and set the stroke so that you can see the image:
- You need to convert the drawing object to a path. [Shift+Ctrl+C]
- Select the node tool [N]. The handles on the object now look like gray squares. This indicates you have a path.
Select every node (CTRL+A), click on Insert new nodes into selected segments.
Press a few times if you want a smoother object, but don't overdo it. - Set the segments to straight lines:
- Select everything, then go to Document Properties [Shift+Ctrl+D] and click on Resize page to content:
- Click on Resize page to drawing or selection.
Don't panic if your dots seem like they are outside the page, it will all be fine in the end. - Navigate to File>Save As (SHIFT+CTRL+S) and save the drawing.
- You want to save the drawing as as OpenSCAD Polygons
- Open the file in OpenSCAD
- Before the module definition, include a call to linear_extrude:
syntax:
example:
linear_extrude(height=xx) pathxxxx();
linear_extrude(height=4){ path3001(); }
- Compile (F5)
- Change the name of your module to something that makes sense:
Importing STL files
- Open a new document in OpenSCAD
- The import_stl() function takes two parameters:
- a file name
- convexity, which specifies the maximum number of front sides a ray intersecting the object might penetrate. This parameter has no effect on the polyhedron rendering, but is necessary in the OpenCSG preview.
stl_import("example.stl",convexity=5);