CNC - G-Code

Cutter Radius Offsets

Up to this point we have covered rapid feeds, linear feeds and arc feeds.  Knowing how to do these will get us a long way toward writing a program to cut something we need on the CNC machine.  However, if you have run the G-Code we have developed so far on a simulator or perhaps your own CNC machine, you will have noticed something.  The center of the cutter is moving on the vectors leaving us a finished part that is smaller than what we wanted.  How much smaller?  I am glad you asked.  It depends on the diameter of the cutter you are using.  For example, if I were to use a .250 inch flat end mill to cut a 1 inch square from some material, I would end up with a .750 inch square.  Why, because half of the cutter, .125 inch is cutting across the vector into my material.  By the time I finish the job, I have lost .125 on all four side or .250 off the length and width of the finished piece.  So the question is how to fix it.  Well, there are two ways you can do it.

1) Recalculate the Tool paths

Cutter Radius 01 thumbStart by taking a good look at the vector and control point image to the left.  Click the image to see a larger version of the vector and control point offset image.  In this example we want to profile this 1 inch square.  This square is depicted in the drawing by a gray vectors.  Additionally the control points, the points that we would use to calculate our G1 feeds from are shown in red with their coordinates.  As stated above if we were to use these control points to cut this profile the square would end up smaller than we intended.  To solve this problem we have to move the control points in such a way they the edge of the tool will be on the vectors we wish to cut.  In this example we are cutting on the X an Y plane using a .250 inch flat end mill.  Since we know the cutter diameter is .250 inch we know the radius is half that, or .125 inch. Let's examine the bottom left corner of the square.  It is located at (1, 1).  To determine our new control point we have to move it the radius of the tool below the original point to cut on the bottom line of the vector.  This takes care of half of it but we need to move the point left so that on the last pass of the profile we do not clip the edge of the square off.  We also need to move the point to the left by the radius of the tool.  So subtracting .125 inch from 1 inch gives is .875 inch for both X and Y.  This becomes our new control point marked in green.  This has to be done for every control point of the drawing.  Moving it either left or right on the X-Axis and up or down on the Y-Axis to compensate for the radius of the tool we are using.  Once you have all the control points for the drawing translated, you can then write the code to do the profile.  The Yellow dashed vectors indicate the center of the tool at it is cutting, leaving the edge of the tool on the gray vectors.  The end result is the 1 inch square profile we were looking for.

I realize that was a very simple example, but the same is true whether you have a complex shape you are cutting or a simple one.  The only challenge is one you start cutting angular profiles where the distance you move on the X or Y axis may be more.  To figure these out use some simple trigonometric functions with the angle to determine the new point.  If you want an example of this let me know through the CONTACT US link at the top of the page and I will do one for you.

So all is well, we have a set of points and a G-Code program written to use the .250 inch end mill, but what happens when we discover that our end mill is broken and the closest I have is a .375 inch end mill?  Well, recalculate the new control points and write a new program.  Simple huh???  Yeah right!!!  Who wants to do that, there has to be a better way.  There is and it is called cutter radius offsets.  Let's take a look at that next.

2) Use Cutter Radius Offsets

Cutter Radius 02 thumbRemember our discussion on arc feeds using the G2 and G3 commands.  There was one for clockwise (CW) movement and one for counter clockwise movement (CCW).  Well cutter radius compensation has two commands as well, but they are referred to left and right rather than CW or CCW.  Only because the idea of CW and CCW doesn't really fit in this category.  A cutter could be going CW around a profile, but be either on the left side of the vector or the right side of the vector.  The inverse is also true, the cutter could be moving CCW and be on either the left or right side of the vector.  The way to visualize it is this.  Always thing of the cutter moving around the vector.  Even if your machine's table moves always think of the cutter doing the moving.  With this in mind, regardless if the cutter is traveling CW or CCW we want to be on one side of the vector or another.  Either the left or the right.  If we were cutting the profile of the square above and traveling in a CW direction around the perimeter, we would want the cutter to the LEFT of the vector, if we were instead cutting a pocket on the inside of the square going in a CW direction we would want the cutter to be on the right side of the vector.  Now, let's change that up and say we are traveling CCW around the vector cutting a profile, we would want the cutter on the right side of the vector.  If we were cutting a pocket going CCW we would be on the left side of the vector.  I think the easiest way to visualize the left or right is to imagine you are the cutter.  Which direction are you going?  As you travel along the vector, are you on the Left or the Right side?  Look at the image to the left to see this in pictorial form.

