Fanuc G65 Circle Milling Macro: Troubleshooting O7001

Tom Garrett7 min read
FanucMotion ControlTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Details

A common shop-floor building block is a G65-called circular interpolation macro that bores or finishes a circular pocket from the part center using cutter compensation and three arc moves. The calling program passes clearance plane, absolute depth, nominal diameter and feed as macro arguments; the macro program does the lead-in, one full circle, and a tangential lead-out.

Typical caller and macro body:

O6001 (CALL CIRCLE MILLING)
T1 M6
G0 G54 X0 Y0 M3 S1500
G0 G43 H1 D1 Z50
G65 P7001 R2 Z-6 D30 F500
G0 G53 G49 Z0 M5 M9
M30

O7001 (CIRCLE MILLING)
G0 Z#18
G1 Z#26 F[#9/4]
G91 G41 X[#7/2-0.3] Y0.3 F#9
G3 X-[#7/2-0.3] Y[#7/2-0.3] I-[#7/2-0.3] J0
G3 X0 Y0 I0 J-[#7/2]
G3 X-[#7/2-0.3] Y-[#7/2-0.3] I0 J-[#7/2-0.3]
G1 G40 X[#7/2-0.3] Y-0.3
G0 G90 Z#18
M99

Reported symptoms fall into four buckets: the macro runs but cuts a wildly undersized or oversized circle; the control alarms on cutter compensation at the lead-in block; the tool plunges at rapid or at the wrong Z; or the macro appears to "do nothing" because the arguments never reached the local variables.

Argument-to-Local-Variable Map

G65 argument specification (Type I) maps addresses to local variables at the new nesting level. Every value used inside O7001 must match this table exactly — a mismatch here is the single most frequent cause of a macro that "ignores" its inputs.

Address in G65 block Local variable Meaning in this macro Example value
R #18 Clearance / approach plane (absolute Z) 2.0
Z #26 Final depth, absolute -6.0
D #7 Nominal finished diameter 30.0
F #9 Contour feed (mm/min) 500

Other Type I assignments worth knowing when you extend the macro: A=#1, B=#2, C=#3, I=#4, J=#5, K=#6, E=#8, H=#11, M=#13, Q=#17, S=#19, T=#20, U=#21, V=#22, W=#23, X=#24, Y=#25.

Critical: Arguments are passed only by G65/G66. If the program is called with M98 P7001, the local variables stay null (#0) and every bracketed expression either alarms or evaluates unpredictably. Never substitute M98 for G65 on this macro.

Root Cause Analysis

1. Decimal points in the G65 call

Argument values written without a decimal point are interpreted in the least input increment of that address on many FANUC configurations. On a metric control with 0.001 mm increment, D30 can be read as 0.030 mm and R2 as 0.002 mm — the macro then commands a microscopic circle at a clearance plane essentially at Z0. Always write D30. Z-6. R2. F500. in the call, or confirm the decimal-point (calculator-type) programming setting in your control's parameter manual before relying on integer arguments.

2. Missing plane and modal state

The macro issues G3 with I/J but never commands G17. If the caller or a previous cycle left G18/G19 active, the I/J offsets are meaningless for the active plane and the control alarms or cuts in the wrong plane. Likewise, feed mode is inherited: if G95 (feed per rev) is modal, F500 is 500 mm/rev.

3. Cutter compensation offset number vs. the D argument

The wear/geometry offset used for compensation comes from D1 commanded in O6001 on the G0 G43 H1 D1 Z50 line. Inside the G65 block, D30 is an argument, not an offset selection — it does not change the modal D offset. That behaviour is correct, but it makes the macro silently dependent on the caller. If the caller omits D1, compensation starts with offset 0 and the tool cuts the programmed path centerline, producing a hole oversized by one tool diameter.

4. Geometry constraint on the lead-in

The hard-coded 0.3 mm lead-in stand-off sets the quarter-arc radius to #7/2 - 0.3. Two limits apply:

  • #7/2 - 0.3 must be greater than zero, i.e. nominal diameter > 0.6 mm.
  • Tool radius must be smaller than #7/2, and in practice smaller than the lead-in arc radius, otherwise the compensated path reverses. Typical FANUC responses are the cutter-compensation "no intersection point" alarm (033) or the interference alarm (041).

5. Full-depth plunge

G1 Z#26 F[#9/4] drives straight to final depth in one move at one quarter of contour feed. That requires a center-cutting end mill or a pre-drilled start hole, and it caps depth of cut at whatever the cutter can plunge. There is no Q peck or helical entry in the original.

6. M30 inside the subprogram

An M30 placed after M99 in the macro body is unreachable while the macro is a separate program, but it becomes a program-ending land mine if the two programs are ever merged into one file or if a block is edited above it. Delete it; keep only M99.

Geometry Verification

Trace with D=30 (radius 15), lead-in radius r = 14.7, starting at the part center. All arc blocks are incremental (G91) and CCW.

Block Arc center (from part center) End point Function
G91 G41 X14.7 Y0.3 — (14.7, 0.3) Comp start-up, straight lead-in
G3 X-14.7 Y14.7 I-14.7 J0 (0, 0.3) (0, 15.0) 90° tangential entry arc onto contour
G3 X0 Y0 I0 J-15 (0, 0) (0, 15.0) Full 360° circle, R15
G3 X-14.7 Y-14.7 I0 J-14.7 (0, 0.3) (-14.7, 0.3) 90° tangential exit arc
G1 G40 X14.7 Y-0.3 — (0, 0) Comp cancel, return to center

The math closes: the tool returns exactly to the calling XY position and G0 G90 Z#18 restores absolute mode and the clearance plane. With G41 and M3 the cutter runs climb, and the left-hand offset pushes the tool center inward, so the finished bore equals the programmed D value. Geometry is not the defect — modal state, decimal points and offset handling are.

Hardened Macro

This version adds argument validation, explicit modal setup, a default clearance plane, an optional Q depth increment, and a single variable for the lead-in stand-off.

O7001 (CIRCLE MILLING - INTERNAL FINISH)
(R=#18 CLEARANCE  Z=#26 DEPTH ABS  D=#7 DIA  F=#9 FEED  Q=#17 STEP)
IF [#7 EQ #0] GOTO 90
IF [#26 EQ #0] GOTO 91
IF [#9 EQ #0] GOTO 92
IF [#18 EQ #0] THEN #18 = 2.
IF [#17 EQ #0] THEN #17 = ABS[#26]
#100 = #7 / 2 - 0.3      (LEAD-IN ARC RADIUS)
#101 = #7 / 2            (CONTOUR RADIUS)
IF [#100 LE 0] GOTO 93
G17 G90 G94
G0 Z#18
#102 = #18               (CURRENT Z)
N10 #102 = #102 - #17
IF [#102 LT #26] THEN #102 = #26
G1 Z#102 F[#9/4]
G91 G41 X#100 Y0.3 F#9
G3 X-#100 Y#100  I-#100 J0
G3 X0    Y0     I0     J-#101
G3 X-#100 Y-#100 I0    J-#100
G1 G40 X#100 Y-0.3
G90
IF [#102 GT #26] GOTO 10
G0 G90 Z#18
M99
N90 #3000 = 1 (NO DIAMETER D)
N91 #3000 = 2 (NO DEPTH Z)
N92 #3000 = 3 (NO FEED F)
N93 #3000 = 4 (DIAMETER TOO SMALL)

Call it the same way, with decimal points and an explicit cutter-comp offset:

G0 G54 X0 Y0 M3 S1500
G0 G43 H1 D1 Z50.
G65 P7001 R2. Z-6. D30. F500. Q3.
Program number range: Keep user macros out of ranges your control protects or reserves. Programs 8000–8999 and 9000–9999 are commonly write-protected or vendor-occupied by parameter setting; 7001 is normally free, but verify before loading.

Commissioning Checklist

  1. Load D1 geometry offset with the actual tool radius and confirm the wear offset is zeroed for the first cut.
  2. Run the caller in single block with Z50. raised and dry-run active; watch the macro variable page and confirm #7=30., #26=-6., #18=2., #9=500. after the G65 block executes.
  3. Verify the modal display shows G17 G90 G94 before the first arc and G41 active only between the lead-in and G40.
  4. Confirm the tool returns to the exact call position in X and Y at the end. Any residual offset means a G91/G90 mismatch.
  5. Cut air at Z above stock, then a test bore in scrap; measure and correct diameter with the D1 wear offset only, never by changing the macro's 0.3 mm lead-in constant.
  6. Test the guard rails: call the macro with the D argument omitted and confirm the macro alarm fires instead of a crash.

FAQ

Why do my G65 macro arguments come through as tiny values?

Values passed without a decimal point can be interpreted in the least input increment of the address, so D30 becomes 0.030 mm on a 0.001 mm metric control. Always write D30. Z-6. R2. with decimal points in the G65 block.

Which local variables do R, Z, D and F map to in a G65 call?

Under Type I argument specification, R=#18, Z=#26, D=#7, F=#9. Use exactly these inside the macro body; M98 does not pass arguments at all.

Does the D word in a G65 block change my cutter compensation offset?

No. Inside a G65 block D is an argument only. The active compensation offset stays whatever was commanded earlier, which is why the caller must include D1 on the G43 H1 line.

Why does the control alarm at the cutter-compensation start-up block?

The lead-in arc radius is D/2 - 0.3. If the tool radius approaches or exceeds that value, the compensated path reverses and the control raises a cutter-compensation no-intersection or interference alarm. Use a smaller cutter or add a diameter-versus-radius check in the macro.

Can I add depth stepping to this circular milling macro?

Yes. Pass a Q increment (#17), loop the arc block set with an IF ... GOTO, and clamp the running Z to the commanded #26 depth so the last pass lands exactly on size.

Back to blog