3D-Design with openscad

TL;DR: You can program 3D stuff with openscad

For a long time I’ve avoided designing 3D stuff myself. The reason is that my spatial imagination is really bad. I even get lost or take the longer route in cities I know. It’s a disaster in an unknown territory where I try to take a ‘shortcut’. But at least I will always be in a good shape physically.

But when you own a 3D printer you want to at least change designs. I’ve tried this with the usual CAD programs and failed. I just can’t turn the objects in my head, I have no feel for the proportions.

So I’ve changed to openscad. This one I really like. It’s an ancient piece of software where you write code which is translated into 3D objects. F.e. this piece of code

tolerance = 0.2;
cube([5 + 2 * tolerance, 10, height * 2], center = true);

generates a cube with my desired dimensions in the center.

You can already see that it has a c-like syntax and basic algorithmic which is used here to incorporate the tolerance of my 3d printer. As it is a programming language you can do the usual stuff: organisation by modules with parameters, functions, for-loops, sin/cos calculations, intersection, difference and more complex operations like the convex hull.

This leads naturally to a hierarchy. You build your objects bottom-up and you can test each piece individually.

The cons are that you can’t do real unit-tests for your objects and that the editor is garbage. The editor can easily be fixed by using an external editor or astyle. Astyle automatically indents and formats your code.

Also there are strange glittering artifacts if you have coinciding surfaces. That’s why I translate all objects which use difference by 0.1mm or 0.01mm which removes these artifacts.

Here is the example code for my kitchen mixer adapter:

/* this is an adapter for a bosch mixer sold by aldi

    measurements of inner rod are 7mm circle, with flat sides diameter = 5mm

    outer circumference is 20mm. Without the rods on the outside it's 16mm

    adjust tolerance parameter for your printer. It should only fit with a lot of pressure
*/


tolerance = 0.2;

module rod()
{
    height = 14;
    intersection()
    {
        cylinder(h = height, r = 7 / 2 + 2 * tolerance);
        cube([5 + 2 * tolerance, 10, height * 2], center = true);
    }
}


module adapter()
{
    bottomPlaneRadius = 32 / 2;
    indentionHeight = 5;
    matchingPartHeight = 20;
    difference()
    {
        union()
        {
            cylinder(r = bottomPlaneRadius, h = 6);

            // matching part
            translate([0, 0, indentionHeight])
            {
                cylinder(h = matchingPartHeight, r = 13 / 2);
                for(i = [0:1:5])
                {
                    rotate([0, 0, i * 360 / 6])
                    translate([13 / 2, 0, 0])
                    {
                        // the total diameter has to be less than 20
                        cylinder(r = 2.5, h = matchingPartHeight);
                        // strengthen the bottom
                        cylinder(r1 = 5, r2 = 2.5, h = 3);
                    }
                } // end for

            } // end matching part
        } // end additive part

        union()
        {
            // flatten the top
            topFlatHeight = 6;
            translate([0, 0, matchingPartHeight + indentionHeight - topFlatHeight + 0.01])
            difference()
            {
                cylinder(h = topFlatHeight, r = bottomPlaneRadius);
                translate([0, 0, -0.01])
                cylinder(h = topFlatHeight, r1 = bottomPlaneRadius, r2 = 12 / 2);
            }
            // cut out at the center
            translate([0, 0, -0.01])
            rod();
            // rim at the outer region
            translate([0, 0, -0.01])
            difference()
            {
                cylinder(h = indentionHeight, r = 27.5 / 2 + tolerance);
                cylinder(h = indentionHeight, r = 23.5 / 2 - tolerance);
            }
            // reduce the outer rim height
            translate([0, 0, -0.01])
            difference()
            {
                cylinder(h = 2, r = bottomPlaneRadius + 0.1);
                cylinder(h = 2, r = 27 / 2 - 0.1);
            }
            // only the center 16mm allow full depth
            translate([0, 0, -0.01])
            difference()
            {
                cylinder(h = 2, r = 24 / 2 + tolerance);
                cylinder(h = 2, r = 16 / 2 - tolerance);
            }
        }
    }
}

$fn = 128;
//rod();
adapter();

Which results in this object:

mixer adapter preview in openscad

bottom side preview of the mixer adapter

This is the resulting print:

printed mixer adapter. The rough surface is because I printed it upside down with supports

  The print works flawlessly on my kitchen mixer on the third try.

Conclusion

Openscad is an easy way to design functional parts. The designs look quite minimalistic and usually take up the minimum amount of space because you just set constraints which openscad tries to fulfill – at least if you’re good.

Also you can publish your designs on thingiverse. Openscad can easily be extended and customized as it is just code. You could even track changes with GIT.