The command for selecting cutter compensation are G41 and G42G41 selects cutter compensation of the cutter radius to the LEFT of the direction of travel.  G42 selects cutter compensation of the cutter radius to the RIGHT of the direction of travel.  Now that we know how to select which offset we would like to use, how do we apply the actual value of the offset.

Getting the Offset


Arc Feeds

Just like the linear feeds discussion we had, we will need to cover some information before we jump in to write code to cut circles or arcs.  The first thing to discuss is the circle itself.

Arcs and Circles

circle info thumbThe first thing is to describe a circle.  According to a circle is a closed plane curve every point of which is equidistant from a fixed point within the curve.  From this we can deduce that an arc is a partial curve on a plane.  That is all well and good, but what about circles and arcs in terms of CNC and G-Code?  Take a study of the image to the left.  We start with a circle drawn in blue.  The circle can be described as being a point on a plane and a radius and diameter. This is how most circles are described when we encounter them on a drawing or when we draw something up in a CAD package.  There are a few more things to know about a circle in order to know enough to write G-Code to cut one.  Looking back at our image to the left, if a horizontal line is drawn through the circle passing through the center point and a vertical line drawn through the circle through the center point we have divided it into four sections or quadrants.  These quadrants are essentially the same as the quadrants you labeled in high school algebra when you were mapping equations on a Cartesian plane.  Here, simply call the center point of the circle the origin of the Cartesian plane.  The quadrants are numbered exactly the same.  The upper right is quadrant I, then working counter clockwise, Quadrant II, III and IV.  This concept is important because later we will have to calculate indexes based on the quadrant we are cutting in.

The next thing to observe is that the point at which the circle crosses quadrants is called the quadrant point.  These are kind of special as most simple cuts either start and/or end on one of these points.  Additionally the indexes are easily calculated for these points.  There are lots of other things to know about circles, but this is enough for what we are trying to do.

Arc Direction - Clockwise or Counter Clockwise

We have two choices when cutting arcs.  They can be cut in either a clockwise direction or counter clockwise direction.  Mathematically speaking, an arc going in the counter clockwise direction is moving in a positive direction and is a positive angle.  The reverse applies to an arc going in the clockwise direction.  It moves in a negative direction and is a negative angle.  Arc direction is controlled by G2 and G3.  A G2 command specifies an arc in the clockwise direction (CW) and the G3 command specifies that the arc will be in the counter clockwise direction (CCW).

What plane are we in?

When cutting arcs, the controller needs to know what plane are the arcs being cut in.  There are three possibilities for this, most often we will be cutting in the XY plane.  But you can also cut in the XZ plane and the YZ plane.  There are specific preparatory command that let the controller know which plane we are working in.  The command G17 selects the XY plane.  The G18 command selects the XZ plane and the G19 command selects the YZ plane.  So, if I am cutting a profile on my JGRO CNC Router that has rounded corners, I would select the G17 command to let the controller know that my arcs are being cut on the XY plane.

Describing the arc or circle

Now that we know what the commands are for selecting the plane and arc direction we need to describe from which point the arc begins and ends and the radius of the arc we are cutting.  This information allows the controller to calculate the path that it needs to run on to make the cut.  Selecting the starting point of the arc is easy.  It is the current location of the tool.  Let me clarify that a little.  If we are cutting a piece of material and we want rounded corners, we would start by making a linear cut using something like G1 X2 Y2 and then start our rounded corner.  Well the starting point of our arc will be the last position the cutter was in, in this case X2 Y2.  To find the end point we look at our drawing and determine what that will be.  Lets pretend we are cutting a round corner.  Our corner is a quarter circle of a 1 inch radius and will start at X2 Y2 and end at point X1 Y3.  The center point of our circle will be at X1 Y2.  It may be helpful to sketch that out.  Go ahead and do that, I will wait for you here.

