Setting up a GRBL controller without knowing your M-codes is like trying to cook a meal without knowing what any of the buttons on the stove do. You might get lucky, but more often you'll burn something, stall a motor, or crash a spindle into your workpiece. An M-code reference chart specific to GRBL gives you a quick, reliable lookup so you can write and troubleshoot your G-code programs with confidence instead of guessing or constantly searching through forum threads.

What Are M-Codes and Why Do They Matter for GRBL?

M-codes are machine-level commands in CNC programming that control functions outside of tool movement things like turning the spindle on or off, enabling coolant, or stopping a program. While G-codes tell the tool where to go, M-codes tell the machine what else to do along the way. If you're working with a GRBL-based CNC router, laser engraver, or mill, understanding M-codes is the difference between running a clean job and dealing with unexpected stops or errors.

GRBL is an open-source motion control firmware that runs on Arduino-based boards. It interprets a subset of standard G-code and M-code commands. The key word there is subset. GRBL does not support every M-code you'll find in industrial CNC controllers like Fanuc or Haas. This is where many beginners run into trouble they grab a generic M-code chart from the internet and try to use commands their GRBL controller simply doesn't recognize.

Which M-Codes Does GRBL Actually Support?

GRBL's supported M-code list is intentionally small. Here's a straightforward reference chart of the M-codes that work on standard GRBL firmware:

  • M0 Program Pause (unconditional stop)
  • M1 Optional Program Pause (pauses if the optional stop switch is on)
  • M2 End Program
  • M3 Spindle On, Clockwise (CW)
  • M4 Spindle On, Counter-Clockwise (CCW) used in laser mode for variable power
  • M5 Spindle Stop
  • M6 Tool Change (requires configuration in some GRBL forks)
  • M7 Mist Coolant On
  • M8 Flood Coolant On
  • M9 All Coolant Off
  • M30 End Program and Rewind

That's it. If you send something like M6, M7, or M8 without proper pin configuration or a GRBL fork that supports them, you'll likely get an error or no response at all. For a deeper breakdown of how to actually read and interpret these codes in your programs, understanding how to read M-codes in CNC programming can help fill in the gaps.

How Is GRBL's M-Code Support Different From Industrial CNC Controllers?

Industrial CNC machines might support hundreds of M-codes, many of them manufacturer-specific. A Fanuc controller, for example, uses M-codes for automatic tool changers, pallet changers, bar feeders, and dozens of custom auxiliary functions. GRBL was designed for simpler machines desktop CNC routers, small mills, and laser engravers so its M-code set reflects that.

Here are a few M-codes you won't find in stock GRBL:

  • M98/M99 Subprogram call and return (common in Fanuc controls)
  • M50 through M99+ Custom auxiliary M-codes used by machine builders
  • M41/M42 Gear range selection (for machines with geared spindles)

If your post-processor is generating M-codes outside of GRBL's supported list, your controller will throw an error. This is one of the most common issues people hit when switching from a simulator or industrial CAM software to a GRBL-based setup. You need to either adjust your post-processor or manually edit the output to strip unsupported codes.

When Should You Reference an M-Code Chart During Setup?

You'll reach for an M-code reference chart at a few specific points:

  1. During initial controller configuration You need to know which M-codes your firmware version supports before wiring spindle relays, coolant pumps, or laser modules to specific pins.
  2. When writing or editing G-code by hand If you're manually coding toolpaths (common for simple 2D cuts or laser jobs), you'll insert M3/M5 commands to control the spindle or laser.
  3. When debugging a failed job If your program stops mid-run with an error, checking whether an unsupported M-code is in the file is one of the first things to troubleshoot.
  4. When switching between GRBL versions or forks Grbl-Mega, grblHAL, and other forks add extra M-code support. What works on one version may not work on another.

Keeping a printed or bookmarked chart near your workstation saves real time. Instead of opening a browser tab every time you need to check whether M4 is clockwise or counter-clockwise, you just glance at the sheet.

What Do the Most Common M-Codes Actually Do in Practice?

Let's walk through the M-codes you'll use most often in a real GRBL project, with context:

M3 S1000 This tells the spindle to turn on clockwise at 1000 RPM. On a laser setup, M3 typically enables the laser at a set power level. You'll use this at the start of almost every CNC job.

