Introduction: How to Control a Servo Using GRBL

About: 55+ years in electronics, computers, and teaching ... now retired.

GRBL is an arduino program for controlling each of the XYZ stepping motors on 3-axis machines such as 3D-printers and milling machines. [1]

If you study the predefined GRBL pin-outs in photo 2 you will see that none of the PWM (pulse width modulation) pins are available for controlling a servo.

This instructable explains how to:

  • free up a PWM servo pin by modifying GRBLversion 1.1f,
  • configure GRBL for coreXY plotters,
  • create a g-code calibration file using Inkscape 0.92,
  • insert the necessary pen-lift control codes using “GcodePostProcessor” [2],
  • configure your plotter settings and
  • send the modified g-code to your plotter.

The opening photo shows the results obtained when I ported GRBL to the CoreXY plotter described in

The video shows GRBL controlling a servo motor using the pen-lift code sequences generated by “GcodePostProcessor”. The solid blue line indicates when the servo arm should be up as the virtual pen traverses the letters ABC.


More information may be found at


“GcodePostProcessor (GPP)” inserts GRBL servo pen-lift commands into existing g-code. This original program, and the source code, are attached to this instructable.

Step 1: Theory

Servo motors require pulse width modulation (PWM) signal to operate. Unfortunately GRBL has allocated another task to each of the PWM pins ... we need to borrow one of these pins to control our servo.

Pin 11 is an ideal candidate as the “Limit Z-Axis” function is not required when plotting ... but to access this pin we must replace the “spindle_control.c” code module within GRBL with code of our own.

This solves one problem but creates another ... any G-code that we send to the plotter now requires “special” code sequences for raising and lowering the pen.

Generating the Code Sequences

There are two distinctly different ways of doing this:

  1. add an “extension” to Inkscape. [1]
  2. insert the required M3,M5 code sequences into existing G-code using a post-processor.

The end result from both approaches is the same.

An example of post-processing using my “GcodePostProcessor” is shown in photo 1. The left-hand file contains the original Inkscape g-code. The right-hand file contains the additional GRBL command sequences. Lines that have been deleted are shown with a red “minus” sign and red highlight. Lines that have been added are shown with a green “plus” sign and green highlight.

Let’s get started ...


A video demonstrating this process may be found at and is fully documented in the comment section below the video.

A downside to this approach is that the extension may become obsolete. For example the “MI Inkscape Extension” used in the above video only works with Inkscape 0.47.


A post-processor offers the following advantages:

  • existing G-code files don’t have to be recreated.
  • it works with any G-code software generator.
  • it is compatible with the latest versions of Inkscape.

Step 2: Hardware and Software Requirements

Before starting we need to organize our hardware and software.


Your plotter wiring should match that shown in the photo “GRBL Servo Wiring” .

All components in the attached parts list were obtained from

Instructions for adjusting the motor currents are contained in the parts list.


The following software should be be installed on your computer:


Java 8 is required by “Processing 3” and “Universal Gcode Sender”


“Processing 3” is a graphics processor with an interface similar to the Arduino IDE (integrated development environment). Apart from a few extra drawing commands the two programs are similar except that Processing 3 calls its main loop draw(){}.

Step 3: Modifying GRBL

The following steps are required:

  1. Download and unzip “” (photo 1) from
  2. Download “spindle_control.c” (photo 2) from . [1] [2]
  3. Navigate to the “grbl” folder within the zip file we have downloaded and replace the “spindle._control.c” file with the “spindle_control.c” file from “”.
  4. If you have a COREXY plotter you must edit line 189 in the file “config.h” to read “#define COREXY;” as shown in photo3. Use a text editor such as Notepad++ to do this. Do NOT use a word processor.
  5. Copy the “grbl folder” to the arduino “libraries” folder and rename to say “grbl1.1f_servo” ... the name doesn’t matter so long as you can find the folder. The path to this folder is normally C:\Documents\Arduino\libraries\.
  6. Open your arduino IDE and navigate to the folder C:\Documents\Arduino\libraries\grbl1.1f_servo\examples\grblUpload.
  7. Select the sketch “grblUpload.ino” then upload it to your arduino.

That’s it ... GRBL is installed.


This blog fully explains the process. For convenience, a copy of this “spindle_control.c” file is attached to this instructable in case, as happened to me, some of the comments and source code get merged during download and need to be unscrambled.


19 January 2019

The file "spindle_control.c" has been removed from

For convenience a version of GRBL that contains an updated version of "spindle_control.c" may be obtained by downloading "" from and following the authors installation instructions.