Now that we know our data, the start point, the end point and the radius we have enough information to write the code to cut this arc.  It is as follows:

G3 X1 Y3 R1 ;CCW arc starting at X2 Y2 and will go to X1 Y3 with a radius of 1 inch.

That seems simple enough, but there is a problem.  When arcs of this nature are described with a Radius it is possible that the controller can select a center point of someplace other than what we intended.  For example, we intended that the center of the circle was at location X1 Y2, but a point at X2 Y3 would have worked too.  Additionally, some controllers will not accept the Radius command.  But don't despair, there is a better way and once you learn it, there is no chance for ambiguity.

Setting the center point using offsets

Another way of describing the center point of the arc or circle is to give the controller a relative offset from the starting position to tell it exactly where the center point is located.  Now this sound a lot more complicated than it really is.  First there are three offsets we can work with.  These are I, J and K and each one of these is used with a certain axis.  I is used for the X-Axis, J is used for the Y-Axis and K is used for the Z-Axis.  To calculate the offset, lets go back to the Cartesian plane and the quadrant stuff from above.  Remember, our center point represents the origin or (0,0) of the Cartesian plane.  To determine the offset we need to calculate what we would need to add or subtract from the X, Y or Z axis to get us from the starting point of the arc to the origin (or center point) of our arc.  In our example above, our arc stared at X2 Y2 and the origin was at X1 Y2.  Since we are working in the XY plane we will use the I and J offsets.  Remember, I is used for the X-Axis and J for the Y-Axis.  Now lets calculate what our offsets would need to be.  Looking at the X location of the starting point we know it is at 2 and the X location of the origin is at 1, so to get from 2 to 1 we have to subtract 1 from the starting point.  We are working in the X-Axis so that means the I offset equals -1. (I-1).  We do the same process for the Y-Axis.  The starting Y position of the arc is 2 and the center point of our arc is 2 so to get from 2 to 2 we add/subtract 0.  The J offset is used for the Y-Axis so it comes out as (J0).  Also note that we are starting on a quadrant point making our calculations pretty simple.  If this confuses you, read the above a couple more times.  If you need more examples use the CONTACT US link at the top of the page, and I will add more examples of doing this.

Now that we have calculated the offsets let's rewrite the code above to use them.

G3 X1 Y3 I-1 J0 ;Using the starting point of X2 Y2, CCW arc ending on X1 Y3 with center point being X1 Y2

That wasn't so bad, but there is another caveat.  How do we cut a full circle.  Well we know that the start point and end point are the same.  Let's say we want to cut a 1 inch diameter circle with the center point being at X4 Y5.  Let's cut the circle using a clockwise cut and start it in the left center of the circle on the quadrant point.  The start position would be the center point minus the radius of the circle for the X coordinate and Y is the same as the center point.  So the start point is X3.5 Y5.  Since we are cutting a full circle, the end point will be the same as the starting point.  Now we need to calculate the I and J offsets.  Remember, we are going from the start point to the origin or center point of the circle.  The I offset equals .5 because we need to add .5 inches to the X coordinate to get to the center.  The Y starting point is the same as the origin or center point of the circle so the J offset is 0. The code to cut this circle is as follows.

G2 X3.5 Y5 I.5 J0 ;Starting point X3.5 Y5, cutting clockwise with center at X4 Y5 ending on X3.5 Y5

So where is the caveat?  Well, some controllers will not let you cut across a quadrant boundary.  So how do you cut a circle then?  If the controller does not let you cut across a quadrant then you will have to cut the circle in four segments.  One for each quadrant.  The code to do that is as follows:

G2 X4 Y5.5 I.5 J0 ;Starting point X3.5 Y5, cutting clockwise with center at X4 Y5 ending on X4 Y5.5 Quadrant II
G2 X4.5 Y5 I0 J-.5 ;Starting point X4 Y5.5, cutting clockwise with center at X4 Y5 ending on X4.5 Y5 Quadrant I
G2 X4 Y4.5 I-.5 J0 ;Starting point X4.5 Y5, cutting clockwise with center at X4 Y5 ending on X4 Y4.5 Quadrant IV
G2 X3.5 Y5 I0 J.5 ;Starting point X4 Y4.5, cutting clockwise with center at X4 Y5 ending on X3.5 Y5 Quadrant III

It is more work to cut this way but you are assured it will run on many more controllers.  This only matters if you are worried about portability.  Learn what your controller will do and do it the way you find easiest, whether you cut in one line, cut be quadrant or use the radius method.

Other things to consider

Finally, when cutting arcs or circles there are other things to consider.  Although I didn't mention it, the G2 and G3 command require a feed rate just like the G1 command.  If you don't supply a feed rate (F command) for the arc feed command the controller will use the last feed rate used.  If one does not exist, then it will throw and error.  Finally, if your start point begins on a point that does not reside on one of the quadrant points, you may have to use a little trigonometry to determine the point to calculate your I, J or K offset.

Putting it all together

Cutting arcs thumbTake a look at the drawing to the left.  Let is assume this is what we want to cut the profile of.  Further let's make the following assumptions.  The machine origin is located at the red cross hairs and is X0, Y0.  The material is wood and is .500 inches thick.  The Z-Axis home position has been set to the top surface of the work piece, .500 inches.  The starting position of the Z-Axis is at 1 inch.  Each grid square is equal to 1 inch.  With that out of the way, the drawing is a three inch square block with the corners having a radius of 1 inch.  All we need to do is determine what the starting point of the cut will be.  I have elected to (arbitrarily) start the cutting point at X1, Y2.  To make this part, we will use a .250 inch flat end mill.  We will take two passes at .250 inch each to cut the complete profile.  Below is the program to cut the profile.

(Set the units to inches)
(set the plane to XY)
(Select Tool 1 - .250 End mill, Change Tool)
T1 M6
(Set the feed rate to 50 inches per minute)
(Turn the spindle on clockwise at 15,000 RPM)
M3 S15000
(Move to the start position)
G0 X1 Y2
G1 Z-.250 ;plunge to first cut depth
G3 X2 Y1 I1 J0 ;cut bottom left radius
G1 X3 Y1 ;cut the bottom of the square
G3 X4 Y2 I0 J1 ;cut bottom right radius
G1 X4 Y3 ;cut right side of square
G3 X3 Y4 I-1 J0 ;cut top right radius
G1 X2 Y4 ;cut top of square
G3 X1 Y3 I0 J-1 ;cut top left radius
G1 X1 Y2 ;cut left side and finish first pass
G1 Z-.500 ;plunge to final cut depth
G3 X2 Y1 I1 J0 ;cut bottom left radius
G1 X3 Y1 ;cut the bottom of the square
G3 X4 Y2 I0 J1 ;cut bottom right radius
G1 X4 Y3 ;cut right side of square
G3 X3 Y4 I-1 J0 ;cut top right radius
G1 X2 Y4 ;cut top of square
G3 X1 Y3 I0 J-1 ;cut top left radius
G1 X1 Y2 ;cut left side and finish second pass
G0 Z2 ;retract end mill
G0 X0 Y0 ;return home
M5 ;turn off spindle
M30 ;end of program
Clowns to the left of me, Jokers to the right, here I am, Stuck in the middle with you.

So far we have covered rapids, linear feeds and arc feeds.  If you have ran this code in an emulator you will have noticed that the cutter is cutting on the actual line.  As a result, the part is not the correct size as it ends up smaller than it is supposed to.  Cutter radius compensation is the answer and we will touch on that next.

Getting started with G-Code

Before starting with any actual codes that do something, we need to let the controller know a couple of things about our set up.  We should get in the habit of doing this even if we are only writing code to run on an emulator.  Eventually, we will want code to run on a real machine so let's start getting in the habit of it.

I like to call these code that make settings to the controller preparatory codes.  These codes prepare the controller for what is to follow.

Finally, I want to mention N codes.  These are program line numbers.  Line numbers have their place.  You will need them for sub-routines or some other identifier.  LinuxCNC does not require the use of line numbers in your program, other controllers out there may.  If you are using something other than LinuxCNC, like Mach3 check to see if your controller requires the use of line numbers.  I will cover them next.

Line Numbers

Line numbers begin with the letter N followed by up to five numbers in length and must be positive and no decimals.  As i stated earlier, N codes are usually optional and are ommitied.  But check your controller to be sure. Examples of line numbers or blocks are as follows:

N3 ...


Comments are bits of text that you can put in your program to make notes to yourself on what you were doing.  Programs should have lots of comments.  It is frustrating to go back to a program to make a tweak a month later only to have no idea what you were trying to do.  I advise you to comment your code.  Comments are ignored by the controller and have no impact on the machining job at hand.  Comments in a G-Code program are made in two possible ways.  Comments are embedded within a line of code using the parenthesis characters, ( and ).  Comments can also be started with the semicolon character, ; and are read to the end of the line.  Some examples of comments follow:

(This is a comment on a single line)
;This is a comment on a single line too.
N10 G0 (rapid movement comment) X0 Y3
N11 G0 X2 Y5 ;This comment is read to the end of this line


CNC machines can operate in either millimetres or inches.  The controller needs to know what dimensions you are operating in.  The difference between 5mm and 5in is rather large and can mean the difference of doing it right and making a horrible mistake.  There are 2 G codes that are used to set the units of measurements.  These are G20 and G21G20 means the machine coordinates are measured in inches and G21 means the machine coordinates are measured in millimetres.  I think the metric system is probably the best system to use in most things, but having grown up using the imperial measurements, I cannot make the switch all that easy so most of my stuff will be in inches.

Rapid Movements

Rapid movements are one of the most basic G-Codes.  It is represented by G0 (That is the letter G followed by the number zero.)  Rapids are intended to move to a certain location a fast as the machine can.  The actual rate at which the machine travels is very much machine and controller dependent.  My JGRO CNC Router for example can only rapid about 30 inches per minute (i.p.m.) if I drive it any faster the stepper motors will start missing steps.  It is important to note that rapids are only to be used to move from some place to another, you would never try cutting with a rapid as you will likely snap a bit or much worse.  It is also worth noting that when you rapid in more than one axis at the same time, it is up to the controller to decide how that were to happen.  Some controllers will do a single axis at a time while others will do all the given axis at the same time.  To complicate it further, when doing both axis at the same time, they may be coordinated to arrive at their programmed destination at the same time or they may arrive independently.  It is important to learn how your controller works.  And one more thing, when doing rapids make sure you have nothing in your path.  For example a vice or clamping fixture.  It is a bummer when you run into one of these.

Now that we have a little code under our belt, let's write our first program.

(Program to travel in a square staring from coordinate 0,0 with each side being 2 inches)
N1 G20 ;Set machine units to inches
N2 G0 X0 Y0 ;move spindle to origin
N3 G0 X2 Y0 ;do the bottom of the square
N4 G0 X2 Y2 ;do the right side of the square
N5 G0 X0 Y2 ;do the top of the square
N6 G0 X0 Y0 ;do the left side finishing the square

 A couple of things to note

Remember I said that line numbers are for the most part these days optional.  Another thing to note is that the controller will remember where a given axis is at any time.  For example in line N3 above we told the spindle to go to X2 Y0, well it was already at Y0 and the controller knows that.  Because of this behaviour we could have left the Y0 off the line.  Additionally, the controller remembers what motion mode it is in.  In this example we set it a G0 (Rapid Motion) so the additional G0 commands could be left off. So the above program could have been written as:

(Program to travel in a square staring from coordinate 0,0 with each side being 2 inches)
G20 ;Set machine units to inches
G0 X0 Y0 ;move spindle to origin
X2       ;do the bottom of the square
Y2       ;do the right side of the square
X0       ;do the top of the square
Y0       ;do the left side finishing the square

That was a lot smaller wasn't it.  We could have left the comments off to making it even smaller.  Things like this are good to know to save you time when writing G-Code programs by hand.  But it is worth noting that it is OK to put them in there like the first example.  Streamlining code to save you time writing it has diminishing returns.  Sure, you can write the code faster but the more you do like this the harder it becomes to understand.  Do what your comfortable with and most importantly do whatever helps you understand the program a little better.  More is usually better than less in this case even if it takes a little longer to type up!!!

In the next installment we will talk about linear feeds.  This is a basic G-Code to cut straight lines.

Linear Feeds

