Skip to content

Latest commit

 

History

History
917 lines (635 loc) · 32.9 KB

part1.adoc

File metadata and controls

917 lines (635 loc) · 32.9 KB

An Introduction to OpenSCAD

What is OpenSCAD?

Pronounced “open-ess-cad,” according to the OpenSCAD web site.

OpenSCAD is a constructive geometry 3D modeling program. It is less popular than some other 3D modeling tools such as FreeCAD, SketchUp, or Blender, but has some advantages for creating 3D part designs:

  • Parts are created by writing a script, not with the mouse. This makes some things easier for part design, but other things harder.

  • Can create libraries of part designs for others to use. Or use existing libraries such as MCAD.

  • Parts can be parameterized to make then easy to customize.

  • It’s harder, in general, to create a non-solid model than with some other 3D modeling tools—​important when 3D printing.

  • Good for designing CAD models, bad for artistic modeling.

First Steps

Installing OpenSCAD

The latest release of OpenSCAD, as of this writing, is 2015.03-1. Download OpenSCAD from the OpenSCAD web site, http://www.openscad.org/downloads.html. There are installers for Windows, a DMG for OS X, and instructions for various Linux distributions.

The OpenSCAD Window

When you start OpenSCAD a window will appear with three panes, an editor for modifying your OpenSCAD script, a view to display your 3D model, and a console for information and error messages.

OpenSCAD window

Your First Model

In the editor window, enter this (very small) script and press F5 to render the object in the view pane. You can instead press the preview button asciidoc-test, which is the same as pressing F5, or use the menu option Design > Preview. After you have saved the file once, updating the preview is automatic as soon as the file is saved.

cube();

You should then see a small cube shown in the view:

Cube image

Manipulating the View

The cube is 1x1x1, which is quite small. Zoom the view using the zoom button Zoom button, or press the zoom all button Zoom-all button to adjust the view to match the size and position of your model. You can also use the mouse wheel or a zoom gesture on your touchpad. All of the commands that affect the view are in the View menu as well.

Clicking and dragging in the view rotates the axes around so you can see all sides of your model. By default the origin is in the center of the view, and the view rotates around the origin. You can drag the view laterally without rotation by Ctrl-click and drag. After that the view rotates around the new center of the view, rather than the origin. There are also buttons below the view panel for choosing particular eye positions, such as top, right, and so on.

The Structure of OpenSCAD Scripts

The use of cube(); above demonstrates 2 things about the structure of OpenSCAD scripts.

  1. cube() is an example of a predefined OpenSCAD module. In this case it is what is called an object module, because it creates 3D objects. The parentheses are required when invoking a module.

  2. The whole line—​with the semicolon—​is an example of an OpenSCAD action. (We would probably call it a statement in another language.) OpenSCAD scripts consist of a number of actions. Each action may span multiple lines but must end in a semicolon (or sometimes be wrapped in braces: { and }).

Sizing the Cube

We obviously don’t want cubes of only one size. We can also create cuboids where the sides have different lengths.

cube(size=[10, 5, 8]);

This produces a cuboid of size 10 units on the X axis, 5 units on the Y axis, and 8 units on the Z axis.

Sized cubeoid

Coordinate System

OpenSCAD is usually used to create STL files for 3D printing. STL files do not have a way to indicate a physical measurement to correspond to a unit of 1 in the STL file. Instead, the 3D printing or slicing program will have an option to specify whether to interpret the STL units as millimeters, tenths of inches, or some other measure.

I usually design parts using millimeters, a practice that appears to be common among others using OpenSCAD, but you can make your own decision how to handle units of measure.

The coordinate axes follow the right-hand rule where the arrangement of your thumb and first two fingers on your right hand match the X, Y, and Z axes, respectively.

Right-hand coordinate system

Parameters to Modules

The addition of size=[10, 5, 8] is an example of passing a parameter to a module in order to modify what object it creates. The cube() module takes these parameters:

size

Either a single number or a vector of three numbers giving the X, Y, and Z dimensions. If you supply a single number, it will be used for all three dimensions.

