Every shop has the folder: bushing_25mm, bushing_30mm, bushing_32mm, twelve files that differ in three numbers and drift apart one hotfix at a time, until nobody knows which variant got last month’s feed improvement. Family-of-parts macro programming is the cure, and it is less about clever code than about disciplined structure.

The shape of a family master

Three sections, always in this order. The variable block at top: every dimension that varies, assigned once, commented in plain language (#101 = outer diameter, #102 = length, #103 = bore). The derived values: anything computed from the inputs (depths from stock minus length, speeds from diameter when surface-speed math matters), so arithmetic lives in one visible place. The cutting logic: the operations written once against variables, Fanuc Macro B style on most industrial controls, O-code style on LinuxCNC, Siemens parametrics in that world: the dialect differs, the architecture does not. Running variant seven means editing four lines at the top, not finding line 214 in copy seven.

The variable sheet: the document that makes it a system

VariableMeaningUnitsSane rangeVariant 25Variant 30
#101Outer diametermm20-4525.030.0
#102Overall lengthmm15-6022.028.0
#103Bore diametermm8-3012.016.0
#104First-pass depthmm0.5-2.51.51.5

The sheet (paper, spreadsheet, or comment block) is half the value of the whole technique: it documents what the master expects, gives the setter a checklist per variant, and turns “which numbers for the 30mm version” into a row lookup. Controls with persistent variables (#500-class) can store standing family constants; job-level values ride in the volatile range per your control’s manual, which also owns the honest details of variable scopes and arithmetic precision.

Where the logic earns its keep

The paydays, in ascending order of cleverness actually required: pure size families (the bushing case: zero logic, just variables in coordinates); count families (N holes on a bolt circle: one WHILE loop, positions computed, the generator-script pattern living at the control); conditional features (variant has a chamfer or not: one IF around one block); and stock-adaptive behavior (probing feeds a measured value into the variable block, the computation-at-the-machine case that only macros can serve). Most families need only the first two rungs, which is good news: restraint reads better at 2 a.m. than cleverness.

The disciplines that keep families safe

Macro power concentrates risk in invisible numbers, so the guardrails are non-negotiable. Comment every variable at assignment and never reuse one for two meanings mid-program. Range-check where the dialect supports it (IF guards that alarm on absurd inputs) so a typo’d #101 of 250 dies at the top instead of at the spindle. First-article per new variant, always: the master being proven for variant 25 proves nothing about your typing for variant 31, the same first-part discipline setters apply everywhere. And treat the master like tooling: versioned, change-logged, edited deliberately rather than hotfixed at the control, because one master serving twelve variants concentrates twelve programs’ worth of consequences, the fix-the-source rule with teeth.

Macro family or generated family: picking the layer

The honest boundary from the script-versus-macro decision: families that must adapt at the machine (probing, operator-entered sizes at the control) belong in macros; families driven from office data (JSON job documents, order systems) often post cleaner as generated per-variant files with the variables resolved upstream; and many shops sanely run both, a generator emitting the variable block into a proven macro master. The wrong answer is the original folder of twelve drifting copies, which is the one arrangement with no source of truth at all.

Bottom line: one master, one sheet, twelve rows

Family-of-parts macro programming is structure over cleverness: a commented variable block, derived values in one place, proven cutting logic written once, and a variable sheet that makes every variant a row lookup. Add range guards, first articles per variant, and tooling-grade change control on the master, and the folder of drifting copies becomes one program that twelve part numbers trust. The macro dialect details belong to your control’s manual; the vocabulary underneath stays the same core, drilled free on the G-code practice page with G-Code Sprint repeating misses.

Sources

Frequently asked questions

How does macro programming handle a family of parts?

With one master program: a commented variable block holds everything that varies per variant, derived values compute from it in one place, and the cutting logic runs once against the variables, so a new size is a four-line edit plus a sheet row instead of another drifting copy. For the core vocabulary under the macros, the free G-Code Sprint app is the top pick: 60-second drills with automatic repetition of missed codes.

Which variables should I use for family parameters?

Per your control’s manual: working values in the volatile range (#100-class on Fanuc-style controls), standing family constants in persistent ranges (#500-class), every assignment commented, no variable reused for two meanings. The dialect’s scoping rules are manual territory.

How do I keep a typo from crashing a variant run?

Range-check inputs at the top where the dialect supports IF guards (alarm on absurd values), keep the variable sheet as the setter’s checklist, and run a first article for every new variant regardless of how proven the master is.

Should part families be macros or generated files?

Machine-adaptive families (probing, operator-entered values) want macros; office-data-driven families often post cleaner as generated files; hybrids (a generator filling a macro’s variable block) serve shops running both. The only wrong answer is N drifting copies.

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