If you compare the the header in the original "spindle_control.c" (attached to this instructable) with that in this latest version you will note a major change.

The original version of "spindle_control.c" reads: "When the spindle is on, the servo moves the pen down. When it is off the pen moves up".

The latest version of "spindle_control.c" reads: "In stepper.c it will will look at the Z position. Any Z>0 is pen up." which means that post-processing is no longer required.

In this new release, "Grbl is still running a full range virtual Z axis with accelerations and speeds. Be aware how this will affect your pen. For example: If the Z is at 5 and you tell it to go to -5, the pen will stay up as the virtual z moves from 5 to 0. The pen will then go down. The virtual Z will continue to go down to -5 before it executes the next move. You can control these "delays" by adjusting the speed and acceleration of the Z axis and what your CAM uses a Z locations for up and down.

If you want to have the pen go to the up position at turn on, define a negative Z work offset. Send the command "G10 L2 P0 Z-2". This will trick Grbl into thinking the pen needs to be up."

Step 4: Create Some G-code

It is helpful to have a calibration file for checking the accuracy of your plotter.

Let’s generate the g-code for a 100mm square using the latest version of Inkscape [1], then insert the required GBRL servo commands using “GcodePostProcessor”.

Create a “square” using Inkscape

The following steps are required:

  1. Launch Inkscape
  2. Click "File|Document properties" (Shift+Ctrl+D)and set your paper size.
  3. Click "Create Rectangles & Squares" (F4) from the sidebar.
  4. Click and drag a rough square shape. (photo 1)
  5. Click "Select and transform objects" (F1) from the sidebar. Our square will become surrounded by tiny arrows. (photo 2). At this point we could simply drag this shape onto our work area, but let's add some accurate dimensions so that we can check our plotter calibration.
  6. Change the (W)idth and (H)eight measurements to 100mm then click the padlock. (photo 3)
  7. Now drag the square onto the work area. Set the X & Y positional values to whole numbers. (photo 4)

We are now ready to create our G-code.

Generate the G-code

The following steps are required:

  1. Click "Path|Object to path" ... nothing appears to happen but it does.
  2. Click "Extensions|Gcodetools|Orientation points|Apply ... then Close" ... orientation points will appear. (photo 5)
  3. Click the square to bring back the arrows.
  4. Click "Extensions|Gcodetools|Tools library|Default ... then Close" ... a green screen will appear. (photo 6)
  5. Click the "Create and edit text objects" (F8) from the sidebar.
  6. Carefully edit the speeds in the green box. I've set my plotter speeds to 10000mm per minute in this example. (photo 7)
  7. Click and drag the green box to one side of our work space.
  8. Click our square to select it.
  9. Click "Extensions|Gcodetools|Path to Gcode|Preferences" and complete the form. (photo 8)
  10. Click "Options" and make any changes. For test purposes I have increased the arc radius to 1mm ... the default value is 0.02mm (photo 9)
  11. Click "Path to Gcode". (photo 10)
  12. Click "Apply" and a toolpath with tiny direction arrows will eventually appear. (photo 11)
  13. You may now close Inkscape ... a file "square.gcode" should appear on your desktop. The contents of this file are shown in photo 12.

If you examine the code in photo 12 you will see that Inkscape has inserted some M2,M3,M5 codes.

These codes are for a milling machine, not a plotter, and need to be stripped out and replaced with custom codes of our own.

Let's do this ...

Step 5: Insert the Pen-Lift Commands

This step explains how to:

  1. install, and run, “GcodePostProcessor” [1].
  2. create a standalone executable version of “GcodePostProcessor.exe”.

Install the Post Processor

The next three steps only have to be done once:

  1. launch Processing 3
  2. copy the contents of “GcodePostProcessor.pde” (attached) into the Processing 3 sketch.
  3. save the sketch as “GcodePostProcessor” without the quotes. This will create a folder C:\Documents\Processing\GcodePostProcessor.

Run the Post Processor

The following steps are required for every plotter file:

  1. open the “GcodePostProcessor” sketch (photo 1)
  2. copy “square.gcode” from your desktop to folder C:\Documents\Processing\ GcodePostProcessor
  3. click the Processing “Run” button (top-left arrow-head) ... a series of popup boxes will appear (photos 2..5)
  4. click the the first pop-up box and type the filename (in this case “square.gcode”).
  5. A file, “square.gcode.gcode”, will appear in your C:\Documents\Processing\GcodePostProcessor folder. [2]

We will send this file to our plotter shortly.

Create an Executable Version of the Post Processor

This (optional) once-only step creates an executable version of “GcodePostProcessor.exe”

