Fanuc System Variables

Fanuc system variables (the #-numbers) are how a custom macro reads and writes the control’s internal state — tool offsets, work offsets, live axis positions, probe results, modal codes, timers, and alarms. A part program treats them like any other variable: read one into a general-purpose variable, do arithmetic, and (where the variable is writable) assign a new value back. This is the mechanism behind every probing routine, tool-breakage check, and adaptive macro on a Fanuc control.

How the Numbering Is Organized

The number itself tells you what family a variable belongs to. Once you know the map, an unfamiliar #-number stops being a lookup exercise:

RangeFamily
#1#33Local variables & macro call arguments
#100#999Common (general-purpose) variables
#2001#2800, #10001#13999Tool offsets
#3000#3902Alarms, timers, control switches, counters
#4001#4130Modal information (active G-codes and addresses)
#5001#5108Positions (previous block, machine, work, skip, deviation)
#5201#5328, #7001#7948Work offsets (external, G54–G59, G54.1 P1–P48)

Complete Reference

The R/W column is the part most tables leave out — it tells you whether a macro can assign to the variable (R/W or W) or only read it (R). Writing to a read-only variable raises an alarm.

VariableUsageR/W
Macro Arguments & General Purpose
#0Null (vacant) variable — always empty; assignment is not allowedR
#1#33Local variables / macro call arguments — a fresh level per macro call (unpassed arguments are null; the caller’s values are restored at M99; initialized to null at power-off)R/W
#100#199Common variables, cleared at power-off. Probing software (e.g. Renishaw Inspection Plus) reserves part of this range for measurement outputs when installedR/W
#500#999Common variables, retained through power-off. Probe calibration data conventionally lives at the bottom of this range when probing is installedR/W
Tool Offsets — 5-digit numbers (offsets 1–999, every memory type)
#10001#10999Length wear, H-code (base + offset number). On memory type A this is the single combined offset value; on type B, wear (B makes no H/D distinction)R/W
#11001#11999Length geometry, H-code (base + offset number); on memory type B, geometryR/W
#12001#12999Radius wear, D-code (memory type C only)R/W
#13001#13999Radius geometry, D-code (memory type C only)R/W
Tool Offsets — legacy #2xxx aliases (first 200 offsets only)
#2001#2200Alias of #10001+ — memory type A: the offset value; type B/C: length (H) wear by defaultR/W
#2201#2400Alias of #11001+ — length (H) geometry by defaultR/W
#2401#2600, #2601#2800Radius (D) geometry / wear aliases — exist only in FS15-style numbering (bit 3 V15 of parameter 6000 = 1, plus bit 5 D15 of parameter 6004 on 30i); by default D offsets have no #2xxx aliasR/W
System & Control
#3000Programmable alarm: #3000 = 1 (MESSAGE) stops the program and displays the messageW
#3001Millisecond timer (counts while power is on; presettable)R/W
#3002Hour timer (counts while the cycle-start lamp is on)R/W
#3003Suppress single block / M-function wait (bit-coded)R/W
#3004Disable feed hold / feedrate override / exact stop (bit-coded, cleared on reset)R/W
#3006Programmable stop with message: #3006 = 1 (MESSAGE)W
#3007Mirror-image status per axis (bit-coded)R
#3011Current date, YYYYMMDDR
#3012Current time, HHMMSSR
#3901Machined parts countR/W
#3902Required parts countR/W
Modal Information (state of the last buffered block)
#4001G-code group 01, motion: 0=G00, 1=G01, 2=G02, 3=G03R
#4002G-code group 02, plane: 17=G17, 18=G18, 19=G19R
#4003G-code group 03: 90=G90 absolute, 91=G91 incrementalR
#4005G-code group 05, feed mode: 94=G94, 95=G95R
#4006G-code group 06, units: 20=G20 inch, 21=G21 metricR
#4007G-code group 07, cutter comp: 40=G40, 41=G41, 42=G42R
#4008G-code group 08, length comp: 43=G43, 44=G44, 49=G49R
#4010G-code group 10, canned-cycle return: 98=G98, 99=G99R
#4014G-code group 14, work coordinate system: 54=G54 … 59=G59R
#4001#4030All other modal G-code groups follow the same pattern (group NN → #40NN); groups run to 22 on 16i/18i and 0i, to 30 on 30iR
#4102Modal B codeR
#4107Modal D code (active radius offset number)R
#4109Modal F code (active feedrate)R
#4111Modal H code (active length offset number)R
#4113Modal M codeR
#4114Current sequence (N) numberR
#4115Current program (O) numberR
#4119Modal S code (active spindle speed)R
#4120Modal T code (active tool number)R
#4130Modal P code (active G54.1 additional WCS number)R
Position Data (axis order X, Y, Z, 4th… within each block)
#5001#5008Previous block end position (programmed endpoint, work coordinates)R
#5021#5028Present position, machine coordinates (read with axes stopped)R
#5041#5048Present position, work coordinates (read with axes stopped)R
#5061#5068Skip position — where the probe tripped during G31, in work coordinates (if the skip input never trips, these hold the block’s programmed end point)R
#5081#5088Tool length compensation currently appliedR
#5101#5108Servo position deviation (following error)R
Work Offsets
#5201#5208External work offset (EXT / common shift applied to every coordinate system)R/W
#5221#5228G54 work offsets (X, Y, Z, 4th…)R/W
#5241#5248G55 work offsetsR/W
#5261#5268G56 work offsetsR/W
#5281#5288G57 work offsetsR/W
#5301#5308G58 work offsetsR/W
#5321#5328G59 work offsetsR/W
Additional Work Offsets
#7001#7008G54.1 P1 additional work offsetsR/W
#7021#7028G54.1 P2 additional work offsets (each P adds 20 to the base)R/W
#7941#7948G54.1 P48 additional work offsetsR/W

Generation Notes

The table above uses the classic 8-axis numbering of the 16i/18i era, which most shop-floor references assume. Where the manuals genuinely differ by control family:

Topic0i-B16i/18i-B30i/31i/32i
Common variables#100–#199, #500–#999 standard#100–#149, #500–#531 base; #150–#199 / #532–#999 optional100-variable (#100–#149, #500–#549) or 600-variable (#100–#199, #500–#999) option; B Plus adds a retained #98000–#98499 tier
Axes per position / offset block4 (#5001–#5004 … G54.1 P48 = #7941–#7944)8 (#5001–#5008, work offsets #5201–#5328)20 (#5001–#5020; skip = #5061–#5080; G54 = #5221–#5240), plus a #100001+ range for up to 50 axes
Modal groups#4001–#4022#4001–#4030, plus #4201–#4330 (block executing right now) and #4401–#4530 (block interrupted by an interrupt-type macro)
G54.1 setsP1–P48 at #7001+; P1–P300 at #14001+ with the 300-set optionSame numbering; #4330 additionally reports the P number of the executing block
#3000 alarmn = 0–200, message ≤ 26 characters, displays as 3000+nn = 0–4095 when bit 1 (MCA) of parameter 6008 is set (displays as MCnnnn); message up to 60 characters on B Plus
Value range / precision±1047, roughly 8 significant digitsIEEE double precision (≈ ±10308) unless bit 0 (F16) of parameter 6008 selects the legacy format

One 16i/0i-era wrinkle: #5201–#5328 (and the even older per-axis aliases #2500–#2806) require the workpiece-coordinate-system option on those controls. The #2500-block work-offset aliases were dropped from the 30i numbering — don’t confuse them with the #2001-block tool offsets.

Read-Only vs Read/Write at a Glance

The rule of thumb: variables that report machine state (positions, modal codes, clock, mirror status) are read-only; variables that hold setup data (offsets, common variables, counters, timers) are writable. Getting this wrong is the classic source of “why won’t it write?” confusion — e.g. #5041 (where the axis is) cannot be assigned, but #5221 (where G54 points) can.

Read-only (report state)Read/write (you can assign to them)
Positions #5001–#5108 (previous-block end, machine, work, skip, tool comp, servo deviation)Common variables #100–#199, #500–#999
Modal codes #4001–#4130 (active G/M/T/S/F/H/D and program state)Tool offsets #2001–#2800, #10001–#13999
Clock #3011/#3012, mirror status #3007, null #0Work offsets #5201–#5328, additional #7001–#7948
Timers #3001/#3002, part counts #3901/#3902, alarm/stop #3000/#3006 (write-only)

Named System Variables (30i / 0i-F / Plus)

On the 30i family, every system variable in the tables above also has a name. The format is [#_NAME] for scalars and [#_NAME[i]] for indexed families — the whole reference, # included, sits inside square brackets. A name begins with an underscore followed by up to seven uppercase letters, numerics, or underscores, and the subscript can be any expression, with a non-integer result rounded off ([#_ABSIO[1.4999999]] reads #5001; [#_ABSIO[1.5]] reads #5002). Names have been there since the first 30i (Model A), and they beat raw numbers on two counts: they read like what they are, and they survive numbering changes — [#_WZG54[3]] is G54’s third axis whether the control maps it at #5223 or at #100353 in the 50-axis range, and the tool-offset names follow the wear/geometry meaning even when the V15 parameter bit swaps which #2xxx range holds which. The control also polices them: a misspelled or unregistered name raises alarm PS1098 (“NO VARIABLE NAME”), and an invalid subscript raises PS1099.

The curated table below covers the names a mill macro actually reaches for; the full list in the B-64724EN manual runs to well over a hundred.

NameNumber equivalentIndexR/WMeaning
Work Offsets (index n = axis number, 1–20 / 1–50)
#_WZCMN[n]#5201#5220; #100301#100350n = axisR/WExternal workpiece origin offset (applied to all coordinate systems)
#_WZG54[n]#5221#5240; #100351#100400n = axisR/WG54 workpiece origin offset
#_WZG55[n]#5241#5260; #100401#100450n = axisR/WG55 workpiece origin offset
#_WZG56[n]#5261#5280; #100451#100500n = axisR/WG56 workpiece origin offset
#_WZG57[n]#5281#5300; #100501#100550n = axisR/WG57 workpiece origin offset
#_WZG58[n]#5301#5320; #100551#100600n = axisR/WG58 workpiece origin offset
#_WZG59[n]#5321#5340; #100601#100650n = axisR/WG59 workpiece origin offset
#_WZP1[n]#_WZP48[n] (to #_WZP300 with the 300-set option)#7001#7960 (20 per set); #14001#20000 (P1–P300); #101001#116000 (50-axis)n = axis; the G54.1 P number is encoded in the nameR/WG54.1 Pk additional workpiece origin offset — [#_WZP17[3]] is G54.1 P17, 3rd axis
Tool Offsets (index n = compensation number, 1–200 / 1–999) — ranges shown for V15 = 0; V15 = 1 swaps the wear/geometry numbers, the names always follow the meaning
#_OFSHW[n]#2001#2200, #10001#10999n = offset numberR/WH-code length wear (memory C)
#_OFSHG[n]#2201#2400, #11001#11999n = offset numberR/WH-code length geometry (memory C)
#_OFSDW[n]#12001#12999n = offset numberR/WD-code radius wear (memory C)
#_OFSDG[n]#13001#13999n = offset numberR/WD-code radius geometry (memory C)
#_OFS[n]#2001#2200; #10001#10999n = offset numberR/WThe single combined offset value (memory A)
#_OFSW[n]#2001#2200, #10001#10999n = offset numberR/WOffset wear (memory B)
#_OFSG[n]#2201#2400, #11001#11999n = offset numberR/WOffset geometry (memory B)
Positions (index n = axis number, 1–20 / 1–50)
#_ABSIO[n]#5001#5020; #100001#100050n = axisREnd point position of the previous block (work coordinates)
#_ABSMT[n]#5021#5040; #100051#100100n = axisRCurrent position (machine coordinates)
#_ABSOT[n]#5041#5060; #100101#100150n = axisRCurrent position (work coordinates)
#_ABSKP[n]#5061#5080; #100151#100200n = axisRSkip position — where G31 tripped (work coordinates)
Interface Signals (index is 0-origin, unlike everything above)
#_UI[n]#1000#1031; #1036#1067n = bit, 0-origin (n = 0–31 → UI000–UI031; n = 32–63 → UI400–UI431)RInterface input signal, one bit
#_UO[n]#1100#1131; #1136#1167n = bit, 0-originR/WInterface output signal, one bit
#_UIL[n]#1032#1035; #1068#1071n = 32-bit word, 0-origin (0 = UI000–UI031, 1 = UI100–UI131, …)RInterface input signals, 32 points at a time
#_UOL[n]#1132#1135; #1168#1171n = 32-bit word, 0-originR/WInterface output signals, 32 points at a time
Clock & Date
#_CLOCK1#3001R/WClock 1 (milliseconds)
#_CLOCK2#3002R/WClock 2 (hours)
#_DATE#3011RYear/Month/Date
#_TIME#3012RHour/Minute/Second
Alarm & Message
#_ALM#3000WMacro alarm
#_MSGSTP#3006WStop with a message
System Constants
#_EMPTY#0, #3100RNull (the vacant value)
#_PI#3101RCircular constant π = 3.14159265358979323846
#_E#3102RBase of natural logarithm e = 2.71828182845904523536
Execution Control — per-bit names (no numeric per-bit equivalent exists)
#_M_SBK / #_M_FINbits 0 / 1 of #3003R/WEnable/disable suppression of single block stop / waiting for the auxiliary function completion signal
#_M_FHD / #_M_OV / #_M_ESTbits 0 / 1 / 2 of #3004R/WEnable/disable feed hold / feedrate override / exact stop check
Modal Information
#_BUFG[n]#4001#4030n = G-code group numberRModal G code of the last buffered block
#_ACTG[n]#4201#4230n = G-code group numberRModal G code of the block currently being executed
#_BUFF / #_BUFS / #_BUFT / #_BUFM#4109 / #4119 / #4120 / #4113RModal F / S / T / M of the last buffered block; the #_ACT… forms (#4309 / #4319 / #4320 / #4313) report the executing block

Side by side, the number form and the name form of the same reads and the same probe write (this is the “touch off and set zero” pattern worked in full in the next section — Z is axis 3, so [#_WZG54[3]] is #5223 and [#_ABSKP[3]] is #5063):

(READ G54 Z - NUMBER FORM, THEN NAMED FORM)
#101 = #5223
#101 = [#_WZG54[3]]                          (INDEX 3 = Z, THE 3RD AXIS)

(PROBE TOUCH-OFF WRITE, NAMED FORM)
G90 G31 Z-25. F50.                           (FEED DOWN UNTIL THE PROBE TRIPS)
[#_WZG54[3]] = [#_WZG54[3]] + [#_ABSKP[3]]   (SHIFT G54 Z BY THE SKIP Z)
G00 Z25.                                     (RETRACT)

Because the subscript takes any expression, the indirect-addressing tricks later in this article carry straight over — [#_ABSKP[#500*2]] is legal. The lathe-side names (#_OFSXW, #_OFSZG, #_WKSFTX and kin) are mapped in the Fanuc Turning System Variables article.

Reading & Writing System Variables in a Macro

Read the current work coordinate and motion mode, then decode them:

#100 = #4001   (active motion mode: 0=G00, 1=G01, 2=G02, 3=G03)
#101 = #4014   (active work coordinate: 54-59)
#102 = #5041   (current X in the work coordinate system)
#103 = #5021   (current X in machine coordinates)

Probe a surface and write the result to a work offset. This is the core “touch off and set zero” pattern: feed down with G31 until the probe trips, then shift the G54 Z offset (#5223) so the touched face becomes Z0 in that work coordinate system. (#5061–#5068 hold the skip position in work coordinates; the axis order is X, Y, Z…, so Z is #5063.)

(TOUCH TOP OF PART, SET IT AS G54 Z0)
G90 G31 Z-25. F50.        (feed down until the probe trips)
#5223 = #5223 + #5063     (shift G54 Z so the touched face = Z0)
G00 Z25.                  (retract)

Measure a tool on a tool setter and write its length offset. The same skip mechanism, but the write target is a tool geometry offset, addressed indirectly so one macro serves every tool. #500 holds the calibrated trigger height of the setter (a retained common variable, set once during calibration):

(MEASURE TOOL LENGTH ON A TOOL SETTER)
#1 = 5                      (tool / H number being measured)
G91 G31 Z-400. F200.        (first touch, fast)
G01 Z2.                     (back off)
G31 Z-4. F30.               (second touch, slow, for repeatability)
#[11000 + #1] = #5063 - #500  (geometry offset = skip Z minus setter height)
G91 G28 Z0.                 (home Z)

Indirect addressing also works on the read side — here, checking the geometry length offset for whatever H-code is currently active:

#104 = #[11000 + #4111]   (geometry length offset for the active H number)
IF [#104 GT 6.0] GOTO 10  (branch if the tool is unexpectedly long)

Gotchas Worth Knowing

  • Look-ahead buffering. The control reads blocks ahead of the one executing. A macro block that reads position or modal state can be evaluated before the preceding motion finishes — and a block already in the buffer keeps the old value of a work offset you just wrote. Where the read/write must be synchronized with motion, force the buffer to drain first (a G04 dwell or a G53 positioning block are the common idioms).
  • Read positions with the axes stopped. The manuals mark #5021–#5028 and #5041–#5048 as “read operation during movement: disabled” — because of the buffering (pre-read) function, a value read mid-move is not guaranteed to be the expected one. The exception is the skip block: #5061–#5068 are latched at the instant the G31 input trips, which is exactly why probing macros read those instead of #5041.
  • Tool offset numbering depends on the memory type — and one parameter bit. The five-digit #10001+ blocks are the safe choice: they exist on every memory type and cover offsets 1–999. The four-digit #2001+ numbers are aliases for the first 200 offsets only, and what they mean shifts with memory type (on type A, #2001 is the whole offset; on B/C it is the wear register by default). On top of that, bit 3 (V15) of parameter 6000 swaps the wear/geometry assignment across the whole map to match FS15 conventions — and some builders ship it set. Write a known value from MDI and read it back before trusting hard-coded numbers.
  • The null variable #0 is not zero. An unset (vacant) variable equals #0, and IF [#7 EQ #0] (is it vacant?) behaves differently from IF [#7 EQ 0] (is it zero?). A vacant variable used in arithmetic is treated as 0, which silently masks a missing macro argument — test against #0 when an argument is optional.
  • #3000 stops the program; #3006 pauses it. Use #3000 = n (TEXT) for a hard fault (operator must reset) and #3006 = 1 (TEXT) for a planned operator interaction (cycle start continues).

Try these in the Macro Playground — pick the Fanuc control, type a macro, set the system-variable inputs (like #5063), and watch the values update live as it runs.

The Macro Playground with the Fanuc control selected: the system-variable reference sidebar on the left mirrors this article's tables, and the Inputs panel supplies values for machine-input variables like #5221

The playground’s variable sidebar is built from this reference — read-but-never-written variables (like the #5221 G54 origin here) automatically become machine inputs you can set.

See also: Reading & Writing System Variables for the same probe-to-offset chain on every control, Modal & Position Data for the #4001/#5001 families in depth, Tool Offset Variables for offset-memory details, and Custom G/M Cycles for packaging these reads and writes into a reusable cycle.

References

  • FANUC, Series 30i/31i/32i-MODEL B Plus Operator’s Manual (Common to Lathe System / Machining Center System), B-64724EN/01, Ch. 16 “Custom Macro”.
  • FANUC, Series 30i/31i/32i-MODEL A User’s Manual (Common to Lathe System / Machining Center System), B-63944EN/03, Ch. 16 “Custom Macro”.
  • FANUC, Series 16i/18i/160i/180i-MODEL B Operator’s Manual (Machining Center), B-63534EN/02, Ch. 15 “Custom Macro”.
  • FANUC, Series 0i-MODEL B Operator’s Manual (Machining Center), B-63844EN/02, Ch. 15 “Custom Macro”.
  • Peter Smid, Fanuc CNC Custom Macros, Industrial Press, 2004.

Have a question or want to contribute?

Contact us with corrections, additions, or topics you'd like covered.

Get in Touch