Most of our beloved tools, such as Slic3r, Cura or KISSlicer, offer scripting interfaces that help a great deal if your existing 3D printing toolchain has yet to learn how to produce decent results with a five headed thermoplastic spitting hydra. Using scripts, it’s possible to tweak the little bits it takes to get great results, inserting wipe or prime towers and purge moves on the fly, and if your setup requires it, also control additional servos and solenoids for the flamethrowers.

This article gives you a short introduction in how to post-process G-code using Perl and Slic3r. Perl Ninja skills are not required. Slic3r plays well with pretty much any scripting language that produces executables, so if you’re reluctant to use Perl, you’ll probably be able to replicate most of the steps in your favorite language.

Getting Started

All you need is Slic3r and Perl installed on your system. OSX and Linux users will already have Perl on board, while Windows users need to install a Perl package, Strawberry Perl for example. OSX users may download the example post-processing scripts from Slic3r’s GitHub repository, which only come with the Windows and Linux binaries.

The Main Loop

Once you’re set, create an empty text file `postprocessor.pl` in your user directory and fire up your favorite editor to fill it with the following basic structure:

#!/usr/bin/perl -i use strict; use warnings; # the main loop while (<>) { print; # implicitly print an unmodified G-code line back into the file }

The first line clarifies the scripting language, strict disables some advanced Perl magic and warnings yells at you when you’re doing something wrong. The diamond operator <> lets the while loop iterate over the input file (our G-code) line-by-line. In this example, we just print back the unchanged content of the G-code line.

Perl uses a default variable $_ , which is implicitly used in some places. Therefore in Perl, the following three snippets all mean (almost) the same:

while (<>){ print; }

while (<>){ print $_; }

while (my $_ = <>){ print $_; }

Windows users may need to add $^I = '.bak'; before the while(<>) loop to create a temporary working copy.

Running The Script From Slic3r

Slic3r runs the post-processing script for you after the model is sliced. All you need to do is making sure that the script is executable ( chmod 755 postprocessor.pl ) and specify the absolute path to the script in the output options of Slic3r.

Debugging

Instead of using Slic3r, you can also manually apply the script to an existing G-code file in the terminal:

perl path/to/postprocessor.pl path/to/some.gcode

This way, you’ll also get all the warnings and errors for debugging your script.

Example Script: Filament Counter

The above script doesn’t yet modify the G-code, so let’s write one that actually does something. The following script tracks the filament consumption during the print and displays it to the printer’s LCD (if it has one) using the M117 command. It simply filters all G1/G2 commands for the E (extruder) and Z (Z-axis) addresses using regular expressions. To keep this example simple, it works only with relative extrusion moves:

#!/usr/bin/perl -i use strict; use warnings; use Math::Round; my $consumedFilament=0; while (<>){ # a regular expression for the G0/G1 commmand (click it to see what it does) if(/^G[01](\h+X(-?\d*\.?\d+))?(\h+Y(-?\d*\.?\d+))?(\h+Z(-?\d*\.?\d+))?(\h+E(-?\d*\.?\d+))?(\h+F(\d*\.?\d+))?(\h*;\h*([\h\w_-]*)\h*)?/){ # the match variables, just readable my $X=$2, my $Y=$4, my $Z=$6, my $E=$8, my $F=$10, my $verbose=$12; if($E){ # tracking how much filament we're using $consumedFilament+=$E; }if($Z){ # print the consumed filament to the LCD print "

M117 ".round($consumedFilament)."mm

"; } } print; }

Wipe/Prime Tower Scripts

At this point, you can basically track any G-Code command and also insert arbitrary new G-codes, for example G1 printing moves (for wipe towers) or M280 commands to control a servo. Yet, it also becomes clear that this way, you’ll spend a lot of time writing code to track G-code moves and make sense of them. I’ve written some post-processing scripts using the above method, so if you need wipe/prime towers, you may check them out on GitHub. Wipe/prime towers are a great method to free the nozzle from oozed filament on tool changes in multicolor prints, or to prime an extruder before it starts printing after an idle phase. The latter is especially necessary when using color-switching nozzles, where the previous color needs to be purged from the nozzle. They are also a great example for what can be done with Perl postprocessing scripts.

Zero-ooze results The nozzle during the wiping move.

A Universal Template

Since we need to parse a lot of G-Code before we can do anything more complex, I came to the conclusion that the best way is a template that makes the most common G-codes available as subroutines. For example, it would be nice to have a subroutine process_printing_move() in which you may specify how you want to process every printing move in a G-code file. You can download my template on GitHub, it’s supposed to make it easier to develop new single-file post-processing scripts. The following example implements the filament counter from the very first example in this post, only more readable:

Template Example: Filament Counter

my $consumedFilament=0; sub process_printing_move { # these arguments (XYZE and F) are passed to the subroutine my $thisLine=$_[0], my $X = $_[1], my $Y = $_[2], my $Z = $_[3], my $E = $_[4], my $F = $_[5]; # tracking filament usage if($E){ $consumedFilament+=$E; } # returning the unchanged line return $thisLine; } sub process_layer_change { # the available arguments my $thisLine = $_[0], my $Z = $_[1], my $F = $_[2]; # print the consumed filament to the LCD my $message="

M117 ".round($consumedFilament)."mm

"; # return modified line return $thisLine.$message; }

The template also buffers the entire G-Code and makes Slic3r’s printing parameters available to your code from an associative array %parameters . For example, the filament diameter specified in Slic3r becomes available through $parameters{"filament_diameter"} . The parameter names are the same as in the Slic3r configuration files. You can also specify your own parameters just by adding them to the Start G-code section in Slic3r as a comment ( ; some_parameter = 2 ). For our filament counter, that means we can also calculate the volume of the consumed material:

sub process_layer_change { # the available arguments my $thisLine = $_[0], my $Z = $_[1], my $F = $_[2]; # calculating the volume my $volume=$consumedFilament*$parameters{"filament_diameter"}**2*PI/4000; # printing the volume to the LCD my $message="

M117 ".round($volume)."cm^2

"; return $thisLine.$message; }

Other Experimental Applications

I hope you enjoyed this little introduction to Perl and G-Code post-processing. Eventually, there is a lot more you can do with G-Code post-processors. One more interesting application is interlocking non-planar printing. The idea is to use interlocking, non-planar layers to turn layer tension stress (the big weakness of FDM) into layer shearing and compression stress (a strength of FDM). Since Local Motors seemed to be looking for a way to generate stronger parts, I ran their Strati model through a G-code post-processor I had written a while ago (in Java, though) that displaces the layers along sinusoidal wave field. Since the displaced layers don’t intersect, this can still be printed on a regular 3-axis printer.