center

If true, the center point of the cuboid will be at the origin. If false or omitted, a corner of the cuboid will be at the origin.

Creating a cuboid with and without centering:

Centered cuboid

Cuboid not centered

Parameters in OpenSCAD work a little differently than parameters in some other languages.

  • They may be omitted if there is a default value. For cube(), for example, center defaults to false and size defaults to 1.

  • They have names which may be provided. If they are not provided, then the parameters need to be in the right order. cube() expects size first, and center second, so cube(size=[10, 5, 8]) and cube([10, 5, 8]) are equivalent.

  • If you use the parameter names, you can specify the parameters in any order.

  • Some parameters may take values of different types. cube() allows size to be a number or a vector, for example.

  • You can specify parameters the module does not expect. These will be silently ignored. (A bad design decision, IMHO, but probably caused by the handling of special variables--see below.)

Based on these characteristics of parameters, all of these actions are equivalent ways to create a 10x5x8 cuboid:

cube(size=[10, 5, 8]);
cube([10, 5, 8]);
cube([10, 5, 8], false);
cube(center=false, size=[10, 5, 8]);
cube(size=[10, 5, 8], false);
cube([10, 5, 8], center=false);

Note that the only way to specify center first is to include the names of both parameters.

Data Types in OpenSCAD

In the examples above, we see three different types of values that can be specified as parameters.

numbers

In OpenSCAD these are always floating-point numbers. IEEE784 representation is used, giving about 17 digits of precision.

vectors

Vectors are sequences of values enclosed in the square brackets [ and ], and separated by commas. Vectors can hold items of any type, including other vectors: [[1, 2, 3], [4, 5, 6]]

boolean values

true and false are built-in boolean constants. There are also operators which give boolean results.

In addition, OpenSCAD supports string values enclosed in double quotes.

"hello"

Some of the standard escape sequences are valid, including \", and also the ability to specify Unicode code points using hexadecimal, such as \u201D.

"this is a string with a quote \" in the middle"

More View Manipulations

Now that we have a cuboid that has differing edge lengths, we can tell the difference between a view from a different side. There are six standard viewpoints to look down each axis in either direction, right, top, bottom, left, front, and back. These are all available in the View menu, or you can use the buttons below the view pane:

Six standard viewpoints

Clicking and dragging the mouse rotates the view about the point in the center of the view, by default the origin. You can instead drag the view left or right by Ctrl-click and drag, or by dragging with the right mouse button. If you want to center the axes in the view again, press the “reset view” button Reset view button.

By default the view shows a perspective projection. That is, a 2-dimensional view of the 3D scene in which objects in the view seem smaller as they recede away. To see this, zoom the view so that the cube takes up much of the area of the pane. Notice that the edges of the cube converge toward a vanishing point.

A perspective view is not always the best, because it makes it more difficult to determine whether object edges coincide. An alternative view is an orthogonal view, which can be selected via the menu by View > Orthogonal or by pressing the Orthogonal view button.

Exercise 1

  1. Create a cuboid that is 20 units long in the X direction, 3 in the Y direction, and 6 in the Z direction.

  2. Modify your use of the cube() module to center the cuboid around the origin.

  3. Rotate the view around using the mouse so that the narrow end of the cuboid is pointing toward you, but you can still see the top face of the object.

  4. Zoom the view so you can see that the edges of the cuboid parallel to the X axis converge to a vanishing point.

  5. Change the view to an orthogonal projection so that the edges now are parallel and don’t converge to a vanishing point.

  6. Use the buttons to select each of the 6 standard views.

  7. Use Ctrl-click and drag to move the view around laterally, without rotation.

  8. Reset the view back to a diagonal viewpoint.

Manipulating Objects

To place objects somewhere other than the origin, you use the translate() module. For example, this code offsets a cuboid so that it sits on the X-Y plane, but 10 units along the X axis and 5 along the Y axis.

translate(v=[10, 5, 0]) {
  cube(size=[20, 3, 6]);
}
Translated cube

The translate() module is our first example of what OpenSCAD calls an operator module, one which does not produce 3D objects, but modifies how other objects are rendered. translate() takes a single argument v which is a vector of the distances along the X, Y, and Z axes to offset the objects it is modifying. The objects to be offset are placed inside braces, { and }. If there is only one module to be operated on, the braces can be omitted. This script is equivalent to the one above:

translate([10, 5, 0])
cube(size=[20, 3, 6]);

In this case the parameter name v has also been omitted. Some will indent the second line:

translate([10, 5, 0])
    cube(size=[20, 3, 6]);

I tend not to indent unless using braces to wrap the target objects, since multiple operators may be combined, and I find the resulting indentation makes the script harder to read.

OpenSCAD Coding Style

OpenSCAD is a language similar in syntax to C and Java. For that reason, using a writing style similar to what you might use in C or Java makes sense. The rest of the examples herein will use these rules. But they are my rules, not necessarily what you will see in other OpenSCAD scripts.

  • Opening braces will be on the same line as the operator they follow.

  • If braces are used to surround the operands of an operator module, the contents inside the braces will be indented. The default indent amount in the OpenSCAD editor is four spaces, but you can change this in the preferences dialog. I find two spaces is sufficient.

  • If braces are not used to surround the operand of an operator module, the operand will use the same level of indentation as the operator.

  • The parameter name will be omitted if a module takes a single parameter and included otherwise.

Drawing Multiple Objects

To draw more than one object, just put the actions one after anohter. For example, this draws a wall with an entranceway.

cube(size=[8, 2, 6]);

translate([12, 0, 0])
cube(size=[8, 2, 6]);

translate([18, 0, 0])
cube(size=[2, 20, 6]);

translate([0, 18, 0])
cube(size=[20, 2, 6]);

cube(size=[2, 20, 6]);
Walled enclosure

Getting Help

The OpenSCAD documentation is viewable in a web browser. There are links in the Help menu to launch a browser window to the help pages. The most important of these links are:

Help > Cheat Sheet

This launches a quick-reference page of all the modules and functions—​we haven’t talked about those yet—​available. The documentation on each is usually quite good. All the parameters are explained, usually with examples.

Help > Documentation

This launches a menu of available documentation, including the OpenSCAD language reference. The language reference has information on some topics, such as data types, which are not listed on the cheat sheet.

Exercise 2

  1. Draw an arch using three cuboids, like the image below. Make the two uprights and the crossbar have the same cross-section, and the overhang of the crossbar the same on each end. (The exact dimensions aren’t important.)

    Pi-shaped arch

  2. Manipulate the view to see each side, to make sure the arch is symmetric.

  3. Modify the crossbar so there is no overhang past the upright posts.

  4. Move the uprights closer together. Make sure the crossbar stays flush with the uprights at each end.

  5. Use the OpenSCAD cheat sheet to look at the documentation on the scale() operator module. Use scale() to double the size of your arch. Hint: Use braces, { and }, to group together what you want to scale.

Debugging Help—​Drawing Highlighted and Transparent

Different objects in your scripts can blend together in the 3D view, making it more difficult to figure out what is wrong if your model isn’t exactly right. There are two prefix characters you can prepend to an object to cause it to be drawn specially, enabling you to see better how the parts fit together.

#: Highlight—​draw an object in a translucent red so it stands out.

%: Transparent—​draw an object in a translucent gray so you can see through it. This also omits the object from the rendered STL file.

An example: here is a solution to the arch problem drawing one upright transparent and the other highlighted.

%translate([5, 0, 0])
cube(size=[5, 5, 15]);

#translate([20, 0, 0])
cube(size=[5, 5, 15]);

translate([0, 0, 15])
cube(size=[30, 5, 5]);

Highlight and transparent modifiers

Parameterizing Your Model

Narrowing the arch or removing the overhang required modifying multiple numbers in the script. OpenSCAD allows you to create variables to avoid hard-coding numbers.

Variables are assigned anywhere in your script. Variable names are similar to C++ or Java identifiers. As an example, here is a small script that uses a variable.

cubeSize = [10, 3, 6];

