Skip to content

Instantly share code, notes, and snippets.

@rmeissn
Last active April 4, 2025 04:34
Show Gist options
  • Save rmeissn/f24294a20b57c870abf1c9e760e54954 to your computer and use it in GitHub Desktop.
Save rmeissn/f24294a20b57c870abf1c9e760e54954 to your computer and use it in GitHub Desktop.
Flashforge Adventurer 3 Cura

The firmware of the Flashforge Adventurer 3 seems to understand only a subset of typical marlin gcode:

  • no G0 support (use G1 instead)
  • if XYZ coordinates are combined within G1, the bed leveling mesh seems to be ignored (use two G1 (one for Z and one for XY) instead)
  • M140 does not support decimal point numbers (only e.g. S50 instead of S50.0)
  • M104 does not support decimal point numbers (only e.g. S50 instead of S50.0)
  • no relative E value support (cura produces absolute E values either way)
  • a Z-Offset needs to be included in each Z coordinate if required (use cura Z-Offset plugin and tick "extensive z-offset processing")

-> I've created a bash script to convert cura gcode to flashforge gcode. I'm not sure I've covered all edge cases, but it seems to work.

X: 150mm
Y: 150mm
Z: 150mm
Build_Plate: Rectangular
Origin at Center: Tick
Heated Bed: Tick
Heated Build Volume: false
G-Code Flavor: Marlin
xmin: -20
ymin: -10
xmax: 10
ymax: 10
gantry hight: 150
no of extruders: 1
Apply Extruder Offset: Tick
M104 S0 T0 ; Hotend to 0°C
M140 S0 T0 ; Bed to 0°C
G162 Z F1800 ; Move Z Axes to Maximum
G28 X Y ; Home XY
M132 X Y A B ; Recall home offsets
M652 ; ???
G91 ; Relative Positioning
M18 ; Disable Steppers
M107 ;Turn-off fan
M140 S{material_bed_temperature} T0
M104 S{material_print_temperature} T0
M104 S0 T1 ; Tool 1 to 0°C
M107 ; Fan off
M900 K0.000 T0 ; K-Factor to 0
G90 ; Absolute Positioning
G28 ; Home XYZ
M132 X Y Z A B ; Recall home offsets
G1 Z50.250 F420 ; Move Z to 50mm
G161 X Y F3300 ; Move Axes to Minimum
M7 T0 ; Stabilize bed temperature
M6 T0 ; Stabilize extruder temperature
M651 S255 ; Set case fan on
M108 T0 ; Break and Continue
#!/bin/bash
# use as: transform_cura_to_flashforge.sh xxx.gcode
ConvertedGCode=$(cat $1)
# replace temperature of kind xx.0 to just xx
M140=$(echo "$ConvertedGCode" | grep M140)
while IFS= read -r line; do
convertedLine=$(echo "$line" | sed -E 's/S([0-9]+)\.0/S\1/g')
ConvertedGCode="${ConvertedGCode//$line/$convertedLine}"
done <<< "$M140"
M104=$(echo "$ConvertedGCode" | grep M104)
while IFS= read -r line; do
convertedLine=$(echo "$line" | sed -E 's/S([0-9]+)\.0/S\1/g')
ConvertedGCode="${ConvertedGCode//$line/$convertedLine}"
done <<< "$M104"
# seperate each G0 with Z coordinate into two G1 commands
linesWithZ=$(echo "$ConvertedGCode" | grep G0 | grep ' Z.*\.')
while IFS= read -r line; do
# Extracting relevant parts
speed=$(echo "$line" | awk -F '[ ;]' '{print $2}')
x=$(echo "$line" | awk -F '[ ;]' '{print $3}')
y=$(echo "$line" | awk -F '[ ;]' '{print $4}')
z=$(echo "$line" | awk -F '[ ;]' '{print $5}')
# Creating the new lines
z_line="G1 F420 ${z}0"
xy_line="G1 $speed $x $y"
# Printing the new lines
replacement=$(printf "%s\n%s\n" "$z_line" "$xy_line")
#echo "$line"
#echo $replacement
# Replacing within the original text
ConvertedGCode="${ConvertedGCode//$line/$replacement}"
# the following lines are currently not working
#ConvertedGCode=$(echo "$ConvertedGCode" | sed -e "s/\$line/\$replacement/g")
#ConvertedGCode=$(echo "$ConvertedGCode" | sed -e "s/$line/$replacement/g")
done <<< "$linesWithZ"
# Convert each remaining G0 to G1
ConvertedGCode=$(echo "$ConvertedGCode" | sed -e 's/G0/G1/g')
ending='.gcode'
convertedFile=${1%$ending}\-converted.g
echo "$ConvertedGCode" > $convertedFile
@dbaarda
Copy link

dbaarda commented Nov 14, 2024

Thanks for this excellent resource, I've not been able to find something quite so complete anywhere else. You have one minor gap I can help fill.

You have M651 S255 as "Set case fan on". You can also use values 0 to 255 to set the case fan speed. Note this is the fan in the roof of the Adv3 that vents air out of the enclosure. For materials like ASA where you want the enclosure heated you'll want to turn this down or even better turn it off.

You have M652 marked as "???". It turns off the case fan. You want this in your initialisation for things like ASA.

