How to Write Code for CNC Machine
This guide explains how to write code for CNC machine work, from G-code and M-code structure to CAM output and the first dry run. It is written for design engineers and buyers who need to read a program, check it, and know when hand-written code is the right call.

Key takeaways
What You Actually Write: G-Code and M-Code
A CNC program is a list of blocks. Each block is one line, and each line holds a letter address and a number: G for preparatory commands, M for miscellaneous machine commands, X Y Z for coordinates, F for feed, S for spindle speed, T for tool number. The control reads the list top to bottom and executes it. Nothing is implied; if you leave out a feed rate, the machine uses whatever modal value was active from the previous block.
G-code covers motion. G00 is rapid positioning at machine maximum, G01 is straight feed at the programmed F value, G02 and G03 are clockwise and counterclockwise arcs, G81 to G89 are canned drilling and tapping cycles. G17, G18 and G19 select the working plane for arcs and cutter compensation. G20 and G21 set inch or metric mode, and that single line changes how every coordinate after it is read.
M-code covers everything that is not a path. M03 starts the spindle clockwise, M05 stops it, M08 and M09 control coolant, M06 calls a tool change, M30 ends the program and rewinds. On a mill, M03 S8000 means 8,000 rpm clockwise. On a lathe with live tooling, the same M03 may need a station address first. The meaning is machine-specific, so always check the control manual.
One more distinction matters for how you write code for CNC machine work. G90 and G91 choose absolute or incremental positioning. In absolute mode every move goes to a fixed point from the part zero. In incremental mode each move is measured from the current position. Mixing the two by accident is one of the most common crash causes on a proven program.
- 1Block structureN-number is optional on modern controls; most CAM posts skip it.
- 2Modal stateG94 feed per minute, G95 feed per revolution. Pick one and stay in it.
- 3Cutter compensationG41 left, G42 right, G40 cancel. Apply on a straight lead-in move only.
The CAM Workflow Behind Most Production Code
Hand-written code still has a place, but it is a small place. Simple 2.5D plates, a drilling pattern, a repair on an existing program. Everything with curved surfaces, multiple setups or more than about twenty tools goes through CAM. The CAM system holds the geometry model, the stock model, the tool library and the post-processor, and it writes the coordinate lines you would otherwise type.
The chain starts with CAD. The model must be the finished part at nominal size. Tolerance and finish callouts live in the drawing or the 3D annotation, not in the model, so the programmer has to read them and pick cutting strategies that can hold ±0.005 mm where the drawing demands it. A 0.5 mm finishing pass cannot correct for a roughing strategy that left 0.05 mm of uneven stock.
Then the programmer sets the setup. That means choosing the workholding, defining the WCS origin, and deciding how many operations are needed. For a part that fits a 5-axis machine in one setup, the same geometry may need three setups on a 3-axis mill. Each extra setup adds an origin, an operator step and a chance for position error.
Finally the post-processor converts the internal toolpath into control-specific code. A Fanuc post uses G43 H for tool length compensation and M08 for flood coolant. A Heidenhain control accepts conversational cycles instead of G81 blocks. Same part, same tool, different text. The post is where a good CAM setup becomes a program the operator can actually run.
Before release, the programmer runs a stock simulation and a machine simulation. The first catches gouges and leftover material. The second catches holder collisions, table clearance and rotary axis limits. Both are faster than a crash.
- 1CAD modelNominal geometry, correct units, no scaling. Check the model against the drawing revision.
- 2Tool libraryReal holder and stick-out lengths. Gauge length errors cause holder crashes.
- 3Post-processorTied to the control family, not the machine brand. Verify with a known-good test part.
- 4SimulationStock removal plus machine kinematics. Run both before the program reaches the floor.
Feeds, Speeds and the Numbers That Break Tools
Most beginner programs fail on cutting data, not on coordinates. The two variables that drive everything are surface speed and chip load. Surface speed is the speed at which the cutting edge travels through the material, expressed in m/min or surface feet per minute. Chip load is the thickness of material each tooth removes per revolution, in mm per tooth. Spindle speed and feed rate are derived from those two.
For aluminum, a coated carbide end mill runs around 300 to 500 m/min surface speed. For 304 stainless, drop to 120 to 180 m/min. Titanium Ti-6Al-4V sits near 40 to 60 m/min. Inconel is lower still. These are starting points, not limits; tool coating, coolant delivery and rigidity move them. The formula for spindle speed is rpm = (surface speed × 1000) ÷ (π × tool diameter).
Feed rate follows from chip load: feed = rpm × number of teeth × chip load. A 10 mm three-flute carbide end mill in 6061 aluminium at 0.05 mm per tooth and 8,000 rpm gives 1,200 mm/min. The same tool in 304 stainless at 0.03 mm per tooth and 3,000 rpm gives 270 mm/min. Cut the feed in half and the tool rubs instead of cutting, which dulls it faster than a heavy chip load.
Radial and axial depth of cut set how much of the tool is engaged. Full-width slotting in aluminium is fine at 0.5 × diameter axial depth with good coolant. In stainless, keep radial engagement below 30 percent of the tool diameter and use trochoidal paths. Adaptive clearing strategies trade a wider path for a lighter load per pass, which keeps tool temperature down.
Plunge moves deserve their own feed. A tool entering vertically at cutting feed in steel will chatter or snap. Use a ramp or helix entry at 2 to 5 degrees, and set a separate plunge feed at roughly one third of the cutting feed when a vertical entry is unavoidable.
- 1Chip thinningWhen radial engagement drops below 50 percent, raise the feed per tooth to keep chip thickness.
- 2CoolantThrough-spindle coolant helps past 5 × diameter depth. Air blast suits aluminium and plastics.
- 3Tool runout0.01 mm of runout cuts effective tool life roughly in half. Check with a dial indicator.
When Hand-Written Code Beats CAM Output
Hand-written code wins on small, repeatable jobs. A drilling pattern on a flat plate, a facing pass, a chamfer run around a rectangular pocket. The program is 30 lines, the geometry is trivial, and setting up a CAM file takes longer than typing the code. Programmers keep a library of these snippets and edit the coordinates.
It also wins on the floor. When a tool breaks mid-run and the replacement is 0.2 mm shorter, the operator edits the tool length offset, not the program. When a finishing pass leaves 0.03 mm of stock, the programmer adds a spring pass in G01 at the same coordinates with a smaller radial step. That is a two-line edit, and it is faster than re-posting the whole job.
The trade-off is risk. Hand-typed coordinates have no simulation behind them, so a single wrong digit sends the tool into the vise. Keep manual edits inside a clearly marked section, back up the original program, and dry-run any edit on a part that matters. For anything with 3D surfaces, undercuts or more than two setups, CAM output is the safer path.
There is a middle route that many shops use: write the code in a text editor with a parametric macro. Fanuc custom macros with variables and IF statements let one program handle a family of parts by changing a few values at the top. A bolt-circle drilling program with a radius variable and a count variable covers every flange size without a new CAM file.
For prototypes at GreatLight, programmers often combine both. CAM handles the contoured surfaces; a short hand-written section handles the fixture bolt pattern and the part marking. The two are merged before the first run.
- 1Good candidatesDrilling grids, facing, chamfers, repair passes, fixture plates.
- 2Bad candidatesSculpted surfaces, 5-axis swarf cuts, anything with a collision risk near the holder.
7 Steps to Write and Prove a CNC Program
- 11. Fix the setup and the originChoose workholding, define the WCS origin at a feature you can touch off (a corner or a bored hole), and write it on the setup sheet. Most origin errors come from a drawing dimension measured from a face the operator cannot reach.
- 22. Set the safety blockStart every program with G21 (or G20), G17, G40, G49, G80, G90 and a G91 G28 Z0 home move. This clears modal state left by the previous job. Skip it and a leftover G41 can offset every move.
- 33. Define tools and offsetsList T numbers with H and D offsets matching the tool library. Call G43 H with the correct length offset on the first Z approach. Never assume the offset from the last setup is still valid.
- 44. Write or generate the toolpathsFor CAM work, post with the correct control, then read the first 20 and last 20 blocks manually. For hand-written work, keep one operation per section and label each with a comment in parentheses.
- 55. Set feeds and speeds from chip loadStart conservative, around 70 percent of the calculated feed, and raise it after the first part. Keep plunge feed at one third of cutting feed, and use ramp entry at 2 to 5 degrees in steel.
- 66. Simulate and dry runRun stock simulation, then machine simulation. On the machine, raise the Z offset by 50 mm, run in single block at 10 percent rapid override, and watch the distance-to-go screen.
- 77. Cut the first part and record changesInspect the first part against the drawing, then write every edit back into the master program. Unrecorded edits turn into a program that only the person who ran it can reproduce.
Hand-Written Code vs CAM Output
Match the method to the part, not to habit.
| Factor | Hand-written G-code | CAM output |
|---|---|---|
| Part geometry | Flat faces, holes, chamfers | 3D contours, pockets, undercuts |
| Setup count | One or two | Two or more, or 5-axis |
| Program length | Under about 50 blocks | Hundreds to thousands of blocks |
| Change speed | Seconds, in a text editor | Minutes, re-post required |
| Collision check | Operator experience | Machine simulation |
| Best use | Repairs, fixtures, drilling grids | Production parts, prototypes |
| Main risk | Typing error with no simulation | Post-processor or offset mismatch |
Get the Code Right Before the Spindle Turns
Hand-written code works for simple features; CAM output plus machine simulation is the safer route for contoured or multi-setup parts. Send us the model and tolerances and we will confirm the setup, the tolerances we can hold and the process route before cutting.
Frequently Asked Questions
Can I write CNC code by hand without CAM software?
Yes, for simple parts. Drilling patterns, facing passes and chamfers are easy to write by hand, and a 30-line program is faster to type than to set up in CAM.
The limit is geometry. Curved surfaces, blended corners and 5-axis motion need a CAM system, because calculating the tool center point by hand is impractical and error-prone.
What is the difference between G-code and M-code?
G-code controls motion and mode: G00 rapid, G01 feed, G02 and G03 arcs, G81 drilling cycle, G90 absolute positioning. M-code controls machine functions: M03 spindle on, M05 spindle stop, M08 coolant on, M06 tool change, M30 program end.
One rule to remember: G-code changes what the tool does, M-code changes what the machine does around it.
How do I calculate feeds and speeds for a new material?
Start with surface speed from the material group: roughly 300 to 500 m/min for aluminium, 120 to 180 m/min for 304 stainless, 40 to 60 m/min for Ti-6Al-4V. Convert to spindle speed with rpm = (surface speed × 1000) ÷ (π × tool diameter).
Then set feed from chip load: feed = rpm × teeth × chip load. Run the first part at about 70 percent of that feed and raise it once you hear and see a stable cut.
Why does my program run fine in simulation but crash on the machine?
Simulation uses the model in the CAM system. The machine uses the real fixture, the real holder and the real tool stick-out. A holder that is 10 mm longer than the library value can hit the part while the simulation shows clearance.
Check three things: tool gauge length, fixture height in the model, and the work offset values actually set on the control.
What should be in a setup sheet?
The setup sheet should carry the part number and revision, the operation sequence, the WCS origin location, the tool list with T H D numbers, the fixture used, and the inspection points with tolerances.
It should also carry the program name and the control it was posted for. A program posted for a Fanuc control will not run unchanged on a Heidenhain machine.
Does a 5-axis program need different code?
It needs the same G-code structure plus rotary axis addresses, usually A, B or C. The bigger difference is that the CAM post must output either table rotations or tool center point management, depending on the control.
On machines with RTCP or TRAORI, the control compensates for the pivot distance. Without it, the post has to do that math, and any error shows up as a taper on the part.
Send Your Model, Get a Machining Plan
Upload your CAD file and drawing. Our engineers review the setup, tool access and tolerance stack, then return a quotation with a free DFM analysis within 12 hours.
12-hour quote100% inspectionNDA on request