The following steps are required:

  1. open the “GcodePostProcessor” sketch.
  2. click File|Export Application ... |
  3. complete the pop-up box (photo 6)
  4. click Export ... an application.windows64 folder will appear in C:\Documents\Processing\insertGcode (photo 7)
  5. copy/move this application.windows64 folder to your desktop and rename it “Post Processor”. (photo 8)
  6. copy “square.gcode” file to this folder
  7. double-click “GcodePostProcessor.exe” and follow the prompts ... the program works as before.


My “GcodePostProcessor” algorithm:

  • strips out the M2 code at the end of the program. This prevents the pen marking the paper when the plot is complete.
  • strips out all M3, M5 codes to avoid unwanted pen-lift conflicts
  • inserts an M3, or M5 code, sequence whenever the g-code changes from G0 to any of the G1,G2,G3 commands, and vice versa. When plotting, the pen is always down unless a G0 command is received.


“GcodePostProcessor” adds a “.gcode” extension to your original filename which:

  • groups the source and plotter files together
  • clearly identifies which of the two files is the plotter file (the filename is longer)
  • makes your plotter file easier to find when using the UGS file browser (otherwise you have to select “all files”).

Step 6: Configure Your Plotter

GRBL comes with a number of default plotter settings. In most cases these setting are not what we want and need to be edited prior to plotting. This is a once-only process.

There are two ways we can do this:

  1. edit the GRBL settings using the arduino “Serial Monitor”.
  2. use the command line in “Universal code Sender”.

Both methods are similar ... let’s use the command line in “Universal Gcode Sender” as that requires less cable swapping:

Connect your plotter

To do this:

  1. Plug the arduino USB cable into your computer
  2. launch “Universal Gcode Sender”
  3. select your COM port
  4. set the communications speed to 115200 bauds
  5. click “Open” ... a list of plotter settings will appear [1]

Change your plotter settings

The settings for your plotter are stored in non-volatile memory which means they only need to be configured once. [1]

The default settings in GRBL are shown below:

  • $0=10 Step pulse, microseconds
  • $1=25 Step idle delay, milliseconds
  • $2=0 Step port invert, mask
  • $3=0 Direction port invert, mask
  • $4=0 Step enable invert, boolean
  • $5=0 Limit pins invert, boolean
  • $6=0 Probe pin invert, boolean
  • $10=1 Status report, mask
  • $11=0.010 Junction deviation, mm
  • $12=0.002 Arc tolerance, mm
  • $13=0 Report inches, boolean
  • $20=0 Soft limits, boolean
  • $21=0 Hard limits, boolean
  • $22=1 Homing cycle, boolean
  • $23=0 Homing dir invert, mask
  • $24=25.000 Homing feed, mm/min
  • $25=500.000 Homing seek, mm/min
  • $26=250 Homing debounce, milliseconds
  • $27=1.000 Homing pull-off, mm
  • $30=1000. Max spindle speed, RPM
  • $31=0. Min spindle speed, RPM
  • $32=0 Laser mode, boolean
  • $100=250.000 X steps/mm
  • $101=250.000 Y steps/mm
  • $102=250.000 Z steps/mm
  • $110=500.000 X Max rate, mm/min
  • $111=500.000 Y Max rate, mm/min
  • $112=500.000 Z Max rate, mm/min
  • $120=10.000 X Acceleration, mm/sec^2
  • $121=10.000 Y Acceleration, mm/sec^2
  • $122=10.000 Z Acceleration, mm/sec^2
  • $130=200.000 X Max travel, mm
  • $131=200.000 Y Max travel, mm
  • $132=200.000 Z Max travel, mm

To change any setting simply type the setting number followed by “=” then the “value” into the command line. Once you have finished type $$ to confirm the settings. For example $100=80 tells GRBL that your plotter requires 80 steps to travel 1 mm.

The $100..$132 settings shown in photo 1 are for the CoreXY plotter described in described in [2]


The setting descriptions have been dropped from the latest version of GRBL as the program requires as much memory as possible. Each setting, however, is fully documented in

Thoughtfully, UGS (Universal Gcode Sender) displays this information alongside each setting.


Caveat Emptor ... I’m not an expert.

All of my settings were found by trial and error apart from the 80 steps/mm for $100, $101, and $102, which were calculated.

To ensure that GRBL has full control of the XYZ speed settings I set the F(feed value) in the Inkscape’s “Default Tool” menu to a value higher than the $110, $111, and $112 values in GRBL on the basis that the lowest speed wins ... this approach appears to work.

Must experiment further ...

Step 7: Plotting

Positioning your pen

