Fanuc Custom Macro B is a parametric programming language built into FANUC controls that lets you write CNC programs driven by variables instead of fixed numbers. Instead of editing dozens of lines for every part variation, you write one macro that calculates positions, feeds, and cycle counts on the fly. You should reach for it whenever a job repeats with small changes, needs loops or conditional checks, or calls for math a plain G-code block cannot do. Before writing one, confirm support by looking for the MAC VAR soft key or running a short MDI test.
TL;DR:
- Macro B variables are organized by range, with local (#1-#33) resetting each call, common (#600-#699) persisting across programs, and system variables (#1000+) linked to control functions.
- Use trig functions like SIN, COS, and TAN with degree inputs, and perform pre-calculations outside loops to optimize control performance during machining.
- Validate macro inputs with range checks and custom alarms to prevent silent failures, ensuring safety and predictable operation.
- Support for Custom Macro B can be confirmed by locating a MAC VAR soft key or running a simple MDI test program that reads and writes variables without alarms.
- Developing macros for recurring shop tasks benefits from clear comments, consistent variable usage, and version control, while leveraging calculators and validation tools to improve reliability.
Table of Contents
- What Fanuc Custom Macro B Is and Core Concepts
- Variable Types and Scope: Local, Common, and System
- Expressions, Arithmetic, and Built-In Functions
- Control Flow: Conditionals and Loops
- Subprograms, G65 Calls, and Argument Passing
- Practical Examples and Recipes You Can Adapt
- Testing, Debugging, and Portability Across Machines
- How Machining Calculators Speed Up Macro B Development
- Error Handling and Recovery Techniques
- Organizing Macro B Code for Readability and Reuse
- Security Considerations When Using Macro B
- Integrating Macro B With Standard Cycles and Offsets
- Performance and Optimization Tips
- Practitioner Perspective: When Macro B Earns Its Keep
- Build Macro B Programs Faster With Availzye Machinist Pro
- FAQ
- Sources
What Fanuc Custom Macro B Is and Core Concepts
Custom Macro B is FANUC's implementation of parametric programming, using variables such as #1, #150, #600, and #1000 and up so a program can calculate, branch, and repeat instead of running the same fixed sequence every time. A plain G-code program is static: change the hole pattern and you rewrite every line by hand. A macro program reads arguments, computes the geometry, and runs the same logic for a new part family without a rewrite.
This matters most in a handful of recurring shop situations, where embracing the latest technologies driving the future of manufacturing can make parametric programming even more worthwhile:
- Family-of-parts work: one macro handles a range of bore diameters, bolt circles, or pocket depths by changing only the input arguments.
- Cycle-based checks: a macro counts parts and pauses for an operator check every set number of cycles.
- Geometric calculations: trig-driven patterns, such as evenly spaced holes or scalloped profiles, get computed inside the program instead of pre-calculated by hand.
Macros turn a program into something closer to a small application: it takes inputs, makes decisions, and produces motion. That shift in mindset, not the syntax itself, is usually what separates a basic programmer from one who writes reusable code.
Variable Types and Scope: Local, Common, and System
Macro B organizes variables by number range, and each range behaves differently in terms of lifetime and visibility. Mixing these up is one of the most common sources of bugs in shop-floor macros.
- Local variables (#1 to #33): scoped to the current macro call; they reset or get reassigned when a new subprogram call starts, which makes them safe for temporary math inside one macro.
- Global per-channel variables (#150 to #199): hold their value across subprograms on the same channel, useful for passing data between a main program and nested macros on multi-channel controls.
- Common variables (#600 to #699): persist across programs and power cycles on many controls, so they're a good fit for counters, such as a part-check tally that needs to survive a program restart.
- System variables (#1000 and up): map to control functions like tool offsets, work coordinate systems, and alarm states.
Lifetime is the detail that trips people up: a local variable you expect to hold a value from an earlier call may have already been cleared by a nested subprogram call. For writing offsets, the general guidance is to prefer G10 for portability between machines, reserving direct system-variable writes for cases where you need to read an offset value back into a calculation.
Pro Tip: Keep a one-page variable map taped near the control for any macro using common or system variables, so the next programmer does not have to reverse-engineer what #601 means.
Expressions, Arithmetic, and Built-In Functions
Macro B expressions use standard arithmetic operators (+, -, *, /) inside brackets, and the control evaluates bracketed expressions much like a calculator does. A typical assignment looks like #101 = [#100 * 2] + 5, and nested brackets control order of operations the same way they would in a spreadsheet formula.
Trigonometric and utility functions cover most of the geometry math a programmer needs:
- SIN, COS, TAN: take arguments in degrees, not radians, which is the detail that catches programmers coming from other languages.
- SQRT: extracts a square root, handy for hypotenuse or bolt-circle radius calculations.
- ABS: returns an absolute value, useful when a sign could flip depending on tool direction.
- POW: raises a value to a power, for scaling or area calculations.
- FIX and ROUND: truncate or round a result, which matters when a calculated position needs to land on a clean increment.
A bolt-circle hole position might be written as #110 = #100 + [#101 * COS[#102]], where #100 is the center X, #101 the radius, and #102 the angle in degrees. Writing the formula out this way, with each variable mapped in a comment line, keeps the macro readable months later.
Control Flow: Conditionals and Loops
Decision-making in Macro B runs on IF [condition] THEN statements, and the comparisons use relation operators rather than symbols in some dialects: EQ (equal), NE (not equal), GT (greater than), GE (greater than or equal), LT (less than), and LE (less than or equal).
- Simple conditional:
IF [#1 EQ 0] THEN #1 = 1resets a counter when it hits zero. - Compound conditions: AND and OR let you combine checks, but not every control accepts them the same way, so test compound logic on each machine before relying on it in production.
- WHILE/DO loops:
WHILE [#1 LE 10] DO1...END1repeats a block until the condition fails, and every loop needs a variable that actually changes inside the loop body or it never terminates. - GOTO and block numbers:
GOTO100jumps to a labeled block, but heavy use of GOTO makes a program hard to follow; reserve it for error traps and loop exits rather than general flow control.
Pro Tip: Always build a maximum iteration count into a WHILE loop as a safety net, even when the exit condition looks solid on paper, so a logic error stalls the program instead of running indefinitely.
Subprograms, G65 Calls, and Argument Passing
Subprograms are what make a macro reusable across jobs rather than rewritten each time. A main program calls a macro subprogram with G65 P1000 A10.0 B5.0 C2.0, where P1000 identifies the subprogram number and the letter addresses pass arguments into the macro's local variables.
- Argument mapping: FANUC maps each letter address to a specific local variable number (A to #1, B to #2, and so on), so the subprogram reads
#1,#2, and#3to recover the values passed in as A, B, and C. - Store and reinitialize: good practice copies incoming arguments into named local variables at the top of the subprogram and resets any working variables so leftover values from a prior call cannot leak into the new run.
- Subprograms versus inline macros: a subprogram earns its place when the same logic runs from multiple programs or multiple times in one program; a one-off calculation that runs once is often simpler left inline.
This calling convention is also what makes the part-check and family-of-parts patterns below practical: the same subprogram handles a new part just by changing the arguments in the calling line.
Practical Examples and Recipes You Can Adapt
These three patterns cover the bulk of what shows up on a shop floor, and each one follows the same shape: accept arguments, validate them, calculate, then run motion.
- Part-check every N cycles: a common variable (say #601) increments at the end of each part program. An
IF [#601 GE #602] THENblock compares the counter to a target count, stops the machine with an M0, and prompts the operator to check the part before resetting the counter to zero. - Family-of-parts macro: a subprogram called with
G65 P2000 A[angle] B[offset]accepts an angle and an offset as arguments, calculates the finished position with SIN and COS, and runs the same cutting cycle regardless of which part variant is loaded. - Pattern generation: a WHILE loop paired with COS and SIN produces evenly spaced features around a circle or along a sine-based profile, incrementing an angle variable each pass and recalculating X and Y before each cut.
For each of these, the same checks apply:
- Dry-run first: run the macro in single block with the spindle off and rapid override low, watching the position readout against your hand calculations.
- Watch the variables: use the control's macro variable display to confirm #101, #102, and so on hold the values you expect at each stop.
- Know your alarms: an undefined variable used in a calculation, a division by zero, or an out-of-range argument typically throws a P/S alarm referencing the offending block, which is your first clue where the logic broke.
Pro Tip: Run a new macro at a safe Z height with no tool loaded for the first pass, so a sign error in your trig math shows up as an air-cut mistake instead of a crash.
Testing, Debugging, and Portability Across Machines
Before trusting a macro to run unattended, confirm the control actually supports Custom Macro B. The two practical checks are looking for a MAC VAR soft key on the display and running a short MDI test program that assigns and reads back a variable without throwing an alarm.
- Dry-run, then single block: step through the macro one block at a time before letting it run at full feed.
- Variable watches: use the MAC VAR screen to confirm values match your hand calculations at each checkpoint.
- Manual entry tests: assign test values to # variables through MDI to confirm a subprogram behaves correctly before it's called from a full program.
- Portability rules: prefer G10 for offset writes when a program moves between machines, and avoid hard-coded system-variable numbers that may map to different functions on a different control model.
AND/OR support in conditional statements is one of the most frequent portability gaps between older and newer FANUC models, so testing that logic on each control before production use is worth the few extra minutes it takes.
How Machining Calculators Speed Up Macro B Development
Most Macro B errors trace back to bad numeric inputs, not bad syntax. Running feeds and speeds, chip thinning, or bolt circle math through a dedicated calculator before it goes into a macro catches unit mistakes and out-of-range values before they reach the control.
- Feeds and speeds and chip-thinning calculators give you vetted numeric inputs to drop straight into a macro's feed or speed variables, rather than hand-calculating radial engagement under time pressure.
- A G-code analysis tool, such as our G-Code Wizard, lets you preview how variable substitutions resolve and flag syntax issues before the program ever touches the machine.
- An AI assistant can help translate a shop formula into correctly bracketed Macro B syntax, cutting down on the transcription errors that creep in when converting a handwritten formula into code.
Pro Tip: Validate your calculated values in a standalone calculator first; a macro that compiles without alarms can still cut the wrong geometry if the input math was wrong going in.
Error Handling and Recovery Techniques
A macro that fails silently is more dangerous than one that throws an alarm, so building in deliberate checks matters as much as the core calculation logic. The most common technique is range validation on incoming arguments: an IF [#1 LE 0] THEN block at the top of a subprogram can catch a zero or negative value before it reaches a motion command and trigger a controlled stop instead of a crash.
Alarm messages written into the macro itself, rather than relying on generic FANUC system alarms, save significant troubleshooting time. A custom message tied to a failed condition, such as "ARGUMENT B OUT OF RANGE," tells the operator exactly what to fix instead of leaving them to decode a numbered system alarm.
Recovery logic should also account for interrupted cycles. If a macro counts parts for a scheduled check and the program gets stopped mid-cycle, the counter variable needs a safe way to reset or resume without double-counting or skipping a check. Storing the counter in a common variable, rather than a local one, means the value survives a program stop and a reload, which keeps the check-every-N-parts logic accurate even after an unplanned interruption.
Finally, test error paths deliberately. It's easy to test the success case of a macro and never run the failure case at all, which means the first time an out-of-range argument actually occurs is on the shop floor rather than during development.

Organizing Macro B Code for Readability and Reuse
Macro code that makes sense while you're writing it often becomes unreadable six months later, especially once common and system variables are mixed in. A short comment block at the top of each macro, listing what every local and common variable represents, turns a cryptic string of numbers into something the next programmer can follow without reverse-engineering the logic.
Consistent variable numbering across macros pays off as a library grows. If #600 always means "part counter" and #601 always means "target count" across every macro in a shop, programmers stop guessing what a given number does in an unfamiliar program.
A few habits keep a macro library maintainable over time:
- Version and date each macro in a comment line, so it's clear which revision is running on the machine versus which one is archived.
- Separate calculation blocks from motion blocks visually, with blank lines or comments, so the logic and the physical moves are easy to distinguish at a glance.
- Store a master copy off the control, since a macro edited directly at the machine can drift from the version everyone else is using.
Reusability comes from designing macros around arguments rather than hard-coded values from the start. A macro written once for a specific part, then generalized with G65 arguments later, usually needs more rework than one designed as a parametric tool from day one.
Security Considerations When Using Macro B
Macro B gives a program direct access to variables that control offsets, alarms, and in some cases machine parameters, which means a poorly checked macro can alter settings the operator never intended to touch. Restricting write access to system variables above #1000, except where a macro genuinely needs to read or set an offset, limits the blast radius of a coding mistake.
Shop floor access control matters as much as the code itself. Programs that write to common variables shared across jobs should be reviewed before release, since a macro edited casually at the control can unintentionally change behavior in every other program that reads the same common variable range.
Backup and version control reduce risk further. Keeping an unedited master copy of every macro off the machine means a bad edit made directly at the control, whether accidental or unauthorized, can be reverted without reconstructing the logic from memory. Treating macro files with the same backup discipline as CAM post-processors or tool offset tables is a reasonable baseline for any shop running more than a handful of parametric programs.
Integrating Macro B With Standard Cycles and Offsets
Macro B is rarely used in isolation. Most practical macros wrap around or feed into standard FANUC canned cycles, such as drilling, tapping, or bolt-circle cycles, by calculating the positions or parameters those cycles need rather than replacing the cycles themselves.
A macro that calculates a bolt-circle pattern, for example, typically computes the X and Y coordinates in a loop and then calls a standard G81 or G84 cycle at each calculated position, combining the parametric math with a cycle FANUC already optimized for that motion type.
Offsets integrate through two routes: writing with G10, which updates a work or tool offset in a portable way that behaves consistently across machines, or reading a system variable directly when a macro needs the current offset value to calculate a derived position. The general recommendation is to use G10 for writes and reserve direct system-variable access for reads, since offset-related system-variable numbers are a common source of portability problems between control models.
Tool length and diameter offsets also feed macros that need to compensate for a specific tool's geometry, such as a macro calculating a stepover pattern based on the active tool's diameter stored in the offset table rather than a hard-coded value in the program.

Performance and Optimization Tips
Macro B calculations run on the control's processor in real time, and heavy math inside a motion loop can introduce measurable delays on older controls, especially when trig functions or nested conditionals execute on every single pass of a loop.
The most effective optimization is moving calculations out of the loop wherever possible. Precomputing values before the machining sequence starts, rather than recalculating the same trig function inside every pass, reduces the load on the control during actual cutting motion.
A few other habits help:
- Avoid redundant recalculation: if a value does not change between passes, calculate it once and store it in a variable rather than recomputing it every loop iteration.
- Minimize nested IF statements inside loops: flatten logic where possible, since deeply nested conditionals evaluated on every pass add up on long-running programs.
- Use common variables sparingly in tight loops: system overhead for reading and writing certain variable ranges can differ from local variables, so local variables are generally the faster choice inside a performance-sensitive loop.
None of these changes affect the finished part, only how smoothly the control executes the program, which matters most on older hardware or very long cycle times where every millisecond in the loop adds up.
Practitioner Perspective: When Macro B Earns Its Keep
Macro B pays off once you're running repeated similar parts or many parametric variations, not on a true one-off job. The investment is in discipline: version your macros, comment every variable, and train operators to recognize macro-driven prompts rather than treating them as a generic alarm. When a shop's real need is high-mix CAM output rather than shop-floor math, investing in better CAM post-processing is often a better use of time than building a macro library from scratch.
— Availzye
Build Macro B Programs Faster With Availzye Machinist Pro
We built Availzye Machinist Pro to pair the math behind a macro with the shop management around it, so feeds and speeds, chip thinning, and G-code validation live in one place instead of scattered spreadsheets and paper notes.

Our G-Code Wizard previews variable substitutions before a macro ever touches the machine, and our calculators hand you the numeric inputs a macro needs without a separate spreadsheet. Start a 7-day free trial and see how it fits your shop.
FAQ
What is macro programming?
Macro programming is a method of writing CNC programs with variables, expressions, and logic instead of fixed numeric values, so one program can handle multiple part variations. On FANUC controls, Custom Macro B is the specific implementation that adds this capability to standard G-code.
Is CNC coding hard?
Writing basic G-code is straightforward once you know the common commands, but macro programming adds a learning curve around variables, loops, and conditionals. Practitioners generally find that the syntax itself is simple and the real challenge is learning to think in terms of calculations and logic rather than fixed moves.
Can AI write a CNC program?
An AI assistant can help translate a known formula or logic pattern into correctly formatted Macro B syntax, which reduces transcription errors when converting shop math into code. It is best used as a drafting aid alongside a programmer's own validation, not as a replacement for testing and dry-running the result on the actual control.
Which software is best for VMC programming?
The right tool depends on whether you need CAM toolpath generation, shop math calculators, or program validation, since these are different jobs. For validating macro logic and feeds and speeds inputs before they reach the machine, our Individual plan at $9.99 CAD per month includes calculators and a G-code analysis tool built for that step of the workflow.
How do I tell if my machine supports Custom Macro B?
The quickest check is looking for a MAC VAR soft key on the control's display, which indicates macro variable support. A second method is running a short MDI test program that assigns and reads back a variable value, confirming support if it executes without an alarm.
