CNC Mill Programming: A Practical Guide for G-Code on Machining Centers
CNC mill programming is the process of writing instructions that tell a machining center exactly how to move its axes, control the spindle, manage tools, and remove material from a workpiece. Every instruction is written in G-code — a standardized language that controllers like Fanuc, Haas, Heidenhain, and Siemens all interpret, each with their own dialect.
This guide covers the core concepts you need to write reliable, safe G-code for 3-axis vertical machining centers.
How a CNC Mill Program Is Structured
A typical milling program follows a predictable sequence:
- Safety header — cancel any active modal codes, return to known state
- Tool call — select tool, call tool length offset
- Positioning — move to start position in rapid
- Cutting — execute the toolpath at feed rate
- Retract and end — return to safe position, stop spindle, end program
A minimal working program looks like this:
%
O1000 (FACE MILLING EXAMPLE)
G17 G21 G40 G49 G80 G90 (safety line)
G28 G91 Z0. (return Z to home)
G90
T1 M6 (call tool 1)
G0 G90 X-10. Y-10. S4500 M3 (position + start spindle)
G43 H1 Z50. (activate tool length offset)
M8 (coolant on)
Z2.
G1 Z-0.5 F300 (plunge to depth)
X110. F800 (face pass)
G0 Z50. (retract)
M9 (coolant off)
M5 (spindle stop)
G28 G91 Z0. (Z home)
G28 X0. Y0. (XY home)
M30 (end program)
%
Each line is a block. Each block contains one or more words — a letter followed by a number. G words select motion modes, M words control machine functions, and axis words (X, Y, Z) define positions.
The Safety Line
Every program should begin with a safety block that resets the controller to a known state:
G17 G21 G40 G49 G80 G90
- G17 — select XY plane (standard for milling)
- G21 — metric mode (use G20 for imperial)
- G40 — cancel cutter radius compensation
- G49 — cancel tool length offset
- G80 — cancel any active canned cycle
- G90 — absolute positioning mode
Missing this block means the machine inherits whatever modal state was active from the previous program — a common source of unexpected behavior.
Coordinate Systems
The machine has a fixed origin called machine zero (or machine home). Your part has its own origin called the work offset or datum, stored in registers G54 through G59 (and extended offsets beyond that).
When you program G54 X0 Y0, the machine moves to the work zero of your part — not to machine home. This lets you run the same program on different fixtures without rewriting coordinates.
G90 G54 (activate work offset 1)
G0 X0 Y0 (move to part zero)
The most common mistake for new programmers is forgetting to call a work offset, leaving the machine running in G53 (machine coordinates) — which puts the tool somewhere completely unexpected.
Modal vs. Non-Modal Codes
Modal codes remain active until cancelled or replaced. If you program G1 X10. F200, every subsequent block that moves an axis will continue at feed rate F200 in linear interpolation until you call G0 or another motion mode.
Non-modal codes act only on the block they appear in. G28 (return to home) and G04 (dwell) are non-modal.
Understanding modal behavior is critical — it explains why you don't need to repeat G1 on every line, and why leaving a modal active by accident causes crashes.
The Three Motion Modes
G0 — Rapid positioning
Moves all axes simultaneously at maximum speed. Never use G0 for cutting. Use it to position above the workpiece and to retract after cutting.
G0 X50. Y30. Z5. (rapid to position above part)
G1 — Linear interpolation
Moves in a straight line at the programmed feed rate. Use for all cutting moves.
G1 Z-5. F150 (plunge 5mm at 150mm/min)
G1 X100. F600 (cut across at 600mm/min)
G2 / G3 — Circular interpolation
Cuts arcs. G2 is clockwise, G3 is counterclockwise (when viewed from above in G17 plane).
G2 X50. Y0. R25. F400 (CW arc, radius 25mm)
G3 X0. Y50. I0. J25. (CCW arc using I/J center offsets)
Tool Length Compensation — G43 / G49
Every tool has a different length. G43 activates the tool length offset stored in the H register, so all Z positions are measured from the part surface rather than from some arbitrary machine reference.
T2 M6 (load tool 2)
G43 H2 Z50. (activate offset for tool 2, move Z to 50mm above part)
Always cancel tool length compensation with G49 (or by calling G28) before the program ends. Leaving G43 active between tool changes leads to Z position errors.
Feed Rate and Spindle Speed
Feed rate in G1/G2/G3 moves is programmed with F, in mm/min (G21) or inch/min (G20).
Spindle speed is programmed with S and activated with M3 (clockwise) or M4 (counterclockwise).
S6000 M3 (6000 RPM, clockwise)
G1 X80. F500 (cut at 500 mm/min)
Surface speed mode (G96) keeps the cutting speed constant as diameter changes — common on lathes, occasionally used on mills for facing operations.
What to Check Before Running a New Program
Before pressing Cycle Start on a new program, verify:
- The correct work offset is active (G54/G55/etc.)
- Tool length offsets are set and match the H numbers in the program
- The safety line at the top cancels all modal codes
- Z clearance moves use G0, not G1
- Spindle direction is correct for the tool (M3 for standard end mills)
The fastest way to catch errors before they reach the machine is to run the program in a G-code simulator. Eureka3X loads the actual NC file and simulates it on a full 3D machine model — collisions, over-travels, and positioning errors show up on screen before any metal is cut.
Try Eureka3X free for 30 days →
Next Steps
Now that you understand the structure of a mill program, explore the specific codes that handle the most common milling operations: