Designing with OpenSCAD

OpenSCAD allows 3d-printable models to be generated programatically. This allows easy generation of prints generating repetitive patterns based on parametric settings.

Note

These notes are based on my experiences with the Prusa i3 Mk3 printer. If you are using a different printer, please verify the hardware details are same. These pages may be a bit rough as I revise them and add new material. Please check back regularly for updates.

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

The OpenSCAD user interface

OpenSCAD interface

Fig. 34 OpenSCAD interface

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. 35 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. 36 OpenSCAD parametric model example 2

Downloadable parametric test prints

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. 37 Bed leveling test print generated in OpenSCAD

Here’s the source code:

Listing 32 Parametric bed level test print
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
$fn = 90;

t_bed_width = 250;
t_bed_depth = 210;
t_bed_border = 8;
t_shape_xcount = 3;
t_shape_ycount = 3;
t_shape_xsize = 25;
t_shape_ysize = 25;
t_line_width = 1.6;
t_thickness = 0.2;
t_print_width = t_bed_width - t_shape_xsize - (2*t_bed_border);
t_print_depth = t_bed_depth - t_shape_ysize - (2*t_bed_border);

// Bed size
//%square([t_bed_width, t_bed_depth]); 

// Grid area
translate([t_bed_width/2,t_bed_depth/2]){
    %square([t_print_width,t_print_depth], true);
}

// Print area
translate([t_bed_width/2,t_bed_depth/2]){
    %square([t_bed_width-(2*t_bed_border),t_bed_depth-(2*t_bed_border)], true);
}

linear_extrude(height = t_thickness) { 
    // shift everything to center in print area
    translate([(t_shape_xsize/2)+t_bed_border,(t_shape_ysize/2)+t_bed_border,0]){
        // intervals between printed shapes
        t_increment_x = t_print_width / (t_shape_xcount-1);
        t_increment_y = t_print_depth / (t_shape_ycount-1);
        t_center_x = 0;
        t_center_y = 0;
    
        // draw grid
        // draw horizontal lines along X axis
        for(t_curr_x = [0:t_shape_xcount-1]){
            translate([t_center_x, t_print_depth/2, 0]){
                square([t_line_width,t_print_depth], true);
            }
            t_center_x = t_curr_x * t_increment_x;
        }
        // draw vertical lines along Y axis
        for(t_curr_y = [0:t_shape_ycount-1]){
            translate([t_print_width/2, t_center_y, 0]){
                square([t_print_width, t_line_width], true);
            }
            t_center_y = t_curr_y * t_increment_y;
        }
        
        // draw shapes
        t_center_x = 0;
        for(t_curr_x = [0:t_shape_xcount-1]){
            t_center_y = 0;
            for(t_curr_y = [0:t_shape_ycount-1]){
                translate([t_center_x,t_center_y]){
                    square([t_shape_xsize,t_shape_ysize],true);
                }
                t_center_y = t_curr_y * t_increment_y;
            }
            t_center_x = t_curr_x * t_increment_x;
        }
    }
}

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 |Slic3rPE| modifiers page.

Test tower print generated in OpenSCAD

Fig. 38 Test tower print generated in OpenSCAD

Here’s the source code:

Listing 33 Parametric test tower print
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
$fn = 90;

t_levels = 7; // total number of levels to print
t_start_label = 800; // starting numeric label
t_label = t_start_label; // current level numeric label
t_increment = 100; // increment for text labels on each layer
t_baseheight = 1; // height of base and spacer levels in mm
t_wallheight = 10; // combined height of wall on each layer
t_width = 30; // tower width
t_depth = 25; // tower depth 
t_wallthickness = 1.67; // wall thickness - min. 1.5mm for surface quality & z-seam alignment
t_font = "Open Sans:style=ExtraBold";
t_font_size = t_wallheight*0.6;
t_font_depth = 0.4; // depth of text extrusions
t_solid = true;
t_name = "v20190403";
t_model = "Generic";
t_text_append = "";

module outer_shell() {
    // outer shell
    square([t_width,t_depth], true);
}

module inner_shell() {
    // inner shell is wallthickness thinner
    square([t_width-t_wallthickness,t_depth-t_wallthickness], true);
}

module spacer_shell() {
    // spacer shell is wallthickness thicker
    square([t_width+t_font_depth,t_depth+t_font_depth], true);

}

module print_base(){
    // solid base
    color("goldenrod") {
        linear_extrude(height = t_baseheight) {
            //spacer_shell(); 
                square([t_width+10,t_depth+10], true);
        }
    }
}

module print_spacer(curr_height, fill){
    // elevate to current height
    translate([0,0,curr_height]){
        // spacer layer
        color("gray") {
            linear_extrude(height = t_baseheight) {
                if( fill ) {
                    spacer_shell();
                } else {
                    difference() {
                        spacer_shell(); 
                        inner_shell();
                    }
                }
            }
        }
    }
}

module print_level(curr_height, fill) {
    // elevate to current height
    color("lightblue") {
        translate([0,0,curr_height]){
            linear_extrude(height = t_wallheight) { 
                if( fill ) {
                    outer_shell();
                } else {
                    difference() {
                        outer_shell();
                        inner_shell();
                    }
                }
            }
        }
    }
}

module print_text(curr_height,level_text) {
    // text
    translate([0,-t_depth/2,curr_height]){
        color("wheat"){
            // rotate text upright
            rotate([90, 0, 0]) { 
                // extrude text
                linear_extrude(height = (t_font_depth)) {
                   translate([0,t_wallheight/2,0]){
                            text(level_text,t_font_size,t_font,valign="center",halign="center");
                    }
                }
            }
        }
    }
}

// Generate test tower
// print solid base
print_base();
for(t_level = [0:t_levels-1]){
    // generate levels
    if( t_level == 0 ) {
        // allow for alternate text on 1st (0th) layer
        print_level(t_level, t_solid);
        print_text(t_level,str(t_label,t_text_append));

    } else {
        // generate succeeding layers
        print_spacer(t_level*t_wallheight, t_solid);
        print_level(t_level*t_wallheight, t_solid);        
        print_text(t_level*t_wallheight,str(t_label,t_text_append));
    }
    // update printed label for next layer
    t_label = t_label + (t_level * t_increment);
}

color("red") {
    // print final spacer layer at top of tower
    if(t_solid) {
        difference() {
            print_spacer(t_levels*t_wallheight, t_solid);
            translate([0,0,((t_levels*t_wallheight)+t_baseheight)-t_font_depth]){
                linear_extrude(height = (t_font_depth+1)) {
                    text(t_name,t_font_size*.5,t_font,valign="center",halign="center");
                }
            }
        }
    } else {
        print_spacer(t_levels*t_wallheight, t_solid);
    }
}

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.