cube(size=cubeSize, center=true);

The variable cubeSize is defined in an action of the form variableName = value;. Variables can take on values of any OpenSCAD data type. Here, the cubeSize variable takes on a vector value.

There are some differences between OpenSCAD variables and those you may be familiar with in other languages.

  • Variables may only be assigned once. That is, they are essentially constants. The last value assigned in the script takes precedence. (Exceptions: New lexical scopes allow redefinition, and command-line definitions can take precedence over script definitions.)

  • Variables are untyped. Instead, they take on the type of the value assigned to them.

You may define as many variables as you like. Variables may be used in expressions to define parameter values.

Note
Because variables cannot be redefined, you will never see x = x+1 in an OpenSCAD script.

Comments

You can also add comments to a script using either of the C++ comment styles: // introduces a single-line comment, while /* and */ bracket either single-line or multi-line comments. There are also commands in the Edit menu to comment or uncomment selected sections in your script.

Expressions

Variables and values can be combined in arithmetic expressions to form new values. The expression syntax is very similar to C++, Java, and other languages.

As an example, here is a sample solution to the arch problem that uses four variables.

// Cross-sectional size of the uprights and crossbar.
blockWidth = 5;

// Width between the two uprights.
uprightSeparation = 10;

// Amount the crossbar extends beyond the uprights.
crossbarOverhang = 3;

// Height of the uprights. The bottom of the crossbar is at this height.
uprightHeight = 15;

translate([crossbarOverhang, 0, 0])
cube(size=[blockWidth, blockWidth, uprightHeight]);

translate([crossbarOverhang + blockWidth + uprightSeparation, 0, 0])
cube(size=[blockWidth, blockWidth, uprightHeight]);

translate([0, 0, uprightHeight])
cube(size=[2*crossbarOverhang + 2*blockWidth + uprightSeparation, blockWidth, blockWidth]);

Pi-shaped arch

Solving problem 4 in exercise 2 requires eliminating the overlap and reducing the upright separation. This can be effected by modifying two variable definitions without touching the rest of the script. Or, you can run OpenSCAD from the command line, specify new values for these variables, and render an STL file, all in one step.

uprightSeparation = 5;
crossbarOverhang = 0;
Narrow arch

More Operators and Objects

Creating only rectilinear objects is a little boring. OpenSCAD allows creation of more object types and more operators to modify their rendering.

Rotation

The rotate() operator performs rotations on its target objects. There are several ways to perform rotations.

rotate(a=angle)

Rotates a given amount, in degrees, around the Z axis.

rotate(a=[xAngle, yAngle, zAngle])

Rotates a given amount, in degrees, around the X, Y, and Z axes, in turn.

rotate(a=angle, v=[x, y, z])

Rotates a given amount, in degrees, around an arbitrary vector.

All rotation amounts are in degrees and follow a right-hand rotation rule: if you point your right thumb toward the positive direction of the axis or vector around which you want to rotate, your fingers curl in the direction of positive rotation. Negative degrees rotate in the opposite direction.

Right-hand positive rotation

The most common operation is to rotate around a single axis. Here is an oblong cuboid in its original position and rotated 45 degrees around each axis.

separation = 20;
cubeSize = [10, 5, 2];

cube(cubeSize);

translate([separation, 0, 0])
rotate(a=[45, 0, 0])
cube(cubeSize);

translate([0, separation, 0])
rotate(a=[0, 45, 0])
cube(cubeSize);

translate([0, 0, separation])
rotate(a=[0, 0, 45])
cube(cubeSize);
Rotated cuboids

This example shows two operators being applied, rotation and translation. They are applied last to first--that is, here the rotation is applied first, then the translation. You will get different results if you reverse the order, as this example shows.

Rotation first Translation first

translate([20, 0, 0])
rotate(a=[0, 0, 45])
cube(size=[10, 5, 2]);

Rotation first

rotate(a=[0, 0, 45])
translate([20, 0, 0])
cube(size=[10, 5, 2]);

Rotation first

