Saturday, November 17, 2018

Composing multimaterial 3D objects with OpenSCAD and the command line

I'm a fan of OpenSCAD. I'm also a gardener. My sharpie based plant labels were becoming difficult to read after a season on the ground. Worse though, some of the plants that I keep in my bog garden were becoming completely unreadable. Especially since they can sit outdoors in soggy or wet acidic peat moss for years before I decide that I need to remind myself exactly which cultivar I am looking at. So, having recently acquired the Prusa MMU upgrade for MK3, I naturally decide to 3d print the labels, so that they will never fade, and it will indeed be impossible for them to do so, since the lettering will be in a completely different color of plastic. This brings us to the first bit of code, the 3d printable multi-material plant label written in OpenSCAD:
 
letter="<Main Text>";
smallText="<Small Text>";
    
length = 90;    
textStart = 0; 
height = 2; 

module GetText(bigText, littleText) { 
    union() {         
        translate([textStart, 0, 1.7])
            color("black", 1)
                linear_extrude(height=.301, convexity=4)
                    text(bigText, 
                    font="Bitstream Vera Sans",
                    halign="center",
                    size=7
                    );
        
        translate([textStart, -8, 1.7])
            color("black", 1)
                linear_extrude(height=.301, convexity=4)
                    text(littleText, 
                    font="Bitstream Vera Sans",
                    halign="center",
                    size=5// 3 is too small, doesn't extrude
                          // 4 is readable, but leaves gaps
                    );
            }
}

// First extrusion 
/*marker_one*/difference () { 
    color("white", 1.0)
        union() { 
            //stem
            translate([-length/2 - 100, -2, 0])
                cube([100, 4, height]);
            
            // tapered neck 
            linear_extrude(height) { 
                polygon(points=[[-length/2 -30, 0], [-length / 2, +10], [-length /2, -10], [-length / 2 - 30, 0]]);
            } 
            
            //Broad flat area for text
            translate([-length/2, -10, 0])
                cube([length, 20, height], center=false) ;
        }
    
    // holes for text 
    color("black", 1) 
        union() { 
            GetText(letter, smallText); 

            rotate([180, 0, 0])
                translate([textStart, 1, -2])
                    GetText(letter, smallText); 
        }
}

// Second Extrusion
/*marker_two*/union() { 
    GetText(letter, smallText); 

    rotate([180, 0, 0])
        translate([textStart, 1, -2])
            GetText(letter, smallText); 
}
With this file in hand, I first replace <Main Text> and <Small Text> with something appropriate for the label. I then replace /*marker_two*/ with an asterisk and export the object to an *.amf file. I then repeat the process with /*marker_one*/, after deleting the first asterisk. So I have two *.amf files which I will then load into slic3r and convert into gcode. I print a lot of these labels, and I only print one or two of each of them. So this turns out to be more labor intensive than I'd like. After some research, I created the following powershell function to do the work for me. All from a single command.
function Get-3dMMPlantLabel { 
    Param($mainText, $smallText="")
    process {
        $template = [System.IO.File]::ReadAllText("PlantLabelTemplate.scad")
        $output = $template.Replace("<Main Text>", $mainText).Replace("<Small Text>", $smallText)
        $outputOne = $output.Replace("/*marker_two*/", "*")
        $outputTwo = $output.Replace("/*marker_one*/", "*")
        $outputOneFileName = "$($mainText)1.scad"
        $outputTwoFileName = "$($mainText)2.scad"
    
        $outputOne | Out-File $outputOneFileName -Encoding ascii
        $outputTwo | Out-File $outputTwoFileName -Encoding ascii
    
        & "C:\Program Files\OpenSCAD\openscad.exe" -o "$($mainText)1.amf" $outputOneFileName
        & "C:\Program Files\OpenSCAD\openscad.exe" -o "$($mainText)2.amf" $outputTwoFileName
    
    }
}

Get-3dMMPlantLabel "Swamp Milkweed" "Somewhere in OH"
It outputs two files: "Swamp Milkweed1.amf" and "Swamp Milkweed2.amf" in this example. These are exactly what I need to orchestrate the 3d print in Slic3r. Now if only I could automate the gcode creation in Slic3r. Maybe next Saturday.

Monday, January 1, 2018

3d printing

I've dabbled in 3d printing for a few years now. I just got an awesome new Prusa Mk3. Love it.

I also started updating my OpenSCAD skills.

My latest creation is a simple flower pot.
The whole file on GitHub is here.

Some notes:
1) module -- this seems to be what I, as a programmer, would normal call a function. In the context of OpenSCAD they are modules. Not sure why the change in syntax, it's just something to remember.
2) for loops -- another new thing thing that I have learned, and an immensely useful one in this context.
3) hull() -- this is what I used to achieve the rounded edges. I'm not sure I grok it completely, but it is certainly another useful tool. Here is the article that led me to it.
4) GitHub has a great STL Viewer. The rendered object is here.
5) Oooh, and one more. The MCAD libraries are full of good stuff.
use <MCAD/--filename-->
To include them in a normal scad file.