How to Control a Servo Using GRBL




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


  • Water Contest

    Water Contest
  • Creative Misuse Contest

    Creative Misuse Contest
  • Metalworking Contest

    Metalworking Contest

14 Discussions

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

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.

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?

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


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"

2 more answers

It would appear that you have missed one of the steps in "Step 4" Create Some Gcode".

ALWAYS "select" your drawing before doing anything. (When "selected" your drawing will be surrounded by tiny arrow-heads)

Probable causes are:

(1) Your drawing was not "selected" when you clicked "Path|Object to path"

(2) Your drawing was not "selected" when you clicked "Extensions|Gcodetools|Path to Gcode"

Regarding the "padlock", compare photo 2 with photo 3 in "Step 4" Create Some Gcode".

Photo 3 has a tiny blue square over a "closed padlock" symbol whereas the same symbol in photo2 shows an "open-padlock".

When closed the padlock prevents you accidentally altering your drawing dimensions.

Dear Sir,

Thank you for your polite and genius reply and help.

I have done it now nicely.

Thank you,


Nicely done!

I'm in the middle of trying to port GRBL to ESP32 as I ran out of room on the Arduino, and a Mega is overpriced for what you get. I'm trying to swap out the steppers for DC motors with optocoupler feedback. They work for inkjet printers, so why not? I only need 3 pwm out, 3 digital out for direction, 3 interrupt in, and 3 more inputs for direction. It's a tight squeeze.

Thanks for the great tip about the ability to export a Processing application - works for Linux too.

In Processing3 you can use selectInput() to pop up a file chooser, and save yourself a lot keyboard handling pain. I pasted the example code into a new sketch, and it just worked - brilliant.

For Linux, I may rewrite GPP to work on the command line.

First - off to check out GRBL-Plotter...

1 reply

Thank you for your comment and reference :)

I have added a further step (Step 8) to this instructable plus an alternate version of GPP which may help with your project.

This instructable was so timely when I just completed build of my plotter ans was looking for servo activation for pen lifter.

Few differences in my project are

1. I am not using corexy contruct but plain X Y plotter

2. I am using CNC shield with DRV8825 as stepper drivers (for MEMA 17 motors)

Other similarities

1. I am also using 1.1f GRBL and was looking for a good and working change for spindle_control.c which I got from this instructable and the good explanation at the link.

I was a bit confused on how to wire-up servo (SG90) to CNC shield. After reading this instructable, I wired signal wire of SG90 to Z+ pin of CNC shield and 5v and GND pins to corresponding pins of CNC shield (which in turn is powered by 12v 5amp power adapter in my project)

Following this instructable, I was able to successfully test the pen-up and pen-down. I used following GCodes after a bit of trial and error.

M3 S80 --> for pen-down

M5 --> for pen up

Once I complete full testing, will post my results. But, servi problem is very well solved now.

Thanks again !!!

1 reply

Well done ... thank you for your comment:)

When testing I found that my servo wouldn't operate until it received an "M3 S90" command (which includes the spindle speed) after which you can just use "M3" and "M5" without the S90 for raising/lowering the pen.

For this reason I chose to raise the pen at the program start using "M3 S90" and to use "M5" for pen down to avoid having to manually type "M3 S90" prior to sending my gcode. It also prevents the pen marking the paper.

I never saw this as a problem as there are two ways to correct your servo position"

- reposition the servo arm by 90 degrees

- reverse the numbers in lines 48,49 in spindle_control.c (see attached photo)

If, however, you intend generating g-code by dropping an SVG file into a program such as GRBL_Plotter then for compatibility you should use M3 S90 (the 'S' number doesn't appear to matter) for pen-down and M5 for pen-up.


Nice project, but your “GcodePostProcessor” algorithm sound too complicated.

Why not using a tool which can export the GCode you need, give GRBL-Plotter a try:

Just drag an drop you SVG drawing and get the GCode you need (with the needed M2, M3 commands) - just setup the import options...

2 replies

The GRBL-Plotter setup page:


Thank you for your interest in my project, and for your helpful suggestion :)

I will try but please try my method before writing it off as being too complicated ... the workflow is extremely simple:

(1) point the output of Inkscape towards your PostProcessor folder

(2) set your feed rates in Inkscape before generating your file

(3) run GcodePostProcessor

(4) send the post-processed file to GRBL using UGS

As mentioned in my article, "I'm not an expert". Until now I have written custom interpreters for my projects ... this is my very first dabble into CNC using GRBL.

All suggestions welcome ... the major problem I have is that you have to know what to look for when scouring the net.

Thanks again.