Introduction: W4: G-Code

About: Ph.D. Student in Media Arts & Technology @ UCSB

Last week, we started generating G-Code in Grasshopper that controls the 3d-printer directly. Ender 3 Pro is using Marlin flavored G-Code. Marlin index contains various codes for controlling motion and temperatures on the device, but I found G0/G1 commands particularly interesting. These commands control the movement of nozzle head in 3 dimensions, its speed and extrusion amount. According to the docs, the G0 command is encouraged in situations where no extrusion is happening.

G1 [E<pos::mm>] [F<rate::mm/min>] [X<pos::mm>] [Y<pos::mm>] [Z<pos::mm>]

Step 1: G-Code & Custom Slicer

The previous process of saving G-code commands into a file in the TF card proved too slow to rapidly experiment. I looked online for live control of the printer through my computer. Pronterface is open-source software that can communicate with Ender 3 Pro in real-time. It has GUI (see Figure) components to move nozzle head, a console for G-code execution, and a window to visualize tool paths for a loaded g-code file. I used this program to execute files generated in Grasshopper.

I started experimenting with the sample slicer code provided by Jennifer Jacobs. This sample code takes geometry as input and slices it parallel to the XY-plane. Resulting points are then processed in the Python component and each line segment is converted into motion of nozzle head.

def makeGcodeSpeed(fr, to, speed):
    l = (to - fr).Length
    numerator = (_NozzleWidth * l * _LayerHeight)
    denominator = (1.75 / 2) * (1.75 / 2) * math.pi

    e = numerator / denominator

    return "G1 F" + str(speed) + " X" + "{:.{}f}".format(to.X,2) + " Y" + "{:.{}f}".format(to.Y,2) + " E" + "{:.{}f}".format(e,8) + "\n"

The above function takes two points and speed as input and returns the g-code line required for printing the line. The extrusion amount is calculated by the volume of material that needs to be extruded from the nozzle. The Rhino screenshot and photo are the resulting forms from this process with a truncated cone.

Step 2: Silkworm 2

I also experimented with Grasshopper plug-in Silkworm. I downloaded Silkworm 2beta as it is the most recent version. Unfortunately, I couldn't find detailed information about how to use this version as all the examples are for v1. Yet it comes with five intuitive components:


This component takes the nozzle width, layer height, and filament diameter as input and calculates the required flow ratio for the Extrusion component.


It accepts the flow ratio and speed as inputs and generates nozzle movements from a set of lines and delimiters. It accepts a set of lines or points, iterates them sequentially. Without providing any delimiters, this component will produce continuous extrusion paths.


The line segments defined in Delimiter would retract the filament. It has 7 input connections but I had a hard time understanding the relationships between the retraction and these parameters. I will come back to it later.


This is the main component that generates a g-code string and a model. The g-code string does not contain any preparatory lines, so I had to write a custom file saver for the output by starting with initial heat settings followed by the actual g-code. The model parameter is passed to the Silkworm Viewer for path visualization.

Silkworm Viewer:

This component takes the Silkworm model. Display Logistics shows the non-extrusion paths, and Display Values shows the extruded paths.

After experimenting with basic lines in Grasshopper, I tried printing this example. I am having a problem with converting curves to line segments to feed into Silkworm. To get the line output, I used the Explode component on the curve geometry, which gives me a set of points. Then I used the End Points component to create Lines with the start and endpoints. However the resulting g-code starts from Z=0, then immediately jumps to Z=45 and starts printing from the top. I suspect the problem is in my method of line creation. Any thoughts?