Using FullControlGcode on an Ultimaker 3
23 May 2023In which we try to use FullControl G-code to generate instructions for an Ultimaker 3 and waste an afternoon discovering the opacity of UM3 G-code.
Some Background
If you haven’t heard of FullControl Gcode, go check it out at fullcontrolgcode.com. It’s an intriguing piece of software that lets you skip the STL in 3D printing and directly generate printer instructions from a python script.
The Problem
I tried to get my feet wet with the following script adapted from the FCG tutorials, but no matter how hard I tried, the printer would just flash to the printing mode on its OLED screen before immediately reverting to the file selection screen.
import fullcontrol as fc
centre_point = fc.Point(x=100, y=100, z=0)
brimWidth = 5
start_radius = 10
end_radius = 10
start_angle = 0
n_turns = 20
pitch_z = 2
segments = 320
clockwise = True
steps = []
#Brim
steps.extend(fc.spiralXY(centre_point, start_radius+brimWidth, start_radius, start_angle, 10, 360, False))
#Helix
steps.extend(fc.helixZ(centre_point, start_radius, end_radius, start_angle, n_turns, pitch_z, segments, clockwise))
filename = '2023-05-16.01'
printer = 'generic'
#printer options: generic, ultimaker2plus, prusa_i3, ender_3, cr_10, bambulab_x1, toolchanger_T0, toolchanger_T1, toolchanger_T2, toolchanger_T3
print_settings = {'extrusion_width': 0.5,'extrusion_height': 0.2, 'nozzle_temp': 215, 'bed_temp': 60, 'fan_percent': 100}
#'extrusion_width' and 'extrusion_height' are the width and height of the printed line)
fc.transform(steps, 'gcode', fc.GcodeControls(printer_name=printer, save_as=filename, initialization_data=print_settings))
After some finagling and google-fu, I figured out that the issue was with the header lines Cura generates. These tell the printer useful info about the print it’s about to start for functional reasons as well as (I assume) letting the printer show print time and filament usage estimates on its screen without having to parse and analyse a whole G-code file on the fly.
The header lines generated by cura look something like this:
;START_OF_HEADER
;HEADER_VERSION:0.1
;FLAVOR:Griffin
;GENERATOR.NAME:Cura_SteamEngine
;GENERATOR.VERSION:5.2.1
;GENERATOR.BUILD_DATE:2022-10-19
;TARGET_MACHINE.NAME:Ultimaker 3
;EXTRUDER_TRAIN.0.INITIAL_TEMPERATURE:240
;EXTRUDER_TRAIN.0.MATERIAL.VOLUME_USED:10213
;EXTRUDER_TRAIN.0.MATERIAL.GUID:eff40bcf-588d-420d-a3bc-a5ffd8c7f4b3
;EXTRUDER_TRAIN.0.NOZZLE.DIAMETER:0.4
;EXTRUDER_TRAIN.0.NOZZLE.NAME:AA 0.4
;BUILD_PLATE.INITIAL_TEMPERATURE:60
;PRINT.TIME:5972
;PRINT.GROUPS:1
;PRINT.SIZE.MIN.X:9
;PRINT.SIZE.MIN.Y:6
;PRINT.SIZE.MIN.Z:0.27
;PRINT.SIZE.MAX.X:182.58
;PRINT.SIZE.MAX.Y:209.42
;PRINT.SIZE.MAX.Z:48.07
;SLICE_UUID:616551fb-4680-4057-8bcf-28e64d25e6b9
;END_OF_HEADER
If the header is not present or does not match some specific requirements the printer will flat out refuse the print. Fortunately for us, the UM3 doesn’t seem to notice if we splice this header on to our own, FCG-generated, code.
There is a semi-handy guide here that helps us figure out some of the what and why, but alas, the post is already almost 7 years old and some of the requirements appear to have changed.
For instance, EXTRUDER_TRAIN.{X}.MATERIAL.GUID, doesn’t appear to be optional anymore, and SLICE_UUID seems to be newer than this post and also mandatory.
So what to do?
Fortunately the fix is easy, if a bit fiddly.
- Using Cura, slice an arbitrary STL file and save the G-code somewhere where you can find it later.
- The exact file doesn’t matter, just make sure you pick the extruder you want to actually use for your FCG print, and the correct material (and therefore temperature) settings.
- Using FCG, generate your G-code with
printer = 'generic'
set to generic when you runfc.GcodeControls(printer_name=printer, save_as=filename, initialization_data=print_settings)
- Open both files in the plaintext editor of your choice.
- Copy the header from the Cura-generated file into your FCG-generated file, making sure line 1 reads
;START_OF_HEADER
. Positioning the header further down the file will most likely not work. - Delete the default
; Time to print!!!!! ; GCode created with FullControl - tell us what you're printing! ; info@fullcontrol.xyz or tag FullControlXYZ on Twitter/Instagram/LinkedIn/Reddit/TikTok
in your file. - Tweak the following header lines in your FCG-generated file (code block for easy copy & paste):
;EXTRUDER_TRAIN.0.MATERIAL.VOLUME_USED:0 ;PRINT.TIME:0 ;PRINT.GROUPS:1 ;PRINT.SIZE.MIN.X:0 ;PRINT.SIZE.MIN.Y:0 ;PRINT.SIZE.MIN.Z:0 ;PRINT.SIZE.MAX.X:215 ;PRINT.SIZE.MAX.Y:215 ;PRINT.SIZE.MAX.Z:200
- Why?
- EXTRUDER_TRAIN.0.MATERIAL.VOLUME_USED
- Set this to 0. Prevents bogus filament usage estimates.
- PRINT.TIME
- Set this to 0. Prevents bogus time remaining estimates.
- PRINT.SIZE.MIN.X/Y/Z
- Set all of these to 0. I have no idea if the UM3 checks whether its print moves fall inside the min/max footprint, but I cargo-cult the values anyway because I couldn’t be bothered checking for the sake of six values. If you figure it out, please let me know.
- PRINT.SIZE.MAX.X/Y/Z
- Set to the print envelope of the UM3, i.e. 215 x 215 x 200 for the regular version, or 215 x 215 x 300 for the UM3 extended.
- EXTRUDER_TRAIN.0.MATERIAL.VOLUME_USED
- Presto Printo, your G-code should now work on your UM3.
Example of an edited UM3 g-code header:
;START_OF_HEADER
;HEADER_VERSION:0.1
;FLAVOR:Griffin
;GENERATOR.NAME:Cura_SteamEngine
;GENERATOR.VERSION:5.2.1
;GENERATOR.BUILD_DATE:2022-10-19
;TARGET_MACHINE.NAME:Ultimaker 3
;EXTRUDER_TRAIN.0.INITIAL_TEMPERATURE:240
;EXTRUDER_TRAIN.0.MATERIAL.VOLUME_USED:0
;EXTRUDER_TRAIN.0.MATERIAL.GUID:eff40bcf-588d-420d-a3bc-a5ffd8c7f4b3
;EXTRUDER_TRAIN.0.NOZZLE.DIAMETER:0.4
;EXTRUDER_TRAIN.0.NOZZLE.NAME:AA 0.4
;BUILD_PLATE.INITIAL_TEMPERATURE:60
;PRINT.TIME:0
;PRINT.GROUPS:1
;PRINT.SIZE.MIN.X:0
;PRINT.SIZE.MIN.Y:0
;PRINT.SIZE.MIN.Z:0
;PRINT.SIZE.MAX.X:215
;PRINT.SIZE.MAX.Y:215
;PRINT.SIZE.MAX.Z:200
;SLICE_UUID:616551fb-4680-4057-8bcf-28e64d25e6b9
;END_OF_HEADER
Feedback
I’d like to give two small pieces of feedback to the development of FCG. (I know, everyone’s a critic, and I appreciate that these are low priority issues.) 1, please let us prevent FCG from printing the following lines:
; Time to print!!!!!
; GCode created with FullControl - tell us what you're printing!
; info@fullcontrol.xyz or tag FullControlXYZ on Twitter/Instagram/LinkedIn/Reddit/TikTok
If you have to muck about with the header like you do here, it would be great not to have to delete it manually all the time.
2, please make the default date+time filename optional too. (Yes, I saw the Reddit poll, but I was too late to participate.) With either of these two changes, it would be trivial to include the header in the python script and generate it automatically in the FCG G-code, without having to copy and paste every time.
To the Ultimaker team, please post some sort of updated guide to the G-code header structure. It would’ve saved me a lot of time. At the very least, let the firmware give a “G-code header invalid” error instead of failing silently. That would’ve put me on track immediately.
Closing remarks
I’d like to thank Andy Gleadall for publishing this tool, and for doing it under the generous terms he chose to share it under. FFF hardware has reached a high level of maturity, but I feel like the slicing tools have not had the same pace of progress until recently. People like Andy are really unlocking the next level for FFF tech, and that’s beyond cool, especially if it’s open to all.