You will probably seldom use the option to rotate around an arbitrary vector. One example of when it might be useful is rotating a cube around an axis through corner points, like this. (The view has been rotated to make it easier to see the result.)

rotate(a=60, v=[1, 1, 1])
cube(size=10);
Twirled cube

More Objects

Drawing cuboids is getting boring, so let’s learn some more objects.

Spheres

sphere(r=radius)

Creates a sphere of a given radius, centered around the origin.

sphere(d=diameter)

Creates a sphere if a given diameter, centered around the origin.

Cylinders

cylinder(r=radius, h=height, center=true|false)

Creates a cylinder of given radius and height, either sitting on the X-Y plane or centered around the origin. In either case the height is in the Z direction.

cylinder(d=diameter, h=height, center=true|false)

Creates a cylinder of given diameter and height.

cylinder(r1=radius1, r2=radius2, h=height, center=true|false)

Creates a conical object that has differing top and bottom radii. This can be used to create cones or truncated cones.

cylinder(d1=diameter1, d2=diameter2, h=height, center=true|false)

Creates a conical object that has differing top and bottom diameters. This can be used to create cones or truncated cones.

The example below creates a dumbell shape along the X axis.

sphereSize = 6;
barRadius = 2;
barLength = 25;

sphere(r=sphereSize);

rotate([0, 90, 0])
cylinder(r=barRadius, h=barLength);

translate([barLength, 0, 0])
sphere(r=sphereSize);
Dumbell shape

Making Rounder Objects

You can see in the example above that the cylinder isn’t very “round”--it only has seven sides! And the spheres have obvious facets. OpenSCAD does not really render curves. Instead, it creates triangular faces which approximate the curved surface. If you want more smoothness you need to modify how OpenSCAD chooses the number of faces to generate. There are three variables controlling the smoothness of round surfaces.

$fs

The maximum length of an edge.

$fa

The maximum angle spanned by a single face.

$fn

The number of faces to use around a curve.

You never use all three. Instead, you should either set both $fs and $fa (preferred) or use $fn. As well, $fs and $fa are used together by OpenSCAD, taking the larger of the two values for each face. Let’s say we want the faces approximating our curved surfaces to take no more than 8 degrees of arc, or .5 units of length, whichever is larger. Just add these two lines to the top of the script, and the result is much smoother.

$fs = .5;
$fa = 8;
Smooth dumbell

Using very small values of $fs and $fa can make rendering much slower, especially when creating STL files, so you should match them to the precision needed in your final printing. The settings above change the STL rendering on my machine from almost instantaneous to 4 CPU-seconds. You may have to print a sample or two before you figure out the right settings.

You can also specify the variables on single objects instead. The two cylinders created by this script use faces that span 10 and 20 degrees of arc, respectively.

cylinder(r=5, h=10, $fa=10, $fs=.5);

translate([15, 0, 0])
cylinder(r=5, h=10, $fa=20, $fs=.5);
Cylinders of differing precision

The other variable, $fn, is most useful when you want to fix the number of faces around a curve. For example, the following script generates a hexagonal prism, not a cylinder.

cylinder(r=5, h=10, $fn=6);
Hexagonal prism

Writing STL Files

For most people, the rendering in OpenSCAD is not the end goal. Instead, they want to take the model and print it on a 3D printer. For that purpose, you have to render the model to a mesh of triangular faces, and then export that rendering as STL.

First, press the render button, Button to render the model, or press F6. If you have a model with curves, and you are using small values for $fs and $fa, this can take some time. After the rendering is complete, you can export to STL by using the STL export button, STL export button, or by selecting File > Export > Export as STL…​ in the menu.

