2.6. Designing with OpenSCAD for 3D printing

OpenSCAD is ideal for quickly generating 3d-printable models. Unlike WYSIWYG CAD software, OpenSCAD generates prints programatically. This allows easy design and adjustment of prints based on repetitive patterns using parametric settings.

Note

These notes are based on my experiences with the Prusa i3 Mk3 and Artillery/Evnovo Sidewinder X1 printers. If you are using a different printer, please verify the hardware details are similar.

OpenSCAD is used extensively in the Thingiverse customizer.

These notes are meant to give a taste of OpenSCAD’s capabilities. Please refer to the OpenSCAD online user manual for more details.

Todo

OpenSCAD content

  • Test parts

  • Parametric prints

2.6.1. The OpenSCAD user interface

OpenSCAD interface

Fig. 2.36 OpenSCAD interface

2.6.2. Programming in OpenSCAD

As you adjust the code using OpenSCAD’s programming language, a preview of the resulting model is shown in the view window.

OpenSCAD parametric model example 1

Fig. 2.37 OpenSCAD parametric model example 1

If you adjust parameters or code, pressing the preview button ([F5]) will update the display to show the changes.

OpenSCAD parametric model example 2

Fig. 2.38 OpenSCAD parametric model example 2

2.6.3. Downloadable parametric test prints

2.6.3.1. Bed leveling test

This model is a parametric bed leveling test to be used in conjunction with the Live-Z calibration procedure. It prints a pattern of rectangular shapes in a grid around the print bed, connected by thin lines for easy removal.

Bed leveling test print generated in OpenSCAD

Fig. 2.39 Bed leveling test print generated in OpenSCAD

Here’s the source code:

Listing 2.41 Parametric bed level test print
 1$fn = 90;
 2
 3t_bed_width = 250;
 4t_bed_depth = 210;
 5t_bed_border = 8;
 6t_shape_xcount = 3;
 7t_shape_ycount = 3;
 8t_shape_xsize = 25;
 9t_shape_ysize = 25;
10t_line_width = 1.6;
11t_thickness = 0.2;
12t_print_width = t_bed_width - t_shape_xsize - (2*t_bed_border);
13t_print_depth = t_bed_depth - t_shape_ysize - (2*t_bed_border);
14
15// Bed size
16//%square([t_bed_width, t_bed_depth]); 
17
18// Grid area
19translate([t_bed_width/2,t_bed_depth/2]){
20    %square([t_print_width,t_print_depth], true);
21}
22
23// Print area
24translate([t_bed_width/2,t_bed_depth/2]){
25    %square([t_bed_width-(2*t_bed_border),t_bed_depth-(2*t_bed_border)], true);
26}
27
28linear_extrude(height = t_thickness) { 
29    // shift everything to center in print area
30    translate([(t_shape_xsize/2)+t_bed_border,(t_shape_ysize/2)+t_bed_border,0]){
31        // intervals between printed shapes
32        t_increment_x = t_print_width / (t_shape_xcount-1);
33        t_increment_y = t_print_depth / (t_shape_ycount-1);
34        t_center_x = 0;
35        t_center_y = 0;
36    
37        // draw grid
38        // draw horizontal lines along X axis
39        for(t_curr_x = [0:t_shape_xcount-1]){
40            translate([t_center_x, t_print_depth/2, 0]){
41                square([t_line_width,t_print_depth], true);
42            }
43            t_center_x = t_curr_x * t_increment_x;
44        }
45        // draw vertical lines along Y axis
46        for(t_curr_y = [0:t_shape_ycount-1]){
47            translate([t_print_width/2, t_center_y, 0]){
48                square([t_print_width, t_line_width], true);
49            }
50            t_center_y = t_curr_y * t_increment_y;
51        }
52        
53        // draw shapes
54        t_center_x = 0;
55        for(t_curr_x = [0:t_shape_xcount-1]){
56            t_center_y = 0;
57            for(t_curr_y = [0:t_shape_ycount-1]){
58                translate([t_center_x,t_center_y]){
59                    square([t_shape_xsize,t_shape_ysize],true);
60                }
61                t_center_y = t_curr_y * t_increment_y;
62            }
63            t_center_x = t_curr_x * t_increment_x;
64        }
65    }
66}

2.6.3.2. Test tower

This model is a parametric test tower. It generates a multi-level tower of user-specified dimensions with a divider and label at each level. You can see it in action on the |PS| modifiers page.

Test tower print generated in OpenSCAD

Fig. 2.40 Test tower print generated in OpenSCAD

Here’s the source code:

Listing 2.42 Parametric test tower print
  1$fn = 90;
  2
  3t_levels = 7; // total number of levels to print
  4t_start_label = 800; // starting numeric label
  5t_label = t_start_label; // current level numeric label
  6t_increment = 100; // increment for text labels on each layer
  7t_baseheight = 1; // height of base and spacer levels in mm
  8t_wallheight = 10; // combined height of wall on each layer
  9t_width = 30; // tower width
 10t_depth = 25; // tower depth 
 11t_wallthickness = 1.67; // wall thickness - min. 1.5mm for surface quality & z-seam alignment
 12t_font = "Open Sans:style=ExtraBold";
 13t_font_size = t_wallheight*0.6;
 14t_font_depth = 0.4; // depth of text extrusions
 15t_solid = true;
 16t_name = "v20190403";
 17t_model = "Generic";
 18t_text_append = "";
 19
 20module outer_shell() {
 21    // outer shell
 22    square([t_width,t_depth], true);
 23}
 24
 25module inner_shell() {
 26    // inner shell is wallthickness thinner
 27    square([t_width-t_wallthickness,t_depth-t_wallthickness], true);
 28}
 29
 30module spacer_shell() {
 31    // spacer shell is wallthickness thicker
 32    square([t_width+t_font_depth,t_depth+t_font_depth], true);
 33
 34}
 35
 36module print_base(){
 37    // solid base
 38    color("goldenrod") {
 39        linear_extrude(height = t_baseheight) {
 40            //spacer_shell(); 
 41                square([t_width+10,t_depth+10], true);
 42        }
 43    }
 44}
 45
 46module print_spacer(curr_height, fill){
 47    // elevate to current height
 48    translate([0,0,curr_height]){
 49        // spacer layer
 50        color("gray") {
 51            linear_extrude(height = t_baseheight) {
 52                if( fill ) {
 53                    spacer_shell();
 54                } else {
 55                    difference() {
 56                        spacer_shell(); 
 57                        inner_shell();
 58                    }
 59                }
 60            }
 61        }
 62    }
 63}
 64
 65module print_level(curr_height, fill) {
 66    // elevate to current height
 67    color("lightblue") {
 68        translate([0,0,curr_height]){
 69            linear_extrude(height = t_wallheight) { 
 70                if( fill ) {
 71                    outer_shell();
 72                } else {
 73                    difference() {
 74                        outer_shell();
 75                        inner_shell();
 76                    }
 77                }
 78            }
 79        }
 80    }
 81}
 82
 83module print_text(curr_height,level_text) {
 84    // text
 85    translate([0,-t_depth/2,curr_height]){
 86        color("wheat"){
 87            // rotate text upright
 88            rotate([90, 0, 0]) { 
 89                // extrude text
 90                linear_extrude(height = (t_font_depth)) {
 91                   translate([0,t_wallheight/2,0]){
 92                            text(level_text,t_font_size,t_font,valign="center",halign="center");
 93                    }
 94                }
 95            }
 96        }
 97    }
 98}
 99
100// Generate test tower
101// print solid base
102print_base();
103for(t_level = [0:t_levels-1]){
104    // generate levels
105    if( t_level == 0 ) {
106        // allow for alternate text on 1st (0th) layer
107        print_level(t_level, t_solid);
108        print_text(t_level,str(t_label,t_text_append));
109
110    } else {
111        // generate succeeding layers
112        print_spacer(t_level*t_wallheight, t_solid);
113        print_level(t_level*t_wallheight, t_solid);        
114        print_text(t_level*t_wallheight,str(t_label,t_text_append));
115    }
116    // update printed label for next layer
117    t_label = t_label + (t_level * t_increment);
118}
119
120color("red") {
121    // print final spacer layer at top of tower
122    if(t_solid) {
123        difference() {
124            print_spacer(t_levels*t_wallheight, t_solid);
125            translate([0,0,((t_levels*t_wallheight)+t_baseheight)-t_font_depth]){
126                linear_extrude(height = (t_font_depth+1)) {
127                    text(t_name,t_font_size*.5,t_font,valign="center",halign="center");
128                }
129            }
130        }
131    } else {
132        print_spacer(t_levels*t_wallheight, t_solid);
133    }
134}

Contact and feedback

You can find me on the Prusa support forums or Reddit where I lurk in many of the 3D printing-related subreddits. I occasionally drop into the Official Prusa 3D discord server where I can be reached as bobstro (bobstro#9830). You can email me directly at projects@ttlexceeded.com.

Last modified Apr 03, 2021. Last build on Oct 22, 2021.