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]
  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.

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.

2 People Made This Project!


  • Plastics Contest

    Plastics Contest
  • Optics Contest

    Optics Contest
  • Make it Glow Contest 2018

    Make it Glow Contest 2018

29 Discussions


Question 15 days ago

I use SG90 Servo, Grbl 0.9j, Arduino Uno and Universal G-Code Sender

when I tried sending the M03 S90 servo command it moved as instructed
but the servo was hot and when I tried writing the m M05 servo the command remained in state 90
can you help my problem?

2 more answers

Answer 13 days ago

The "spindle_control.c" file in Step 3 expects GRBLversion 1.1f.
You are using an earlier version ...

Some suggestions:
(1) Install GRBL version 1.1f and try again
(2) Check your wiring as it is unusual for a servo to overheat


Reply 7 days ago

Oke thanks sir
I will try
Sorry i bad english speak


14 days ago

Hi! Thanks so much for the tutorial! I'm having trouble with the new spindle_control.c file... I don't see anywhere to "download" it on the buildlog website, so I'm assuming I copy and paste the code? It's giving me trouble, as I think the formatting on the webpage has a few mistakes... Maybe I'm making a simple mistake, but I haven't edited anything yet. Arduino IDE is giving me syntax errors on the code I directly got from buildlog.



C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c: In function 'spindle_set_speed':
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c:223:4: error: #else after #else
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c:173:0: error: the conditional began here
#ifdef PEN_SERVO
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c: In function 'spindle_set_state':
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c:290:51: error: operator '&&' has no right operand
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c: In function 'spindle_set_speed':
C:\Users\hwail\Documents\Arduino\libraries\grbl\spindle_control.c:315:3: error: expected declaration or statement at end of input
exit status 1
Error compiling for board Arduino/Genuino Uno.

5 replies

Reply 13 days ago

See note [1] in "Step 3: Modifying GRBL".
A copy of "spindle_control.c" is included there ...


Reply 13 days ago

Right. On that page, I can't find a download link. I tried copying and pasting the spindle_control.c text from that page, but it runs with syntax errors (shown above) Is there a download link that I'm not seeing?



Reply 13 days ago

For example, line 223 in the link's code sample has an "#else" that seems to not connect to anything. I'm sure that I'm just overlooking something, but I'm lost!


Reply 13 days ago

Hi! I see the link now... I was looking on the buildlog page for the link you were talking about. Apologies for my confusion!



Reply 12 days ago

Not a problem ... happy to help :)


20 days ago

Hello i have already made the machine, but i have a problem with the SERVO, i hope you can help me:
when i move the X axis or the Y axis, the servo moves too! is like the servo is conected too the step motors, i think is a configuration problem but i don´t find the line of that! i¨ll be waiting for your answer. my english is bad excuse me

1 reply

Reply 15 days ago

Assuming that you have constructed my "COREXY CNC PLOTTER" described in
Check that your wiring matches that in the photo "GRBL Servo Wiring" in the Intro section of
Delete your C:\Documents\Arduino\libraries\grbl1.1f_servo library.
Now reinstall your C:\Documents\Arduino\libraries\grbl1.1f_servo library.
It is important that you use a text editor, such as Notepad++, to uncomment line 189 in the file “spindle_control.c” in your C:\Documents\Arduino\libraries\grbl1.1f_servo folder. Do NOT use a word processor.
Providing you follow each step in "Step 3: Modifying GRBL" your plotter should work.


4 weeks ago

I was looking for a solution for this problem. Grbl 0.9i waw supposés To do so but it s not working at home. I m gonna try your procédure tonight. I have no strong skills on c programming. Hope i Will handle it.

Thanks for the detailed procedure.


1 reply

Reply 4 weeks ago

Thank you for your comment :)
FYI a "scaling" issue in some of the earlier versions of Inkscape has been resolved in the latest release.

M. o J.O.

Question 8 weeks ago

/Users/maxomdal/Documents/Arduino/libraries/grbl/spindle_control.c: In function 'spindle_set_speed':

/Users/maxomdal/Documents/Arduino/libraries/grbl/spindle_control.c:315:3: error: expected declaration or statement at end of input



exit status 1

I am receiving this error after modifying the spindle_control.c file. It uploads fine before modifying. Any ideas?

1 more answer
lingibM. o J.O.

Answer 7 weeks ago

The error message indicates that you may have accidentally added/deleted something while in edit mode.

Providing you only uncomment line 189 , as shown in Step 3- slide 3, everything should compile. Be sure to use a text editor such as Notepad++ ... not a word processor.

Try this:

(1) Delete and reinstall a fresh copy of spindle_control.c.

(2) Does it compile ?

(3) If so, edit line 189 as shown in Step 3, slide 3

(4) If not, the problem is elsewhere ... check that you have GRBLversion 1.1f

All going well it should compile....


Question 7 months ago

First of all, thank you so much for your incredible tutorial.

I'm trying to make a drawbot with GRBL library, but I have one problem.
If you have any solution please advise me.

My problem is...
Everything is good to draw a gcode file, but it is little slow.
I've changed every option using $ command, so I could change drawing speed and scale.
However, there was few second of delay between each gcode command.

For example, after moving to a position and dropping a pen on a paper, the machine doesn't works for a second(state changed to idle). And the machine draw only one line and lift the pen and move to another position, AND STOP FOR FEW SECONDS. I don't know why it stops. Don't be idle!
I really want to remove those delay during drawing.
If there is no delay among each command in gcode, my machine will be 3 times faster than now.

Please help me Thank you~!

3 more answers

Answer 7 months ago

In Step 6, "Configure your plotter", I made the comment:

"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."

Instructions for increasing Inkscapes default F100 to F10000 are given in Step 4, photos 6 & 7.

It would appear that your F100 (feed) setting was the cause of your speed problem.

While I think about it, there appears to be a g-code scaling issue with some versions of Inkscape (

Two solutions:


Search this topic for "" by "Shockster" and follow his instructions ...


Downgrade to an earlier version of Inkscape until the problem is fixed.


Answer 7 months ago

Thank you for your answer!

But there are only G4 P1, not P1000

So, I've tried remove 'G4 P1' command in my gcode

and also I deleted 'G01 Z-1.000000 F100.0(Penetrate)' because it is useless I thought. There is no Z function, only pen lift function which are M3 and M5 commands

Finally, my machine speed increased, but is it ok that I've done?


Answer 7 months ago

As far as I am aware GRBL does not support scaling. The following website, however, may be of interest

Your plotter speed is defined by the S110, S111, and S112 parameters ... just check that they are not being overridden by the tool settings in Inkscape.

GPP does not alter your code ... it only inserts pen up/down code sequences each of which inserts a 1 millisecond using the command G4 P1.

Examine your g-code with a text editor, such as Notepad++, and search (CTRL-F) for P1000 which is a 1 second pause ... if that is the problem just replace them with P1 (1 millisecond).


Question 8 months ago on Step 4


I am able to get empty gcode only. why it is so ?




(Generated by gcodetools from Inkscape.)

(Using default header. To add your own header create file "header" in the output dir.)


(Header end.)

G21 (All units in mm)



G00 X0.0000 Y0.0000


(Using default footer. To add your own footer create file "footer" in the output dir.)



can you inform me what is the problem. Only the thing I didnot understand is " PADLOCK"