Now a question; you have M108 T0 as "Break and Continue", but what exactly does that mean? Doc's like https://marlinfw.org/docs/gcode/M108.html don't mention any T0 argument, and seem to indicate it's like a way to automatically emulate hitting a "continue" UI button in gcode. I don't really get why it might be needed in the start code though.

I note that FlashPrint puts this as the first line for it's start code, where the numbers are the dimensions of the model in mm;

M118 X21.78 Y17.51 Z10.90 T0

Which I think displays this info on the console. Again https://marlinfw.org/docs/gcode/M118.html doesn't seem to match this, with no mention of any of these args, but it's interesting that it has the T0 again. Perhaps this actually ends up displaying a prompt, and M108 T0 is required for it to actually start the print? In which case maybe this has been cargo-cult'ed from flashprint gcode and is not required if you don't have an M118 X21.78 Y17.51 Z10.90 T0?

@rmeissn
Copy link
Author

rmeissn commented Nov 15, 2024

Many thanks for your comments!
I've taken most of the start gcode from generated files of flashprint. I did not find documentation on some commands (like M118 T0 that you mentioned) and did not test all of these in terms of optionality. FlashForge seems to use some custom gcode format that is forked from marlin (maybe not marlin, but RapRap).
You can easily test whether M118 T0 is required by deleting it from the resulting file and printing it.

@dbaarda
Copy link

dbaarda commented Nov 19, 2024

I note that FlashPrint puts this as the first line for it's start code, where the numbers are the dimensions of the model in mm;

M118 X21.78 Y17.51 Z10.90 T0

Which I think displays this info on the console. Again https://marlinfw.org/docs/gcode/M118.html doesn't seem to match this, with no

After playing with this, it seems M118 X<xx.xx> Y<yy.yy> Z<zz.zz> TO actually gives the printer a print-volume boundary within -xx.xx <= X <= xx.xx, -yy.yy <= Y <= yy.yy, and 0.00 <= Z <= zz.zz for the following gcode. If this exceeds the printer's build volume, or any of the gcode instructions after that go outside those boundaries, the file will fail validation and be rejected by the printer. Flashprint gives an error about going out of bounds, cannot be printed by this printer.

So it definitely doesn't do what the docs at https://marlinfw.org/docs/gcode/M118.html say.

@rmeissn
Copy link
Author

rmeissn commented Nov 19, 2024

As a simple workaround: it would enough to set M118 to the max build volume to prevent such errors. I don't see the point in restricting it to anything smaller than the build volume...

@dbaarda
Copy link

dbaarda commented Nov 24, 2024

Yeah, that's what I do, but I guess you could just as easily omit the M118 instruction entirely. One minor advantage is it can be a sanity check when generating your own gcode; you can put the M118 command in with the dimensions you intend on fitting within, and if something goes wrong it'll tell you by rejecting the gcode.

@dbaarda
Copy link

dbaarda commented Apr 4, 2025

I have some other observations that maybe belong in the README.md;

  • No end-of-line comments. if there is a ; anywhere on the line, the whole line is ignored.
  • The M106 extruder fan-on cmd does not support a S<0-255> fan speed argument. The fan can only be on or off.
  • The M106 and M107 fan-on and fan-off cmds are executed as the gcode is parsed and are not injected into the "execution buffer". This means they will execute in advance of the print commands that come before them. You can notice this with the "fan on after first layer" option in flashforge, where the fan will turn on well before the first layer has finished printing, even though the M106 cmd is in the gcode at the start of the second layer, and the fan always turns off before printing has finished even though the M107 cmd is at the very end.

There are some other things I've noticed that I'm unsure about;

  • I'm not entirely sure, but I suspect other cmds you would "normally" only execute at the start or end of a print might also be executed at "parse time". So this could apply to many of the cmds in start.gcode and end.gcode fragments.
  • The M900 pressure-advance cmd doesn't seem to do anything, and probably the Adv3 doesn't actually support pressure advance. I did a heap of tests to try and calibrate pressure advance and although I could see definite signs it would help improve prints, changing the pressure advance setting with the K<value> argument didn't seem to make any difference. However, in retrospect it might have been because my testing made some mistakes;
    1. it's possible the M900 cmd is executed at parse-time like M106 and M107 are, in which case my tests which tried printing accelerating/decelerating lines with different Kf values would have probably whipped through all the different Kf settings, leaving it at the last set value before any of the lines even started printing.
    2. Its possible the Adv3 implements V1.0 Linear Advance where the kfactor is advance_steps / delta_extrusion_speed, not the newer V1.5 Linear Advance where kfactor is advance mm / speed mm/s. This means my tests using new-style 0.0 <= kfactor <=2.0 values would be using a value too small to make a difference. The old-style values would need to be 0.0 <= kfactor <= 200.0.
    3. Maybe the Adv3 implements EXTRA_LIN_ADVANCE_K and the setting only becomes active after executing M900 S0.
    4. It's possible the M900 cmd only kicks in after one of the other start.gcode cmds are executed, like G28 or M108 T0 or M132 X Y Z A B. My tests were just putting M900 cmds between printing each line.

I will one-day try and re-test the M900 cmd taking those possible mistakes into account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment