CNC Math

The follow information on programming macros comes from the experienced and very talented G-code programmer David Hagan.

Macro Programming And Using Variables.

What is a macro? A complex operation that is represented by a single command. For example, canned cycles such as the G80 series drilling cycles or G70 series turning cycles are macros that are provided as standard features by CNC control manufacturers.
These are possible due to the use of variables. If your CNC control has macro options you can use variables along with math and logic statements to simplify programming of part families and / or create custom canned cycles, even add features to machines such as tool measurement or part locating and measurement probes.
However, before you can create canned cycles or add features to equipment and expect them to function correctly you should understand variables along with math and logic statements. In this installment we’ll cover the basics.


Simply put, variables are places to store numbers. Their address is signified by “#”, the number sign.
There are 3 types of variables. Local, common, and system variables.

Local Variables

Local variables are assigned #1~#33. Each is assigned to a specific letter.

#1=A        #4=I        20=T
#2=B        #5=J        21=U
#3=C        #6=K        #22=V
#7=D        #13=M        #23=W
#8=E        #17=Q        #24=X
#9=F        #18=R        #25=Y
#11=H        #19=S        #26=Z

Local variables are passed to the macro program at the time it is called; they are local to the program that is called.
Ex. G65 P9110 X4.0 Y5.0 Z6.0 A45.0 B-60.0
G65 = call a macro
P9110 = macro called is O9110
X4.0 = value of 4.0 is stored in #24
Y5.0 = value of 5.0 is stored in #25
Z6.0 = value of 6.0 is stored in #26
A45.0 = value of 45.0 is stored in #1
B-60.0 = value of -60.0 is stored in #2

When the data block containing G65 executes, program O9110 is called and the XYZAB data is transferred into the local variables.
Local variables are cleared when the reset button is pressed. Something to keep in mind in case the program is interrupted and reset is pressed.

Common Variables

Common variables are assigned #100~ #149 and #500~ #531 (optional #100~#199 and #500~#999). These can be used for what ever is needed. The key characteristic of these variables is that they are common to all macro programs, so if one macro puts a value in #100 another macro can also read that value.
The difference between variables #100~#149 and #500~#531 is that #100~#149 are cleared when the power to the CNC is shut off, #500~#531 are backed up by battery.

System Variables

System variables are assigned #1000 and up. These allow you to read the CNC display information, depending on the information some variables can be written from the macro. Everything you can see on CNC screens can be accessed in a macro program using system variables. There’s a lot of ground to cover with system variables so we’ll deal more with them in a future installment.

Macro Arithmetic Instructions

The CNC will perform math functions following the standard MDAS order of operations. Brackets “[ ]” are used to force the order of operations, which will affect the result. Ex. #100=[5+[4*2]-[6/3]];
Why do the math when the CNC can do it for you? Incidentally, math functions can be placed in word addresses too, that is, the above example could be an axis destination in a data block. Ex. N220 G1 X[5+[4*2]-[6/3]]; .

Trig functions are useful for calculating positions based on angles. There are 4 functions available:

Sine         SIN[ angle]
Cosine        COS[angle]
Tangent        TAN[angle]
Arctangent        ATAN[value]

Scientific functions include:
Square root    SQRT[number]
Absolute value    ABS[number]
Rounding        ROUND[number]
Fix            FIX[number]
Fix up        FUP[number]

Sqrt is self explanatory. ABS returns the absolute value of a number, that is ABS[-2] yields the result 2. Round will round to the nearest whole number.  Fix removes everything to the right of the decimal point and FUP rounds up to the next whole number.

Decisions and Loops

The real power behind macro programming is in its ability to make decisions, looping allows the repetition of a process until groups of actions have been completed.
The IF statement is used to make decisions. After the IF statement is a bracketed statement. If the evaluated statement is true then the bracketed statement is performed. If the evaluated statement is false the bracketed statement is not performed. There are 6 decision statement operators, they are:
EQ        equal to (=)
NE        not equal to (<>)
GT        greater than (>)
GE        greater than or equal to (>=)
LT         less than (<)
LE        Less than or equal to (<=)