Welcome back.  So far we have learned about program numbers with the N code, comments with the ;, ( and ), rapid motion with the G0 command and finally setting the units with the G20 and G21 commands.  These are fine and dandy if you just like moving the machine around and watching.  However, we need it to do some work for is.  The most basic type of motion for a CNC router would be linear feeds.  This will allow us to cut straight lines.  Before we can do that, we need to learn a little more preparatory commands to make that possible.  So let's get started.

Selecting a Tool

At this stage of the game, I am guessing you are using an emulator of some sort to test your G-Code.  But we will proceed like we are actually going to make a real cut in something.

So in order to cut something the machine needs to know what tool it is using.  Some machines have an automatic tool changer while other machines you have to make the tool change yourself.  Not knowing Mach3, I will talk about how LinuxCNC works.  My home made JGRO CNC Router does not have a tool changer so obviously all the tool changes I make are by hand and when the code does a tool change, I get a dialog that tells me to insert toll number such and such.  This gives me the opportunity to get the tool in the router and continue.  LinuxCNC knows that I do not have a tool changer so does this for me.  If I had a machine with an automatic tool changer then LinuxCNC can be configured to use it.  The moral of the story is see what your controller does.

When we write G-Code or even use a CAM package to generate it, we derive our tool paths based on a particular tool.  These tools are stored in a table in the controller and if you have an automatic tool changer, it will be assigned to a particular slot.  For example, on my machine I have the tool table set to something like:

  • T1 - 1/4" flat end mill
  • T2 - 1/8" flat end mill
  • T3 - 1/4" ball mill
  • T4 - 1/8" ball mill
  • T5 - 1/2" 90° V Bit
  • T6 - 1/4" 60° V Bit
  • ...

You get the idea.  To select a tool using G-Code requires two steps.  1) Selecting the tool and 2) issuing a tool change command.  Selecting the tool is really simple, you use the T word with the tool number that you wish to use.  So looking at my list of tools above, if I wanted to make a cut with the 1/4" Ball Mill I would issue the command T3 in my G-Code.  This lets the controller know that when we make a request for a tool change, then that is the tool to go get.  Finally, making the tool change is very simple as well.  Simply issue the tool change command of M6.  When the controller sees the M6 command it knows to change the tool if you have an automatic tool changer and if you don't, LinuxCNC pops up a dialog asking you to load Tool # 6 into the machine.  Pretty easy.  There are other things to talk about tools, but we will discuss them later.  For now we are only worried about enough information to make a simple cut.

Controlling the Spindle

The spindle as you know holds the tool that you are cutting with.  The spindle on my JGRO CNC Router is a Hitachi router.  Bigger and better machines have a real spindle.  The spindle can be controlled by certain codes in your program.  They are pretty straight forward.  To start the spindle you will give either a M3 or M4 command followed by an S### command to tell it the speed. The M3 command will turn on the spindle in the clockwise direction at S### speed.  The M4 command will start the spindle in the counter clockwise direction at S### speed.  As mentioned earlier, the speed of the spindle is controlled by the S word followed by the speed at which you wish to run it.  If I wanted the spindle to run at 1,000 rpm, I would use S1000, if I wanted 25000 rpm, I would use S25000.  Now in reality, on my JGRO CNC Router it does not matter because I do not have the ability to turn on the router or control the speed with the controller.  Many people will install a solid state relay so that the M3 or M4 command actually does turn on the router.  I place these commands in my G-Code, but I manually turn on my router and set the speed with the dial located on the router.  So to turn on the spindle in the clockwise direction at 3000 rpm, I would use the command M3 S3000.  Finally, when I am done I need to turn the spindle off.  To do this we use the M5 command.  When the controller sees this command it will shut down the spindle if your spindle is controlled by the controller.

Controlling the Coolant

When you cut metal and other hard materials you have to have some sort of coolant running to keep the bits cool or you will just dull and burn them up and probably break them as well.  In my case, routing wood with a router there is no need for coolant.  But let's pretend we are on a real milling machine and we need to mill a slot in a piece of steel.  We have to keep it cool.  These machines are equiped with pumps that will either spray of flood the work area with coolant.  This coolant pump can be controlled with your G-Code by issuing the following commands. M7 will turn mist on.  M8 will turn flood on and M9 turns all coolant off.  So back to milling our slot, to turn on the coolant so that it floods the work we would issue the M8 command.  At the end of the job to shut the coolant flow off, we issue the M9 command.

