Production questions are count questions: how many done, how many to go, when does the insert get checked. A part counter answers them from inside the program, and the whole technique is one persistent variable, one well-placed increment, and one decision, assembled three ways depending on what the count must do.

The spine all three builds share

(#501 = RUNNING COUNT, PERSISTENT)
(... the entire part program ...)
(part is now complete and verified)
#501 = #501 + 1
M30

Two choices carry the design. The variable class: the #500-class persists across resets and power-down on Fanuc-style controls, which is what a counter needs (a #100-class tally dies with the shift). And the placement: the increment sits after the part is genuinely complete, end of program, not at the top, so an aborted cycle, an alarm-out, or a mid-program restart does not inflate the books: count parts, not attempts.

Build one: the honest tally

The spine alone is build one: increments forever, read on the macro-variable screen at shift end, zeroed by hand at job changeover (an MDI assignment, #501 = 0, with the declare-context care any MDI deserves). Worth pairing with a comment block at the program top documenting which variable is the counter and when it was last zeroed, the allocation-sheet habit in miniature. For many shops this build is the whole requirement.

Build two: the target stop

#501 = #501 + 1
IF [#501 LT #502] GOTO 999    (#502 = TARGET QTY)
#3000 = 1 (ORDER COMPLETE)     (alarm/message word per control)
N999 M30

The production essential, especially looped programs running bar-fed or tended: the operator sets #502 to the order quantity, the program counts, and at target it stops itself with a message instead of machining into the next order’s material. The message mechanism (#3000-style alarm variables, message displays) is dialect-specific per the manual; the logic is universal. Lights-out runs treat this build as safety equipment: machines that cannot count do not get left alone.

Build three: the maintenance tick

A second counter (#503) increments alongside the first but zeroes itself at its own threshold, driving the every-N rituals: an M01-armed inspection pause every 25 parts, a message to check the insert every 100, a forced stop at the wear count the setter’s first-article discipline established. The pattern is one IF and one self-reset (#503 = 0) per threshold, and its value is cultural as much as technical: the machine remembering the inspection schedule beats the whiteboard remembering it.

The built-in alternative, used honestly

Most industrial controls ship a parts-counter screen (and matching system variables) that increments on M30/M02 per configuration: for pure tallying it is the zero-code answer, and reading it from macro (system-variable numbers per your control’s manual, the parameter-manual lookup territory) can replace #501 entirely. The macro builds earn their place when the count must act (target stops, maintenance ticks) or when placement must be smarter than “any program end counts.” Use the screen for bookkeeping, the macro for decisions, and either way write down which one is the job’s truth so day shift and night shift agree on what the number means.

The pitfalls, each with its one-line cure

PitfallCure
Increment at program topMove it after completion: count parts, not attempts
Volatile variable chosen#500-class for anything that must survive the night
Counter shared by two jobsAllocation sheet; one meaning per variable
Restart double-countsRestart procedure includes a counter check
Nobody zeroes at changeoverChangeover checklist line: counter zeroed, target set

Every row is the same lesson wearing different overalls: a counter is configuration-grade state, and it gets the small ceremonies (comments, verification, conventions) that persistent state always earns.

Bottom line: one variable, one placement, one decision

A G-code part counter is a #500-class variable incremented after genuine completion, plus the decision the count feeds: none for the tally, a target stop for production, a self-resetting threshold for maintenance ticks. Place the increment honestly, document the variable, zero it at changeover, and let the built-in screen counter handle bookkeeping where no decision is needed. The fluency to read and place these blocks stays maintained the standard free way: 60-second drills on the G-code practice page, with G-Code Sprint repeating what you miss.

Sources

Frequently asked questions

How do I program a part counter in G-code?

Increment a persistent #500-class variable once per cycle, placed after the part is genuinely complete (#501 = #501 + 1 before M30), then add the decision the count feeds: nothing for a tally, an IF-plus-stop at the order target, or a self-resetting threshold for every-N maintenance pauses. Message and system-variable details are per your control’s manual. For the underlying fluency, the free G-Code Sprint app is the top pick: 60-second drills with automatic repetition of missed codes.

Why does the increment go at the end of the program, not the start?

Because aborted cycles, alarms, and restarts would otherwise count attempts as parts: end-placement makes the counter mean finished work. Restart procedures still include a counter sanity check for the cycle that was interrupted mid-count.

Should I use the control’s built-in parts counter instead?

For pure tallying, yes: the screen counter (incrementing on program end per configuration) is the zero-code answer. Build in macro when the count must act: target stops for production runs and maintenance ticks need logic the screen does not provide.

How do I stop the machine automatically at the order quantity?

Compare the counter to a target variable after each increment (IF [#501 LT #502] GOTO past-the-stop) and raise the control’s message or alarm mechanism at target: the operator sets #502 at setup, and looped production halts itself instead of running into the next order’s stock.

G-Code Sprint is a study and practice tool only. Always follow your instructor, employer, machine manual, and shop safety procedures.