Useful G-Code Commands for the MPCNC

There are many g-codes that are helpful to know (particularly when configuring a dual endstop setup), but they are scattered across the site and buried in the Marlin G-code Index. I figured it would be handy to have them all on one page.

This list is by no means 100% complete or accurate (at this point), and does not address the MP3DP or the LowRider at this point. Please speak up if you have something to add and I will edit this post to reflect your addition. If something is not listed here, you will probably find it if you dig in the Marlin G-code Index.

Feel free to copy, remix, and use this content wherever you want.

[I encourage MPCNC veterans to pick this document apart. Despite my efforts, I am sure to have screwed up some piece of info somewhere.]



This guide was made using Ryan’s Marlin-based MPCNC firmware. This information may not work on custom firmware flashed onto the device.

I have used OctoPrint as my g-code sender while testing all this info. If you are using Repetier Host or any other g-code sender, please let me know if any of this info does not work for your program. There shouldn’t be any surprises though (I hope!)

All measurements are in mm unless otherwise specified.


Cautionary Notes

A few words of warning before we begin:

  • Exercise caution when executing any g-code command, especially for the first time. Unexpected results can and do happen.
  • Ensure your toolhead is not touching the table when making any movements. Always do a z-raise first.
  • G-code movements may ignore software endstops. Make sure your commands do not cause the machine to attempt movement past it’s own boundaries.


Commenting Your G-Code

The semicolon character “;” is used to indicate the end of a command. Any text following after a semicolon (and before a new line) will be ignored by the software, which makes it a handy place for comments. This is particularly useful when making batch scripts.


  • A line that begins with a semicolon will be treated as a comment.
  • G-code instructions do not require a semicolon (in Marlin, at least). They are only necessary for commenting.
  • Related: To display messages on the LCD screen, use the M117 command. (e.g. M117 Hello world!)

G-Code Examples

The following are all legitimate g-codes because of the placement of the semicolon, and should not cause an error:

G0 F300; Set feedrate to 300 mm/min
; G0 Z1000 (This line will do nothing because it comes after the semicolon.)
G0 Z0; Move Z-axis to origin


G0/G1 - Linear Move

Move continuously in a straight line until reaching your input coordinates.

X[pos] - X position (e.g. X5, X5.2, X-7)
Y[pos] - Y position (e.g. Y5, Y5.2, Y-7) 
Z[pos] - Z position (e.g. Z5, Z5.2, Z-7)
F[rate] - Feedrate, ie. movement speed (default is in mm/min) (e.g. F1800)


  • Any combination of input parameters can be used or omitted as needed.
  • Although G0 and G1 are functionally identical, the Marlin docs say that G0 is designated for rapid travel (“non-print”) moves. In general, just use G0 to be on the safe side in case anything changes in the future.
  • When the machine is powered on, the current coordinates of the toolhead is designated as X0 Y0 Z0. (The LCD will show flashing question marks until the axes have been homed.)
  • Movements can be entered to a precision of 0.1mm [Adjustments in the range of 0.01 mm appear to have no effect and do not engage the steppers. Please correct me if this is wrong.]
  • The feedrate will be preserved until changed by another g-code or the machine is powered off.
  • Keep your feedrate low when doing z-moves so you don’t crash into the table too quickly.

G-Code Example:

Go to coordinates (X5, Y7.2, Z0) at a speed of 2100 mm/min:

G0 X5 Y7.2 Z0 F2100


G28 - Auto Home (X/Y/Z axis)

Perform a homing procedure on one or more axes. Requires endstops and/or a touch plate to send the homing signal. (X/Y homing uses endstops, Z homing uses a touch plate.)

R - Distance to raise the Z-axis before homing (e.g. G28 R5 X Y)
X - Home the X-axis (e.g. G28 X)
Y - Home the Y-axis (e.g. G28 Y)
Z - Home the Z-axis (e.g. G28 Z)


  • Entering G28 with no parameters will home all 3 axes one-by-one. (You probably don’t want to do this.)
  • Parameters can be combined to level two or more axes one-by-one (e.g. G28 X Y or G28 X Y Z)
  • Newer versions of MPCNC firmware have the R parameter set automatically but it can be overridden if desired. It is a good idea to include an R parameter that allows for safe clearance in your homing operations.
  • Don’t use G28 Z without a touch plate underneath! Your Z-axis will force itself into the table until you power off the machine!
  • After homing the Z-axis, use G92 Z[touch plate thickness in mm] to set the true Z-origin of your workpiece. (For a 1.5 mm thick touch plate, this will be G92 Z1.5.) Then use G0 Z5 F300 to allow for clearance so you can remove the touch plate and clamp. Then use .
  • For more details about setting up endstops, see Ryan’s page on the subject.

G-Code Example:

Home the X and Y axes, but first raise the Z-axis by 5mm:

G28 R5 X Y


G92 - Set Position

Set the current position in firmware. Useful when zero’ing your coordinates before starting a job.

X[pos] - X position (e.g. X5, X5.2, X-7)
Y[pos] - Y position (e.g. Y5, Y5.2, Y-7) 
Z[pos] - Z position (e.g. Z5, Z5.2, Z-7)


  • If you do not use endstops, you can simply jog your machine to the desired starting position for your cut, then enter G92 X0 Y0 Z0;. This will zero every axis.

G-Code Example

Reset all coordinates to zero:

G92 X0 Y0 Z0


M106 - Enable Cooling Fan/Set Fan Speed

Manually enable cooling fan(s) and set speed.

P[index] - Fan index (labeled on electronic board, e.g. my cooling fan is on P2.)
S[speed] - Speed (range 0-255), will default to 255 if S parameter is not provided


  • This feature can also be configured to run automatically by editing the firmware before flashing.
  • You should be able to add the g-code to your CAM software’s post-processor. You can also add it to your g-code files manually.
  • Some fans may not function properly at any speed other than the maximum speed. Don’t use the S parameter if this happens to you, just use the fan at full speed.

G-Code Example

Set the fan on the FAN2 header to full speed:

M106 P2 S255


M107 - Disable Cooling Fan

Manually disable cooling fan(s).

P[index] - Fan index (Same as M106)

G-Code Example

Disable the fan connected to the FAN2 header:

M107 P2


M119 - Endstop Status

Reports whether each endstop is open or closed. Useful when configuring endstops, or when debugging homing issues.

Parameters: None


  • For dual endstops, X1 will use the X-MIN endstop, and X2 will use the X-MAX endstop (labeled on the board, as seen in this picture). Same deal for the Y axes.
  • When using a touch plate, use the Z-MIN endstop header on your board.
  • For more info on configuring endstops, check out Ryan’s page here.

G-Code Example



M666 - Software-based Endstop Offset

Ryan’s dual endstop page is the go-to guide for using M666 to square your X and Y axes:

Auto Square, Dual EndStops

The unfortunately designated M666 lets you test your offset to quickly calibrate your machine. Using the command M666 X0.72 would offset the X1 stepper 0.72mm away from it’s endstop, Y! can also be used. To verify your current settings during calibration just an M666 will show the current offsets. Once the correct offset are found you should input them into your firmware.

This is to simplify the actual placement of the endstops themselves, you only need to get them such that the X1 or Y1 endstop is at or slightly behind where it needs to be within a few Millimeters is best.

1-You can verify how square your axis is by measuring the diagonals of the largest rectangle you can draw in your build area. The larger the more accurate…but also harder to measure. I only have 6″ calipers but I was more accurate with a tape measure at my 440mm available diagonal.

2-Measure the diagonals to the X1 and Y1 endstops blocks.

3-Offset the endstop that has the short dimension by the amount it is short or just a hair over. So if the X1 diagonal was 1mm short you would offset X1 by 1mm. M666 X1. Tip – If it is more than 2mm off move the stop block, each belt tooth is 2mm.

4-Draw a fresh one to verify. If that is correct you should edit your firmware to make this change permanent in configuration.h Or add it to all of your Gcode.


Care should be taken to use as little pen pressure as possible with the finest tip possible to get the most accurate results and a pen mount with some give should be used, example pen mount.

My trials and tribulations figuring this out….Feel free to make fun of me. Forum link.

In short, this command is used to set an offset on your X2 stepper. For example, a 0.5 mm offset will, after homing, move your X2 stepper over by +0.5mm and call that the zero point. This is used to ensure the Y-axis is square to the X-axis (i.e. exactly 90 degrees).