Setting the Feedrate

The last item to cover before we can actually do the linear feed is talk about the feed rate at which it will run.  Feed rates are dependant on a lot of things.  The machine rigidity, the desired surface finish, the amount of material being removed, flute loading and more.  Determining feed rates can be more of an art than a science.  Setting the feed rate in your G-Code program is done with the F command followed by the desired feed rate.  Feed rate for a mill will depend on what units of measure you are in.  It will be either Inches per minute if in inch mode using the G20 command or millimeter per minute if you are in mm mode using G21.  So, if I were cutting a profile on my JGRO CNC Router, I may set it to something like 15 inches per minute.  Why so low, well more than that I get flex causing dimensional errors in the final part.  To set this feed rate in G-Code I would write F15.

Linear movement

We are nearing the point that we can write some G-Code.  The next item is the actual command that makes the machine do a linear move.  The command for this is G1.  This is a modal command meaning that it stays in effect until it is changed by another command such as G0 (Rapid move).  When G1 is issued the machine will use the feed rate from above.  When more than one axis is given both axis are moved so that the meet at the destination at the same time.  So if the tool was at the origin of X0 Y0 and the feed rate was set at F15, the I issued the command G1 X1 Y2 the tool will move from the origin to X1 Y2 as a straight line at 15 inches per minute.

Putting it all together

Let's say we have a job to cut a groove in an aluminum block.  The block is 2 inches on each side and .500 inches tall.  The bottom left corner of the block is sitting on X1 Y1.  We want to cut a groove .250 inches wide and .125 inches deep across the middle of the block from X1 Y2 to X3 Y2.  For this job we will use a .25 inch carbide 2 flute end mill.  Going to a calculator the spindle speed should be about 13000 rpm and the feed rate should be about 50 inches per minute.  Let us assume that the tool is at the origin X0 Y0 and 2 inches above the surface of the block.  Also we have set the Z origin to the surface of the aluminum block.  Let's write a program to make the groove for us.

(Cut a .125 deep .250 wide groove across a 2 inch block)
G20 ;Put the machine in inches T1 M6 ;Select the 1/4" end mill and change the tool F50 ;Set the feed rate to 50 Inches per minute M3 S13000 ;Turn the spindle on clockwise as run it at 13,000 RPM G0 X.5 Y2 Z-.125 ;Rapid the tool to the left of the block at .125 inch deep M8 ;Turn the coolant on flood G1 X2.5 ;Make the cut across the block G0 Z2 ;Bring the Z-Axis back to a safe height G0 X0 Y0 ;Bring the tool back to the origin M9 ;Turn the coolant off M5 ;Turn the spindle off M30 ;End of program

I have commented each line of the code.  Reading through it will tell you exactly what each line does.  There are two things to notice here.  First, I did not use line numbers.  Remember, I said they were optional. And second, you will notice that I threw a new G-Code at the end of the program.  To signify to the machine the the program has completed we use the M30 code meaning end of program.  This technically rewinds the program to the beginning.  If we were to remove the block we just cut and fastened another on in its place we could hit the cycle button on the controller and it would run again from the beginning.

The next installment we will cover Arc Feeds and cut a circle!  See you then.

G-Code Introduction

Back when I was trying to figure out what I needed to know to build and use a homemade CNC Router, I was overwhelmed with all the information I was staring at.  At that time I thought I would make some notes on what G-Code was and how it was used, but like many things, it fell to the wayside because there was another piece of the puzzle to figure out.  As a result it was left horribly incomplete and not really much use to anyone.  So I thought I would revisit the subject and see if I can elaborate on it any more.

I have to give you a disclaimer here.  I don't know all that much about G-Code, but will share what I have figured out with you.  I am only human so I am sure that everything I tell you may not be totally correct but I will do my best to make it so.  If you find an error and want to share your correction with me, please email me and I will update the pages.

What is G-Code