Without limit switches, your arduino thinks that the pen is resting at Inkscap coordinate (0,0) when power is applied. I must be doing something wrong because this rarely happens.

The following neat trick solves two startup problems in a single operation:

  1. remove the pen.
  2. plot something small, such as our square.
  3. the GRBL (0,0) coordinate is wherever the pen stops
  4. GodePostProcessor leaves your pen pointing upwards ............................ (problem 1 solved)
  5. switch off the power to the motors.
  6. reattach the pen and move it to your Inkscape (0,0) coordinate .............. ..(problem 2 solved)
  7. switch the power back on to the motors.

You can plot all day now ... the plotter will always return to this coordinate :)

6 March 2018

Finally, with a little help, I have solved the pen positioning problem:

  1. run UGS and "open" a connection to your arduino.
  2. from the command line type "M3 S90" to raise the pen
  3. (comment: the command "M5" lowers the pen)
  4. "check" the box labelled "Enable Keyboard Movement" (photo 1)
  5. set the "XY step size" to 10 mm
  6. set the "Feed rate" to 1000 mm/minute
  7. click the +X, -X, +Y, -Y buttons to move the pen.
  8. when the pen is in the correct position click the "Reset Zero" button
  9. uncheck the "Enable Keyboard Movement" box

The plotter will now return to this position.

Plotting an image

Using photo 2 as a reference:

  1. launch “Universal Gcode Sender”
  2. enter the COM port attached to your plotter
  3. set the communication speed to 115200 bauds
  4. browse for a modified g-code file.
  5. click “Visualize” and a screen will (eventually) appear. The solid blue path indicates when your pen will be up.
  6. click “Open” ... your arduino settings will roll down the screen [1]
  7. click send ... the yellow virtual pen, and your plotter, should both start moving


Check your paper dimensions, and other settings, before you press “send”. If necessary correct them using the command line.

Step 8: Raising and Lowering Your Pen

There are several ways to control your vertical pen-movement should it raise when you want it lowered:


The simplest solution is to unscrew the servo arm and rotate the arm through 90 degrees as you are only using 90 degrees of the possible 180 degrees offered by servos.


Photo 1 shows a software method for reversing the your pen direction. Change the value of line 48 in “spindle_control.c” from 16 to 31, and the value of line 49 from 31 to 16, then recompile and upload GRBL to your arduino.

Changing these numbers slightly enables you to obtain 90 degrees exactly. In practice these values are close enough.


I discovered this method quite by accident ... but first we need some background.

In order to free-up the arduino PWM pin (pin 11) we swapped “spindle_control.c” with code of our own which tricks GRBL into accepting a command such as “M3 S1000” to move the servo-arm on our plotter. Similarly we use the command “M5” to restore the servo-arm to it’s original position.

While on the subject of M3 and M5, GRBL requires a NON-ZERO spindle-speed value before these commands will work. For this reason most programs send an intial “M3 S1000” to the plotter after which you can use M3 without the “S” (spindle speed) value.

Here is where you have to “think outside of the square”. “S1000” is not a command ... it is a value parameter that can be attached to either the “M3” or the “M5” command. Why then do most programs send an initial “M3 S1000” to the plotter, then use M3 for pen-down which leaves an unwanted ink-mark on your paper?

I get the impression that since you would only lower the spindle on a milling-machine while it is spinning, everyone uses “M3 S1000” for pen-down.

When writing GcodePostProcessor I decided to use M3 for pen-up and M5 for pen-down which works beautifully. The only problem that I have encountered is that your pen is is up when it should be down when sending G-code directly to your plotter from third-party programs. Okay ... just unscrew the servo-arm.

But there is a simpler solution ... instead of tricking GRBL with a little white lie (“M3 S1000”) why not tell it a great big whopper in the form of “M5 S1000” which, when interpreted, means “spindle off, but rotate at 1000rpm”... much to my amazement, this actually works!!!!

The beauty of “M5 S1000” is that our M3 and M5 commands are now in sync with the rest of the world. For this reason I have rewritten “GcodePostProcessor” using “M5 S100” to initialise the servo.

I have called this new version “GPP.pde” to avoid confusing the two programs. Download and “unzip” the attached “ “file to your desktop (or other convenient location) and double-click the file “GPP.pde” to run.

The two extra “header” and “footer” files suppress Inkscape “headers “ and “footers” if you direct the g-code output from Inkscape into this folder. These two files are blank text files that have been renamed.

The file “target.gcode” is a small GPP test file should you wish to confirm that the program works as described ... just compare the contents of “target.gcode” with the contents of “target.gcode.gcode” once you have run GPP.

  Click here   to view my other instructables.