Mike Is Making Stuff sticker

Subprogram Looping and Macro Calls in Fanuc G-Code

By Mike · Published October 6, 2026 · Updated October 9, 2026

Repetitive machining, drilling a bolt circle, milling a pocket pattern, engraving a row of labels, does not need repetitive code. Fanuc G-code provides subprograms and macro calls that let you write an operation once and invoke it many times with different parameters. This is not just tidiness: parameterized code is shorter, easier to proofread, and far less error-prone than a hundred hand-copied blocks, because a fix applied once propagates everywhere. For CNC routers doing production or pattern work, subprograms are a core skill.

Subprogram Looping and Macro Calls in Fanuc G-Code

Subprograms: Write Once, Call Often

A subprogram is a separate block of G-code stored under its own program number, typically in the O9000 range on Fanuc controls, that the main program invokes with M98. The call specifies which subprogram and how many times to repeat it: M98 P1001 L5 calls subprogram O1001 five times. When the subprogram ends with M99, control returns to the main program at the block after the call. The classic use is a repeated feature: write the drilling cycle for one hole as a subprogram, then call it from a main program that positions to each hole location. Change the peck depth once in the subprogram and every hole updates. Stay modally aware: a subprogram inherits the main program's modal states, so it should set what it needs explicitly and document what it changes.

Arguments: Passing Parameters

A plain subprogram repeats identically; arguments make it flexible. Fanuc macro calls pass values through letter addresses: M98 P1001 with A, B, C arguments, or the G65 macro call which is designed for it. Inside the subprogram, those arguments arrive as numbered variables (#1 for A, #2 for B, and so on). A bolt-circle subprogram might take the circle radius, the hole count, and the Z depth as arguments, then compute each hole position internally. This transforms the subprogram from a fixed routine into a reusable tool: the same bolt-circle macro drills any bolt circle on any part by changing three numbers at the call site. Keep a comment header in each macro documenting which letter means what.

Looping Inside Macros

For patterns computed at runtime, macros support looping with WHILE statements and conditional branching with IF/GOTO. A WHILE loop repeats a block while a condition holds: stepping an angle variable from zero to 360, computing each hole's XY with trigonometry, drilling, and incrementing. This is how you machine patterns whose geometry is easier to compute than to list: bolt circles, grid arrays with skipped positions, radial slots. The loop variable discipline matters: initialize before the loop, increment inside it, and make sure the termination condition is reachable, because an infinite loop on a CNC control is not a crash you can Ctrl-C; it is a machine doing something unexpected until someone hits feed hold. Keep loops simple and test in single-block mode first.

Variables and Arithmetic

Fanuc macros provide numbered variables (#100 and up for general use) and a full set of arithmetic and function operations: addition, subtraction, multiplication, division, square root, sine, cosine, arctangent. This is a real, if spartan, programming environment inside the G-code. Use variables for anything computed or reused: positions derived from part dimensions, step counts, depth increments for multi-pass cuts. The payoff is parametric programs where changing the part size means changing a few variable assignments at the top, not editing dozens of coordinates. One caution: variable #0 is always null/empty and reads as zero in most contexts, which is useful for detecting unset arguments but treacherous if you assign to it expecting storage. Another: macro variables persist across programs on many controls, so initialize everything your macro uses rather than assuming a clean slate.

Structuring Main and Subprogram Files

Organization keeps macro-based programs maintainable. Keep the main program readable: a short sequence of setup, then macro calls with clear comments stating what each call machines. Store commonly used macros, bolt circles, grid drilling, rectangular pockets, in the protected O9000 range so they are available to every job and not accidentally edited per-part. Document each macro's arguments, units, and any modal states it expects or changes, right in the macro's comment header. When a macro improves, update the stored copy once rather than maintaining per-job variants that drift apart.

Safety Practices for Macro Code

Macros concentrate power, which concentrates risk. A bug in a hand-written block ruins one feature; a bug in a macro ruins every feature it machines. Prove every new or modified macro with a dry run: single-block mode, reduced rapid override, Z offset raised, watching each motion before it happens. Verify argument handling with edge cases: zero holes, one hole, the maximum count, because loops and arithmetic fail at boundaries first. Keep a written log of proven macros and the jobs they ran successfully; trust accumulates with evidence. And respect the control's limits: deeply nested macro calls and very long loops can exceed buffer or nesting limits on older controls, so test at full scale before committing to a production run.

Subprograms turn repetition into reuse; macros turn reuse into parametric power. Write the operation once, parameterize it, loop where the geometry computes cleanly, and prove it dry before it cuts. The machine will happily drill ten thousand holes from twenty lines of code, exactly the same every time.

Related Guides

← Back to Resources