Exercise 3

  1. Write a script to create a (somewhat crude) chess pawn something like this. The exact dimensions aren’t that important. Use variables to control the various dimensions rather than hard-coding numbers.
    Chess pawn

  2. Modify the values of $fs and $fa to make the model smoother. Render the model by pressing the render button or F6. Notice that small values of $fs and $fa can make rendering very slow.

  3. Choose values for $fs and $fa that you think are appropriate for printing on a 3D printer. (Make your best guess.) Render the model and then export to an STL file. Look at the file in a text editor, if you know how. It should start something like this:

    solid OpenSCAD_Model
      facet normal 0.996195 0.0871558 0
        outer loop
          vertex 12.5 0 5
          vertex 12.3101 2.1706 0
          vertex 12.3101 2.1706 5
        endloop
      endfacet
    ...
  4. How would you change the conical shaft of the pawn into a tapered octagonal shaft?

  5. Modify the variables used in the model to make the base and collar wider while making the shaft narrower. Did you do a good job parameterizing your model to make it easy to customize?

Boolean Operations

So far we have built up models by combining primitive objects and operators. We have, then, created a union of multiple objects. Union is an example of a boolean operator. OpenSCAD also supports two other boolean operations, intersection and difference. The last of these, difference, is probably the most important, because it lets you create holes in other objects.

Script Result
union() {
    cube(size=[10, 10, 3], center=true);
    cylinder(r=2, h=12, center=true, $fs=.5);
}

Union of two objects

intersection() {
    cube(size=[10, 10, 3], center=true);
    cylinder(r=2, h=12, center=true, $fs=.5);
}

Union of two objects

difference() {
    cube(size=[10, 10, 3], center=true);
    cylinder(r=2, h=12, center=true, $fs=.5);
}

Union of two objects

Pitfalls When Making Holes

Union and intersection are straightforward to use and won’t cause problems when rendering. Difference, however, can cause problems in the model that mess up the preview, or even mess up the STL file. The script below shows the problem.

difference() {
	cylinder(r=5, h=5);

	translate([0, -8, 0])
	cube(size=[8, 8, 5]);
}

Problem using the difference operator

The script tries to cut a quarter out of a cylinder. It mostly looks OK, but there is a strange artifact at the top and bottom of the cut-out quarter. Let’s highlight the cuboid using # and look at the result edge-on.

Difference problem highlighting the cube

Differnce problem edge-on

The cylinder and cuboid are exactly the same height. The problem is that the cuboid abuts the cylinder at the top and bottom faces. The difference operator cuts a volume out of an object, but doesn’t cut faces out. This causes only the top and bottom faces of the cylinder to remain, but with zero volume. This actually renders to STL correctly, but the preview is messed up.

To correct the problem, extend the cube slightly—​or a lot!--above and below the cylinder. Here is is edge-on with the cuboid highlighted, and the resulting preview without highlighting.

Fixed difference edge on

Fixed difference preview

So, to avoid problems, always cut out a larger chunk than you need, to avoid having the objects involved in the difference() share faces.

Safely “Drilling” Holes

One approach to avoid the problem is to make any holes extend very high and low. For example, heres a script that cuts some holes into a rectangular base. There is a variable maxModelSize that represents a limit on how big the model could possibly be. Holes extend that much below and above the X-Y plane. The second hole is highlighted to show that it extends a long way above and below the X-Y plane.

$fs = .5;
$fa = 10;

maxModelSize = 50;

difference() {
  cube(size=[20, 15, 3]);

  translate([3, 3, 0])
  cylinder(r=1, h=2*maxModelSize, center=true);

  #translate([10, 10, 0])
  cylinder(r=1, h=2*maxModelSize, center=true);

  translate([17, 7, 0])
  cylinder(r=1, h=2*maxModelSize, center=true);
}

Drilling holes

A More Complicated Example

I want to create a model of a wrench, something like this:

Adjustable wrench

To save some time, the model will be a little simpler, nonadjustable, with a rectangular handle rather than tapering, and a circular head. Let’s create the model in several steps.

The Wrench Handle

We can start with a simple rectangle.

handleLength = 45;
handleWidth = 10;
handleHeight = 3;

translate([0, -handleWidth/2, 0])
cube(size=[handleLength, handleWidth, handleHeight]);

Rectangular handle

The far end should be rounded, though, so we’ll shorten the rectangle and add a cylinder.

translate([0, -handleWidth/2, 0])
cube(size=[handleLength - handleWidth/2, handleWidth, handleHeight]);

