The Machine Daily
CNC Programming & G-Code

Using CNC Machine Code to Automate Preventive Maintenance Schedules

Learn how to use CNC machine code and Macro B variables to automate preventive maintenance schedules and prevent costly spindle failures.

Published Robert Caldwell

The Hidden Cost of Ignoring Maintenance Intervals

In modern manufacturing environments, a missed preventive maintenance (PM) interval rarely results in immediate failure. Instead, it accelerates wear on critical components like spindle bearings, way lube systems, and coolant pumps. By the time a spindle seizes or a ballscrew loses preload, the damage is done. In 2026, replacing a high-speed 12,000 RPM direct-drive spindle on a standard VMC costs between $12,000 and $18,000, with lead times often stretching past four weeks. The resulting unplanned downtime easily exceeds $250 per hour in lost production.

Relying on whiteboards, paper logbooks, or even external CMMS (Computerized Maintenance Management Software) to track machine usage introduces human error. Operators forget to log shifts; maintenance techs misread hour meters. The most robust solution is to embed the maintenance schedule directly into the controller using CNC machine code. By leveraging custom macro programming (Macro B), shops can force the machine to track its own usage and trigger un-ignorable alarms when service is due.

⚠️ CRITICAL WARNING: Volatile vs. Non-Volatile Memory
A common and costly mistake in macro-based maintenance tracking is using volatile variables (e.g., #100 to #149). These variables reset to zero every time the machine loses power. If you track spindle hours in a volatile variable, a weekend power outage will erase your maintenance data. Always use non-volatile variables (typically #500 to #599 on Fanuc and Haas controls) to ensure data persists through power cycles.

Architecting the Maintenance Lockout Macro

To automate maintenance tracking, we must write a custom macro that increments a counter every time a part cycle completes, compares that counter against a predefined service threshold, and triggers a system alarm if the threshold is exceeded. This requires integrating standard G-code logic with system variables.

Step 1: Define the Non-Volatile Counter

We will use variable #500 to store our accumulated cycle count for a specific PM task (e.g., checking the way lube distributor unit). We will use #501 to store the target threshold (e.g., 5,000 cycles).

Step 2: Write the Macro Logic

Create a new program in the controller memory, designated as O9010. On most controls, programs in the O9000 range are protected from accidental editing and do not appear in the standard program directory list, keeping them safe from operator deletion.


O9010 (WAY LUBE PM TRACKING MACRO)
#500 = #500 + 1 (INCREMENT CYCLE COUNTER BY 1)
IF [#500 LT #501] GOTO 100 (IF COUNT IS LESS THAN THRESHOLD, SKIP ALARM)
#3000 = 1 (TRIGGER CUSTOM ALARM: WAY LUBE SERVICE OVERDUE)
N100
M99 (RETURN TO CALLING PROGRAM)

In this code block, #3000 is a special system variable. Assigning any value to #3000 immediately halts the machine and displays the assigned value as a custom alarm message on the screen. The machine will enter an alarm state and refuse to cycle start until the alarm is cleared and the variable is reset.

Step 3: Automate the Macro Call via M-Code

Calling O9010 manually at the end of every program is impractical. Instead, we map an unused M-code to trigger the macro automatically. On Fanuc controls, parameters 6071 through 6079 are used to assign M-codes to programs O9001 through O9009.

For O9010, we use the parameter block for custom M-codes (often parameter 6081 for O9010, depending on the exact control generation). By setting Parameter 6081 to 30, typing M30 in your standard G-code program will automatically execute the maintenance check macro before the program resets. (Note: Do not use M30 if it conflicts with your standard 'End of Program/Reset' command; choose an unused code like M58 and map it accordingly).

System Variables for Advanced Time-Based Tracking

Cycle counts are useful for consumable tooling and filters, but time-based metrics are superior for mechanical wear components like spindle bearings and coolant pumps. Modern CNC controllers maintain internal system variables that track exact runtimes.

System Variable Description Typical Use Case Control Compatibility
#3021 Total Cutting Time (Minutes) Insert wear tracking, tool life management Fanuc, Haas, Mitsubishi
#3025 Spindle Run Time (Minutes) Spindle bearing grease intervals, chiller service Fanuc, Haas
#3026 Power ON Time (Minutes) Control cabinet fan filter replacement, battery checks Fanuc, Haas
#500-#599 Non-Volatile User Variables Storing PM thresholds and accumulated custom counters Universal Macro B

By reading #3025 inside your O9010 macro, you can compare the actual spindle run-time against a 500-hour grease interval, completely eliminating the guesswork of manual hour-meter logging. For a deeper dive into mapping these variables, CNC Cookbook's Macro Programming Guide provides excellent controller-specific syntax references.

💡 PRO TIP: The 'Soft' Warning vs. 'Hard' Lockout
Locking out a machine (#3000 = 1) during a critical production run can cause supply chain bottlenecks. Instead, use variable #3006 to generate an operator message that does not halt the machine. Program the macro to issue a #3006 warning at 90% of the maintenance threshold, and reserve the hard #3000 lockout for 105% of the threshold. This gives the shop floor manager a 10% buffer to schedule the PM during a natural shift change.

The Service Technician Reset Procedure

A maintenance macro is only effective if it can be securely reset once the physical service is completed. If the reset process is too complex, technicians will bypass it; if it is too simple, operators will clear it without doing the work.

Executing the MDI Reset

When the maintenance technician completes the PM (e.g., replacing the way lube reservoir and bleeding the lines), they must reset the #500 counter. This is done via the MDI (Manual Data Input) screen:

  1. Switch the control to MDI mode.
  2. Unlock the parameter write switch (Key switch or software toggle).
  3. Type #500 = 0 (or #500 = #3025 if using spindle hours as a rolling baseline).
  4. Press CYCLE START or INSERT to execute the assignment.
  5. Clear the custom alarm by pressing RESET.

Securing the Variables from Operator Overrides

To prevent machine operators from clearing the #500 variable to keep the machine running, you must lock the non-volatile variables. On Haas controls, this is managed via Setting 34 (Macro Variables) or by utilizing the 'Lock' settings in the macro directory. On Fanuc controls, Parameter 3202 (Bit 0 and Bit 1) can be configured to disable editing of programs in the O9000 series and restrict MDI variable assignments to users with the maintenance-level password. Consult your specific machine tool service manual for the exact parameter map, as these security bits vary between the 0i-F and 31i-B control generations.

Integrating Probing Cycles for Automated Verification

Taking automation a step further, advanced shops use CNC machine code not just to track time, but to physically verify machine condition during scheduled downtime. By embedding a Renishaw or Blum probing routine into a 'Weekend PM' macro, the machine can automatically check X and Y axis backlash.

The macro commands the spindle to probe a fixed internal reference sphere. If the measured diameter deviates by more than 0.0005 inches from the baseline stored in #510, the macro flags a ballscrew wear alarm. This transitions the maintenance schedule from purely time-based (preventive) to condition-based (predictive), ensuring you only replace expensive mechanical components when actual geometric degradation occurs.

Embedding maintenance logic directly into your CNC machine code transforms the controller from a simple motion device into an active participant in your facility's asset management strategy. By utilizing non-volatile memory, system runtime variables, and secure reset protocols, you eliminate human error, protect high-value spindles, and ensure that preventive maintenance happens exactly when the machine needs it.