M5 Spindle off. Every safe program should end the spindle or laser before moving the tool to a safe position. Forgetting M5 is a common beginner mistake that can lead to burns on a laser or unwanted cuts on a router.

M4 S1000 Spindle on, counter-clockwise. In laser mode specifically, M4 is used for "dynamic laser power mode," where the laser adjusts power based on movement speed. This prevents overburning on curves and corners.

M0 Program pause. Useful if you need to clamp a part, flip material, or check alignment mid-job. The machine stops and waits for you to resume.

M8 / M9 Coolant on and off. Many desktop CNC routers use a simple mist coolant setup. M8 turns it on; M9 turns it off. If you haven't wired a coolant relay to the appropriate GRBL pin, these commands will do nothing.

If you're just getting started with the basics, learning the M-codes every beginner CNC machinist should memorize is a practical way to build your foundation before diving into more complex setups.

What Are the Most Common Mistakes People Make With M-Codes on GRBL?

Using M-codes that aren't supported. This is number one for a reason. If you're running stock GRBL on an Arduino Uno and send M7 (mist coolant), the firmware will throw an alarm because the default pin configuration doesn't support it without modification. Always verify against the specific GRBL version you're running.

Forgetting to include M5 before M2 or M30. Ending a program without turning off the spindle or laser is a safety issue. Make it a habit to place M5 before your program end commands.

Confusing M3 and M4 in laser mode. In router mode, M3 and M4 just change spindle direction, which usually doesn't matter. In laser mode, the difference is significant M3 runs the laser at constant power, while M4 adjusts power dynamically. Using M3 on a detailed engraving with lots of direction changes can cause overburning.

Not matching M-codes to the correct wiring. Sending M8 to turn on coolant does nothing if you haven't connected a relay to the coolant pin on your controller board. The firmware processes the command, but no physical action happens which can be confusing if you don't understand the hardware side.

Copying G-code from industrial sources without editing. Downloading a template or example file written for a Haas or Mazak machine and running it on GRBL will almost certainly fail. Strip out unsupported M-codes and simplify the program before sending it.

How Can You Customize M-Code Behavior in GRBL?

GRBL allows some customization through its settings. For example, you can configure which pins correspond to spindle enable, spindle direction, coolant, and flood. This matters because M3, M4, M5, M7, M8, and M9 all map to physical output pins on the Arduino.

Key settings to check:

  • $4 Invert step enable pin (affects how the controller interacts with motor drivers)
  • $9 Spindle enable pin inversion
  • $10 Spindle direction pin inversion (if your spindle runs backward when you send M3, flip this)
  • $11 Coolant enable pin inversion

These settings control signal polarity, not M-code support. If you're using a grblHAL fork or Grbl-Mega, you may have additional settings and extra M-codes available check the documentation for your specific fork before assuming what's supported.

Where Can You Learn More About M-Code Programming?

The GRBL GitHub wiki is the primary source for supported commands and settings. Beyond that, practical experience with real programs teaches more than any chart alone. Start simple run a basic square profile with M3 at the start and M5 at the end and build from there.

When you're ready to go deeper into how M-codes fit into full CNC programming workflows, a guide on reading M-codes in CNC programming can help you understand how these commands interact with G-codes in a complete program structure. And as you continue building your knowledge, having a solid grasp of the essential M-codes for beginners keeps your reference skills sharp.

For those working on projects that need clean documentation or labeling, choosing the right typeface for charts and printouts helps with readability. A monospaced option like Roboto Mono works well for code-heavy reference sheets since each character takes the same width, making alignments consistent.

Quick-Start Checklist: Setting Up M-Codes on Your GRBL Controller

  • Identify your GRBL version. Run $$ in your serial console to confirm firmware version and settings.
  • Print or save the supported M-code list above. Keep it within reach at your workstation.
  • Verify your post-processor output. Open a sample G-code file and search for any M-codes not in the supported list.
  • Check your pin wiring. Make sure spindle and coolant relays are connected to the correct GRBL output pins before testing M3, M5, M7, M8, or M9.
  • Run a dry test first. Send your program with the spindle or laser disconnected to verify the controller processes all M-codes without errors.
  • Adjust $-settings if signals are inverted. If M3 spins your motor the wrong way, toggle $9 or $10.
  • Always include M5 before your program end command. Make it a non-negotiable habit for every program you write.