One definition I found on the Internet from 'Wikpedia' is: G-code is a common name for the programming language drive NC and CNC machine tools. It was developed by EIA in the early 1960s, a final revision was approved in February 1980 as RS274D.

Well, that was really helpful!  G-Code it seems is a language used to program machines. The Machine it turns out can be anything really, like a lathe, a robot like a line picker, or a CNC Router. The language as it was initially written was supposed to follow a strict set of rules or standards, These standards were the RS274D. These standards defines what each code would do. For example a G01 would be a linear feed and that sort of thing. Now that we know, at least rudimentary, what G-Code is, what does it look like and how do you write it?

Before we get too deep into this discussion, I would like to point out a couple of tools you can get to help you along the way.

1st - You will need something to write your G-Code with.  Any simple editor will work, for example Notepad, Notepad++ or wordpad for windows.  The important thing is that you do not want any formatting information embedded in the document, so Office would be a bad decision.  I mentioned wordpad but be sure to save your code as text only.  Any formatting information embedded in your G-Code will break it and make it unusable.  For Windows users there is an application called Auto Edit NC that you can use to write your G-Code.  You can get a copy of Auto Edit NC by clicking this link.  Also, a tutorial on using Auto Edit NC can be found at this site.  There may be others.  Google is your friend here.  For Linux users I you can use GEdit or any other text editor of your choice.  Again the important thing to remember is that you want only plain text and no formatting information embedded in the document.

2nd - It would be nice if there were an application that you could use to visualize the G-Code paths as they are being run.  There are a few applications that will do this for you.  In Linux you can use LinuxCNC (Formally known as EMC2)  LinuxCNC can be installed in simulator mode.  You can find information on doing this at the LinuxCNC Wiki - LinuxCNC Pure Simulator pages.  For the Windows users out there, there are a couple of options that come to mind.  The first is CutViewer and a 30 day free trial can be downloaded from  Another option for Windows users is CNCSimulator from  As far as I know this is a free program.  Again, there probably are more solutions available.  Google may be helpful here.  If you find one, use the CONTACT US menu option above and send us a link and I will include it here.

OK, before we start our discussion about G Code we need to come to some common ground. The reason why I say this is because it seems that everything about these machines is relative to something else. So, if we are on the same page about a few things the information I am trying to convey will be much easier to understand.

Axis Names and Direction

hand right rule thumbIt seems that there is a bit of controversy about the name of a particular axis and the direction it travels.  I think both sides of the argument have their merits but like every other obstinate fool out there I have my opinion too.  Since this is my website and my opinion, I will be going with mine, but will touch on both sides of the issue.

The first thing to discuss is the naming of the axis.  I will be using the right hand rule.  Now if you do a Google image search on the right hand rule, you will see several different images expressing it and it still is a little confusing.  But using the image at the left, I use the right hand rule as follows.  Extend your right hand in front of you with your palm facing up and your fingers extended away from your body.  Now point your thumb to the right, your index finger forward and your middle finger straight up.  Curl your ring and pinky fingers into your palm.  Now, as you look at your hand your thumb is the X-Axis, your index finger is the Y-Axis and your middle finger is the Z-Axis and they are point to the positive direction.  Now most people will agree with that representation.  The controversy starts when assigning axis to the machine itself.  I think most people will call the axis holding the spindle (router) the Z-Axis.  However, the X and Y axis becomes a debate.  Peter Smid, the author of the CNC handbook says the X-Axis should be the longest of these two axis.  Others think that the X-Axis is the axis you are facing as you face the machine during operation.  Now this may be improper, but it makes it easy to visualize the coordinates as you look at the machine.  It simply becomes a Cartesian coordinate system like you were used to in high school algebra with the Z-Axis moving up and down.

Some thoughts before moving on

There are a couple of things to remember about G-Code.  First, it is a programming language first and foremost, so if you are familiar with computer programming of the BASIC slant you should have very little problem getting the syntax of G-Code down and working.  For those of you who have never programmed, don't fret, the B in BASIC means beginner so it shouldn't take much to wrap your head around the concepts.  Second, there are terms like relative and actual positions, offsets, preparatory command and a bunch of other stuff that comes to mind when writing G-Code.  We will cover these as we get to them.  With that, lets move on to the next part of the tutorial, making the machine move.