X[adj] - X-axis adjustment
Y[adj] - Y-axis adjustment (Not used in Ryan's instructions)


  • After dialing in your offset, use the command M500 to save your settings in the EEPROM. If you don’t do this, your M666 values will be reset to zero when the machine is powered off.
  • To check your current M666 offsets, use the command M503.
  • If you decide to reset your offsets to zero, you can either use the M502 command or enter M666 X0 Y0.
  • M666 offsets affect only your X2 and Y2 endstops, not X1 or Y1. Note that Ryan’s procedure does not use the Y parameter.
  • Instead of using M666, you can just move your endstops if you don’t want to do this in software. Use whichever method suits you.

G-Code Example

Set the X2 offset to 0.5mm:

M666 X0.5


Honorable Mentions

The following g-codes ended up being useful in some scripts I made, and generally seem useful to know about. However, I feel the ones listed above are more important, and I didn’t want to clutter up the list. Each item below contains a link to the Marlin G-code Index, and should have all the info you need.

G4 - Dwell
G90 - Use absolute coordinates for positioning
G91 - Use relative coordinates for positioning
M18/M84 - Disable Steppers
M117 - Display Message on LCD Screen
M211 - Enable/Disable Software Endstops
M300 - Play Tone (Beep)
M502 - Factory Reset EEPROM
M503 - Report EEPROM Settings
M504 - Validate EEPROM

[Again, please let me know if anything is missing, wrong, or needs clarification. I hope it helps someone to have all this info in one place!]

This work is licensed under a Creative Commons Attribution 4.0 International License.


Re: G0/G1, Marlin treats them the same, but other controllers don’t (grbl). Go ahead and use them correctly, G0 for travel moves, G1 for cutting moves. If Marlin ever becomes “compliant”, your gcode will begin cutting way too fast if everything is G0.


Thank you. I will be referring back to this. could you wrap this up into a tidy gcode that I can carve into my spoil board? LOL


Have you seen the doc page about gcode?

Maybe that could be expanded a little?

Nope, that is the first reference to it that I’ve seen. I’m surprised I never saw a reference to that during all the time I spend traversing the web for a lot of this info.

Noted. Thank you.

I made it about a week ago. So it is easy to miss.

That’s a relief… I would have felt pretty dumb if that was sitting there the whole time. I started this about a week ago also.


Any thoughts on how best to combine them?

Yours provides a better overview of what gcode is, while mine is more of a how-to for each command (plus comments). I actually had some more introductory info, but I removed it since I felt it could be extra baggage for someone who already understood the concept but just needed the reference material.

My first thought is that it would be better to have a general “What is G-code” type page that could then lead to a “gcode cookbook” page for each different V1 project (MPCNC, Lowrider, MP3DP, ZenXY)… If everything got lumped into one big page, I could see it being a pain to navigate. There’s definitely a sweet spot somewhere.

I also think a page for batch scripts would be handy as well. I’m not an expert in that regard though, and that one is more of a back-burner thing in my mind (for now, at least).

1 Like

I like the idea of a cookbook. LR and MPCNC should be the same. The Zen is maybe the most basic subset. MP3DP is pretty much the whole Marlin page. So I can justify just having one for cnc and nothing else.

What do you mean batch files? Like windows .bat files? Is there something you are automating that is related to cnc?

Ah, sorry, I’m probably mangling the terms. I just mean multi-line gcode scripts, e.g. I have one that parks the router at a specific place on the table before I shut it down. That sort of thing.

Ah, like gcode recipes, or scripts.

1 Like

Dang, I like this.

Maybe we merge them? The docs is like a list of the most common commands we would see, and this seems to break out the most common ones we would interact with (by hand) into new user friendly words??? Or add it as a new page and link them just like Marlin is linked? Just an idea you two are the creators of them so just let me know if you need me for anything.

Thanks Nick!

My pleasure, Ryan, I’m glad to see it’s a welcome addition.

You can do what you want with the info, I threw a CC license on it so you can do with it as you please. I don’t “own” the material, this stuff is there to help others. I’m also not familiar with pull requests and all that jazz.

My thoughts are that it would make sense to have this in the docs somewhere, as I mentioned in another post. I’m not sure if it makes more sense to have one g-code page or to split them up, for example:

  1. What is G-Code?
  2. How to execute G-Code [OctoPrint, etc…]
  3. G-Code Commands
  4. G-Code Scripts [i.e. fancy multi-line scripts]

I realize that g-code is sort of a sub-topic of software and not the other way around… I’m just trying to point out that a single document could become rather unwieldy if scope creep really sets in.

At any rate, feel free to put this in the docs. I guess we could nuke this thread as well since it would just distract from the actual documentation section. I see that the GitHub “Issues” section seems to be a good place for any meta-related chatter on the documentation subject so I don’t know if there is a need for this thread to stick around. (I hate when you find, for example, multi-page threads on some forums that go back years since any useful info gets buried in there. Not if there’s a more navigable alternative to find what you need to know…)

My only request is that the links to the docs be made more overt… There could be a link from that little hamburger menu in the top right on the forum page (Next to the FAQ). Also the main menu on the V1 homepage (Where it says Home/Shop/Media/Forums/Contact) should have a link as well. As it stands, I feel there isn’t enough attention drawn to their existence. (I do see that they are very new tbf…)

1 Like

Every few days I am swapping out links from the main site to the “docs” equivalent. Github has a bandwidth limit and I am not sure how to check where we stand, I am also checking to see if there are any complaints in the process. I am not trying to make more problems for myself so slow and steady is most comfortable for me.

Okey dokey, I figured you were on top of it but wanted to mention just in case. :+1:

1 Like

I’m running Vectric Aspire & would like to run a post process between each tool path to change bits over.

If I wanted my router bit to go back to the X0 Y0 Z0 pos. that I positioned at start of cut with
G92 X0 Y0 Z0
Would I simply place "G28 R5 X Y " at the end of my code so it looks like the following

G92 X0 Y0 Z0
-— my lines of G-code here for toolpath 1
G28 R20 X Y ; return to start pos.
---- my lines of G-code here for toolpath 2
G28 R20 X Y ; return to start pos.
---- my lines of G-code here for toolpath 3
G0 X0 Z50 F2100 ; Return Home and move up 50 in Z
M18 ; disable stepper motors
M300 ; Beep Sound to signify completion

This should return to the start & lift the bit so it sits 20 above the surface so I can change the bit ready for the 2nd cut to commence… yes ?

G28 is going to execute the homing sequence where your machine will seek out it limit switches and reset (0,0) to the machine origin. The only way your code will work is if you have a fence you use to mount your stock, and if the corner of the fence used as a reference is 0,0 on your machine. I’ve only seen one machine on this forum setup that way. Since you do a G92 X0 Y0 Z0 at the beginning before you run toolpath 1, the easiest thing would be to just execute an G0 or G1 and move to 0,0. If you want to raise up, just pick your clearance height and put it in Z. So if you want 20mm of clearance, you could do:

G0 X0 Y0 Z20 F2100

There are more complex scenarios you could execute where you could home to the limit switches but still preserve the relative 0,0 of your stock using Workspaces (G54 - G59.3).

Personally I go low tech and separate each tool into its own file.

2 year thread revival!

G92 X0 Y0 ZZ0
(blah blah blah, toolpath 1.)
G0 Z50; Go up to 50mm above starting point
G0 X0 Y0; return to starting point for X and Y
M0 'Ready for toolpath 2'; wait for controller blip to continue
(blah blah blah)

The problem with this is that if you are changing tools, you probably need to re-zero your Z axis. If you have those tool changer rings on your bits, it’s probably OK. I remove them to have the most usable cutting depth available, so it doesn’t work for me.

Most of the time, I do one file per tool as well. It gives me more options to re-zero my work space, but I do have a tool change routine:

G92 X0 Y0 Z0
(blah blah blah)
G0 Z50 F450; Raise the gantry
G0 X0 Y0 F6000; return to origin point
M5; Spindle off if it's controlled by Marlin
M0 "Change Tool"; display message and wait
M0 "Attach Z probe"; display message and wait
G28 Z; re-home Z axis at origin point
G0 Z50 F450; raise gantry
M0 "Remove Z probe"
M3; Spindle on if it's controlled by Marlin
G0 Z5; return to clearance plane
(blah blah blah)