Custom G-Code

Custom g-code is something of a dark art amongst the slicer community. After using several slicers and comparing a variety of profiles, I realized a lot of the magic was happening in the g-code. Many of the best profiles utilized hardware commands embedded in a little-understood part of the settings. Until recently, tuning accleration and jerk settings required tweaking and inserting gcode commands by hand. More recent versions of slicers – notably Slic3r Prusa Edition and Cura – have begun exposing these settings in the printer, print and filament profiles, making them much more accessible and easy to adjust between prints.

Note

These notes apply to 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.

While moving these commands to the slicer GUI is a big improvement, there are still several things you’re likely to want to do at the start and finish of each print. Custom G-code is the right place to insert these functions.

Caution

Please be sure that you’ve calibrated your printer, and particularly your Live-Z settings before using any of the following examples. These routines move the nozzle around close to the bed, and could cause damage if your printer is not adjusted properly.

Slic3r Prusa Edition and other slicers allow inserting custom g-code at several points during a print. The most common are:

  1. Before the print starts. This is a good place to insert printer initialization commands, warmup routines and nozzle priming.
  2. At the end of a print. This code is responsible for turning off heaters, motors and fans, but can also be tweaked to move the extruder and bed after a print.
  3. Between layer changes. This is useful for printing things like temperature calibration prints that require changing print settings based on the current layer.

Start G-Code

I’ve incorporated these features into my own customized g-code settings for Slic3r Prusa Edition. Here’s my start g-code:

Listing 1 Slic3r Prusa Edition start g-code
 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
; Last updated 20181030
M115 U3.3.1 ; tell printer latest fw version
; Set initial warmup temps
M104 S140 ; set extruder no-ooze temp
M140 S{max(first_layer_bed_temperature[0],65)}  ; set bed PINDA warmup temp
; Nozzle warmup routine
M300 S40 P10 ; chirp
G28 W ; home all without mesh bed level
G0 X0 Y200 Z100.0 F10200 ; raise nozzle and present bed for cleaning
M109 ; wait for extruder no-ooze warmup temp before mesh bed leveling, cool hot PINDA
; PINDA warmup routine
M300 S40 P10 ; chirp
G0 X125 Y105 Z0.10 F10200; PINDA warming position
M860 S35 ; wait for PINDA temp to stabilize
M300 S40 P10 ; chirp
G28 W ; home all without mesh bed level
M140 S[first_layer_bed_temperature] ; set bed final temp
G80 ; mesh bed leveling
; Final warmup routine
M104 S[first_layer_temperature] ; set extruder final temp
M109 S[first_layer_temperature] ; wait for extruder final temp
M190 S[first_layer_bed_temperature] ; wait for bed final temp
; Prime line routine
M300 S25 P10 ; chirp
M83  ; extruder relative mode
M900 K0; Disable LA for prime line
G92 E0.0 ; reset extrusion distance
G1 Y-3.0 F1000.0 ; go outside print area
G1 E2 F1000 ; de-retract and push ooze
G1 X20.0 E6  F1000.0 ; fat 20mm intro line @ 0.30
G1 X60.0 E3.2  F1000.0 ; thin +40mm intro line @ 0.08
G1 X100.0 E6  F1000.0 ; fat +40mm intro line @ 0.15
G1 E-0.8 F2100; retract to avoid stringing
G1 X99.0 E0 F1000.0 ; -1mm intro line @ 0.00
G1 X110.0 E0 F1000.0 ; +10mm intro line @ 0.00
G1 E0.5 F1500; de-retract
G92 E0.0 ; reset extrusion distance
; Final print adjustments
M92 E282.54 ; adjust extrusion ratio
;M221 S{if layer_height==0.05}100{else}95{endif}

Each routine is commented. Here is a bit of clarification on what’s going on and what to expect:

  1. The extruder is first homed (G28 W) to get its bearings. The head is moved to the 0,0,0 position in the bottom-left-front of the bed.
  2. The hotend is set to a “no ooze” temperature (M104 S140) that will speed up the warming process, but not ooze filament all over the bed during leveling. I’m using 140C as a good no-ooze temp across most filaments.
  3. The heated bed is set to a PINDA warmup temp or your set bed temp (M140 Sxx), whichever is higher. This is to ensure that the bed is warm enough to warm the PINDA probe on a cold winter day in the next steps. If your prints never start, check to make sure this temperature is set high enough to guarantee PINDA warming. For more information see the Prusa Owner’s Wiki on GitHub.
  4. The extruder is raised and the bed moved forward (G0 X0 Y200 Z100.0 F10200) for nozzle and bed cleaning as the hotend is warmed. Once the extruder is raised, it will wait to either heat up or cool off to the no-ooze temp. This is important, as it ensures the PINDA is cooled before each print.
  5. One the hotend is warmed, the extruder is moved to the center of the bed (G0 X125 Y105 Z0.10 F10200) as it is lowered to a position where the PINDA probe can be warmed. It will remain in this position until the heated bed comes up to temperature, and longer if required for the PINDA probe to be warmed to a 35C temperature (M860 S35). Unfortunately, the Prusa firmware won’t allow custom status messages, so the printer will just appear idle at this point. You can monitor the PINDA temperature progress by pressing the front knob and selecting Settings->Temperature.
  6. Once the PINDA probe is warmed, the extruder will re-home (G28W) and execute the automatic bed leveling routine (G80).
  7. The extruder will return to the home position and sit while the hotend comes up to print temperature (M104 Sxx, M109 Sxx). If your selected bed temp is less than the no-ooze temp, it will be set here as well (M190 Sxx).
  8. Once the hotend comes up to temp, a custom prime line will be printed. I’ve made some tweaks to the bog-standard line:
    1. Linear Advance (M900 Kxx) is set to 0 to avoid distracting extruder clicks.
    2. 2mm of filament is extruded to prime the hotend (G1 E2 F1000).
    3. A 20mm “blort” of filament is extruded (G1 X20.0 E6 F1000.0) to snag any dangling ooze that remains.
    4. A 60mm thin segment is printed (G1 X60.0 E3.2 F1000.0).
    5. A 40mm thick segment is printed (G1 X100.0 E6 F1000.0).
    6. A short retract (G1 E-0.8), 1mm “wipe” (G1 X99.0 E0 F1000.0) and 10mm “coast” move is performed (G1 X110.0 E0 F1000.0) to avoid stringing, followed by a partial extrusion (G1 E0.5 F1500).
  9. Any final printer adjustments are made. I insert a command to tweak my extrusion ratio (M92 E282.54). Adjust for your printer.

At this point, the print will proceed normally.

I’m not a fan of the loud printer beeps, but I have inserted several chirp sounds (M300 S100 P10) to indicate progress throughout the print.

End G-Code

My end g-code is pretty standard. I like to reset any values that aren’t automatically cleared before a job:

  1. Linear Advance (M900 Kxx) is set to 0.
  2. Extrusion rate (M221) is set to 100%.

The rest is pretty standard Prusa g-code. Here’s my current end g-code:

Listing 2 Slic3r Prusa Edition end g-code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
; Last updated 20181027
G4 ; wait
G92 E0 ; prepare to retract
G1 E-5 F2100; retract to avoid ooze
M221 S100 ; reset extruder factor to 100%
M900 K0 ; reset linear acceleration
M104 S0 ; turn off temperature
M140 S0 ; turn off heatbed
M107 ; turn off fan
{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+60, max_print_height)}{endif} ; Move print head up
G1 X0 Y200 ; present bed
M84 ; disable motors
M300 S100 P10 ; chirp

Other custom G-Code

You can also embed custom g-code at before and after every layer change, on tool (nozzle) changes and between sequentially-printed objects.

Here’s an example of using before layer change G-code for changing temperatures on gaaZolee’s temperature calibration tower:

Listing 3 Slic3r Prusa Edition layer change g-code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
;BEFORE_LAYER_CHANGE
G92 E0.0
;layer_z is height of current layer in mm
;[layer_z]
{if layer_z == 91.6}M104 S220
{elsif layer_z == 81.6}M104 S225
{elsif layer_z == 71.6}M104 S230
{elsif layer_z == 61.6}M104 S235
{elsif layer_z == 51.6}M104 S240
{elsif layer_z == 41.6}M104 S245
{elsif layer_z == 31.6}M104 S250
{elsif layer_z == 21.6}M104 S255
{elsif layer_z == 11.6}M104 S260
{elsif layer_z == 1.6}M104 S265
{endif}

Here’s what’s going on:

  1. In this example, the tower prints normally up to 1.6mm height (the height of the tower base).
  2. At 1.6mm, the temperature is changed to the 1st test temperature (265C).
  3. Every 10mm thereafter, the temperature is decreased by 5C.

As written, this g-code depends on layers changing at exactly the specified heights. If you’re not using changes at exact multiples of your layer height, you will want to specify ranges using the <= and >= operators.

Contact and feedback

You can find me on the Prusa forums or Reddit where I lurk in many of the 3D printing-related subreddits.

Last updated on Nov 08, 2018