translate([handleLength - handleWidth/2, 0, 0])
cylinder(d=handleWidth, h=handleHeight);

I’ve highlighted the cylinder to show how the objects fit together.

Rectangular handle with round end

And we need a hole in the end, which I’ve highlighted below.

maxModelHeight = 10;
handleHoleDiameter = handleWidth - 4;

difference() {
  union() {
    translate([0, -handleWidth/2, 0])
    cube(size=[handleLength - handleWidth/2, handleWidth, handleHeight]);

    translate([handleLength - handleWidth/2, 0, 0])
    cylinder(d=handleWidth, h=handleHeight);
  }

  #translate([handleLength - handleHoleDiameter/2 - 2, 0, 0])
  cylinder(d=handleHoleDiameter, h=2*maxModelHeight, center=true);
}

Handle with hole

The Wrench Head

The head of the wrench will be a cylinder centered at the origin.

headDiameter = 2*handleWidth;

cylinder(d=headDiameter, h=handleHeight);

Round head of the wrench

We need a slot in the head. The slot should be roughly rectangular, but with a rounded end. Here is the code for the slot, and an image of how the slot fits with the head.

slotWidth = 10;
slotLength = headDiameter * 3/4;
slotRoundingRadius = 8;

translate([-headDiameter/6, -slotWidth/2, -maxModelHeight])
intersection() {
  cube(size=[headDiameter, slotWidth, 2*maxModelHeight]);

  translate([slotRoundingRadius, slotWidth/2, 0])
  cylinder(r=slotRoundingRadius, h=2*maxModelHeight);
}

The head with the slot cut out

Now we need to rotate the slot around to complete the wrench.

// A wrench model.

$fs = .5;
$fa = 10;

// A size used for making holes. Any part of the model that gets
// a hole should lie within the two planes z = +/- maxModelHeight.
maxModelHeight = 10;

// Dimensions of the wrench handle and hole at the end.
handleLength = 45;
handleWidth = 10;
handleHeight = 3;

handleHoleDiameter = handleWidth - 4;

// Dimensions of the head end and the slot.
headDiameter = 2*handleWidth;

slotWidth = 10;
slotLength = headDiameter * 3/4;
slotRoundingRadius = 8;
slotRotation = 30;

difference() {
  // The handle and head, minus the slot and hole.
  union() {
    cylinder(d=headDiameter, h=handleHeight);

    translate([0, -handleWidth/2, 0])
    cube(size=[handleLength - handleWidth/2, handleWidth, handleHeight]);

    translate([handleLength - handleWidth/2, 0, 0])
    cylinder(d=handleWidth, h=handleHeight);
  }

  // The hole at the end of the handle.
  translate([handleLength - handleHoleDiameter/2 - 2, 0, 0])
  cylinder(d=handleHoleDiameter, h=2*maxModelHeight, center=true);

  // The slot in the head.
  rotate(180 + slotRotation)
  translate([-headDiameter/6, -slotWidth/2, -maxModelHeight])
  intersection() {
    cube(size=[headDiameter, slotWidth, 2*maxModelHeight]);

    translate([slotRoundingRadius, slotWidth/2, 0])
    cylinder(r=slotRoundingRadius, h=2*maxModelHeight);
  }
}

The completed wrench

Exercise 4

You are to create a model of a mount for the Raspberry Pi camera.

Raspberry Pi camera

Raspberry Pi camera

The dimensions of the camera are as follows.

Camera dimensions

You can see an example of a commercial camera mount below.

Sample camera mount

We can make it more rectilinear, though, and without a top covering piece.

Sample Raspberry Pi camera mount

This is a difficult problem that requires you to use cuboids and cylinders, boolean operations, and rotations. To avoid getting stuck, concentrate on one part of the mount at a time. For example, if you don’t know how to create the whole mount, can you create the base? Or can you create the main part of the mount with just the square hole for the camera lens?

More hints: model both the base and the upright portions as horizontal in the X-Y plane, and then rotate the base as a last step. Make sure your holes are of sufficient depth to cut them out completely.