If statements are formatted:
IF[#101EQ0] GOTO3000;
Where if #101 contains the value 0 the CNC will jump to sequence number 3000.
IF can also be used to conditionally set a variable:
IF[#500NE1] THEN[#501=.75];
Where if #500 does not contain the value 1 #501 contain the value .75.

The WHILE statement is used to create a loop. A loop repeats itself until the conditional statement is true.  Example:
While[#110LT6] DO1;
G1 Z-1.0;
G0 Z.1;
G91 X2.0;
G30 Z0;

This would result in 6 holes being drilled along the X axis in 2 inch (or mm) increments then the tool will go home and the program would end.

The DO and END statements work together to indicate the beginning and end of process loops; loops can be nested 3 deep.

In the next installment we’ll look at some practical applications of what has been covered so far and take a look at system variables.

Gcode and CNC math tips

Setting up a Gcode program and do not want to manually type in .375, .750, 1.125,
1.500…etc? It’s easier to program a sub routine in gcode then type that 100+ times, how can this be automated?

method 1

Write the code for one then save that into a subroutine. The next program moves to the start of the next cut, in this case next slot, uses G93 to set offset that starting position to be zero, and calls that subroutine. When done,  move to the next starting point and G93 X0, Y0 to set X and Y to zero again for the next subroutine.

The subroutine program is like a normal program but replace the M30 at the
end with M99

The easiest way to learn this is to use the nesting wizard, look at the
program it creates and use that.

In Mach there is one problem, It will draw your program in the tool path
correctly before you start the job, however during the job the traced line
forgets there is a G93 offset, so each subroutine is draw on top of the last
one at the normal work offset co-ordinates.

another approach would be using G91 (incremental) rather than G92 (offset coordinate) In which case you add to your loop the line : G91 X0.375
To repeat every 3/8″ then don’t forget you need to do a G90 to get back to absolute mode instead of incremental.

Another approach would be using a hack in MS Excel 2003 or later, earlier version might work too.

method 2

Open a blank page in Excell

>At A1 type .375
Hit enter and the highlight will move to A2

Type .750
Hit enter



Now, for the magic…

Pasting from Excel will have each column element separated by a Tab so if you need a space or other character, you will need to search and replace outside of Excel.

If you are going to use Excel, you can just start with cell A1. Type
0.375 into this cell. Then select cells A1 through A100, next choose
“Fill” (I think it is in the edit menu, then “Series” and change the
increment value in the dialog to 0.375. It will fill the cells from A1
to A100 with values incremented by 0.375 in this case.

method 3

Start by defining the variable,

#01 = 10 (sets variable 01 to a value of ten)

Use it like

G0 X[#01]

you can also do

G0 X[#01+10]

Or have another variable that is the offset and try

G0 X[#01+#02]

Or let the offset progressively add to the #01

#01 = [#01+#02}

G0 X[#01]

Set you offset and call your subroutine.

Now copy and paste that above, so each time it runs X moves on by value in

Information Nuggets

  • The ID (in) of a finger ring can be found from ID=0.032*R+0.458 where R is the ring size, e.g., size 6 ring has an id of 0.65 in.
  • The major diameter of a numbered thread (e.g. 6-32) is given by D=0.013*N+0.060 so a #6 has a major diameter of 0.138 in.
  • A rough way to calculate tap drill size (DRILL is much better) is to subtract the pitch (in units of length/thread) from the nominal diameter:
    1/4 (in) – 20 (tpi) => 1/4 (in) – 1/20 (ipt) = 0.2 in (#7 drill)
    6 x 1 mm => 6 – 1 = 5 mm
  • pi~=355/113 with an error of only 0.002% (22/7 is in error by 0.9%)
  • A (US) penny is almost exactly 0.75″ diameter.
  • A (US) nickel weighs ~5 grams.
  • A (US) dollar bill is (imprecisely) 2.5 x 6″.
  • A (US) standard(?) business card is 2 x 3.5″.
  • Zig-Zag cigarette paper is ~0.001″ thick.
  • Metric length conversions aren’t difficult. The (Imperial) inch is defined as exactly 25.4 millimeters. Memorize that number.
  • John Pagett of Birmingham, UK sent along a clever way of converting fractional inches to their metric equivalent. Keep doubling numerator and denominator until the denominator is 256. Then the numerator divided by ten is the equivalent in mm with an error of only 0.78%
    13/64 = 26/128 = 52/256 -> 52/10 -> 5.2 mm (correct value = 5.159375 mm)
  • Steve Redmond points out that mm->in can be done approximately by multiplying by 4 and dividing by 100.
    30 mm * (4/100) =~ 1.2 in (correct value = 1.181)
  • Rule of thumb for milling cutters: depth of cut <= 0.5 * cutter diameter.
  • Stan Dornfeld sends along a handy relation he uses for calculating feeds when drilling:
    d = drill diameter (in)
    r = spindle speed (rpm)
    f = feed (in/min)
    f = d * r / 30
  • Quick way to compute allowance for standard 118 deg. drill tip: multiply drill diameter by 0.3
  • A one foot head of water exerts a pressure of 0.433 psi. A 2.309 feet head of water exerts a pressure of one psi.
  • The flow (GPM = gallons/minute) from a horizontal pipe of (inside) diameter d (in) can be estimated by measuring how far from horizontal the stream has dropped, y (in), at a distance x (in) from the end of the pipe and using the formula GPM = 2.56 * x * d * d / sqrt(y).
  • Most people, when they make homemade signs, make the letters way too small. A good rule of thumb is 2.5 to 3 inches of letter height for every 100 feet of viewing distance.
  • Tap drill size for a thread-forming tap can be found from:
    tap drill = OD – 0.0068*(DOT)/pitch
    For example, with a 1/4-20 tap and a desired depth of thread of 65%, we have:
    tap drill = 0.25 – 0.0068*65/20 = 0.228 in. (#1 drill)
  • This one from Redgie Joy:
    When grinding cutting tools to an accurate profile it is difficult to prevent the layout from getting destroyed by the heat of grinding. Neither Dykem blue or magic marker stand up very well. Mix a dilute solution of Copper Sulfate (Blue Stone) and water. A couple of small lumps dissolved into water is fine. Add a drop or two of Sulfuric Acid (Battery Acid). The acid is not necessary, it just makes it work better. Degrease the toolbit, then paint a drop or two of the solution on the bit. It will immediately leave a thin coating of copper plate on the bit. Wash off in water, then scribe the profile in the copper plate. The copper will not burn off during heating, and since it is very thin, it is possible to engrave extremely fine lines.
  • The Imperial measurement system is hands-down one of the most nonsensical systems still used in (a few) industrialized countries. One of its most ludicrous examples is the system used for indicating the weight of an anvil. A triplet of numbers, e.g., a:b:c, is cast into or stamped onto the anvil. The first number is the number of hundredweights (cwt), the second number is the number of quarters (of a cwt), and the third number is pounds. Thus, the formula for the weight of the anvil in pounds is: 112*a + 28*b + c. The fact that a hundredweight is really 112 pounds and not 100 pounds has something to do with the British who thought eight stone ‘looked’ like about 100 lbs. Since a stone is 14 pounds, 8*14 = 112. Contact John Cleese at the Ministry of Funny Walks and Ridiculous Units for further information.
  • The full series of BA (British Association) threads runs from N=0 to N=22. The pitch of a given thread is given by P(mm)=(0.9)^N and its diameter is given by D(mm)=6 * P^(1.2). All BA threads have a thread angle of 47.5 deg.
  • The volume of a pizza of thickness ‘a’ and radius ‘z’ is given by pi z z a.
  • If you’re going to check a micrometer for accuracy, it’s important to use a set of gage blocks that cause the spindle to seat at different orientations so drunken thread errors will be noticed. The preferred set for inch micrometers is: 0.105, 0.210, 0.315, 0.420, 0.500, 0.605, 0.710, 0.815, 0.920, 1.000. For metric micrometers the preferred set is: 3.1, 6.5, 9.7, 12.5, 15.8, 19.0, 21.9, 25.0.


10 thoughts on “CNC Math

  1. I wouldn’t recommend using local variables (#1 ~#33) as shown in method 3, as they are assigned to a specific letter (at least 1-26 are), i.e. #1=A, #2=B,… #24=X, #25=Y, #26=Z. The values assigned to these variables will be replaced often during program execution, not to mention they are cleared by pressing reset. A better choice would be to use common variables #100~#149 & #500~#531 (optional #100~#199 & #500~#999) although the commons below #500 are returned to null when power is shut off, not the case for #500 and above.

    Also, if you have custom macro options available in your control, writing a little DO / WHILE logic routine within the program often adds much more flexibility than a subroutine and does not require loading additional programs into memory.

  2. Another useful nugget, one that occasionally gives seasoned machinists headaches, to convert RPM back to SF/M. (RPM* diameter)/3.82

    This is particularly useful for working with exotic materials when the “zen” moment occurs where you find a speed that provides good tool life for one tool and need to repeat the results with several following tools of different sizes, or threading shafts of various sizes, etc.

  3. is gcode compiled? what is the underlying software that it runs on linux windows? it is capable of higher level programming like loops and arrays? i need to know as we just bought a CNC mill

  4. is gcode compiled? what is the underlying software that it runs on linux windows?

    Sam, I’m not really sure about what you’re asking. Who makes the cnc control on your machine, Fanuc or a clone, Mazak, Mitsubishi, other?

    Most controls out there can read a file written in a basic text format, however the Mazaks I’ve worked with in the past would read binary files.

    Without knowing who made the cnc side I’m going to WAG that you’ll be able to type a program using windows notepad and then save the file without an extension, use quotation marks at the beginning and end of the program number, do not let windows create an extension for you. You should then be able to load the program via the RS232 port or via flash drive or memory card

  5. use quotation marks at the beginning and end of the program number

    That should be interpreted as: use quotation marks at the beginning and end of the file name you save it as.

  6. Converting a Fraction to Decimal is simply Numerator divided by Denominator:

    3/16 is 3 divided by 16 or .1875

    So converting the fraction to metric is:

    3 / 16 * 25.4 = 4.7625

    more accuracy:

    3 / 16 / .03937 = 4.7625095250190500381000762001524

    Obviously one can find more confusing ways to do this, but why?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s