Tool wear monitoring lets a machining shop change cutting tools when they are actually worn instead of after a conservative fixed count. This use case shows how to publish spindle power and vibration per cut over MQTT, build a wear index for every tool, and schedule tool changes from the data before a worn tool produces scrap or breaks.
The Problem with Fixed Tool Life
Most CNC shops manage tool life with a counter: change the insert after a set number of parts or minutes in cut. The number is chosen conservatively, because a broken tool can scrap an expensive part, damage the spindle or the fixture, and stop the machine for much longer than a planned change.
The result is a compromise that is wrong in both directions. When material is soft and conditions are good, tools are discarded with useful life left. When a batch of material is harder, a coolant nozzle is misaligned or an insert has a defect, the tool wears out before the counter expires and the damage happens anyway. Tool wear monitoring replaces the fixed counter, or at least supplements it, with a measurement of how each tool is actually behaving.
Which Signals Reveal Tool Wear
As a cutting edge wears, it rubs more and cuts less cleanly. That shows up in several measurable ways:
| Signal | How it changes with wear | How to get it |
|---|---|---|
| Spindle power or load | Rises gradually for the same operation | CNC controller data (spindle load percent), or a power transducer or CT on the spindle drive supply |
| Feed axis load | Rises as cutting forces grow | CNC controller axis load data |
| Vibration | RMS and high-frequency content rise; chatter may appear | Accelerometer on the spindle housing |
| Acoustic emission | Changes in high-frequency emission from the cutting zone | Dedicated AE sensor, mostly in high-end systems |
| Part quality | Dimensions drift, surface finish degrades | In-process gauging or post-process measurement |
Spindle power is the most practical starting point. Many modern controllers expose spindle load through OPC UA, MTConnect or a vendor interface, and on older machines a power meter on the spindle drive gives the same information without touching the control. Vibration adds sensitivity to chipping and chatter that power alone can miss. The CNC machine monitoring article covers how to get data out of different controllers.
The Key Idea: Compare Like with Like
Raw spindle power means nothing on its own. Roughing a pocket in steel draws far more power than finishing a face in aluminium, regardless of wear. Tool wear monitoring therefore compares each cut with the same operation performed by the same tool when it was fresh.
That requires context in every message:
- Tool ID (pocket number or, better, a tool identifier from the tool management system)
- Operation ID (program and block range, or an operation name)
- Cut counter for the current tool since it was installed
- Features of the cut: mean power while cutting, peak power, energy, vibration RMS
The edge gateway, which reads the controller and sensors, segments the signal into cuts. A simple method is to treat the period when spindle power exceeds an idle threshold during a known operation as the cut, then compute features over that segment only. Air cutting and rapid moves are excluded, which removes most of the noise.
Data Flow and Payload
Each completed cut produces one message:
acme/plant1/machining/cell2/cnc4/tool/cut
{
"ts": "2026-10-16T10:42:18Z",
"tool_id": "T12-EM10-4F",
"operation": "OP20-rough-pocket",
"cut_no": 143,
"duration_s": 38.2,
"power_mean_kw": 4.61,
"power_peak_kw": 6.02,
"energy_kj": 176.1,
"vib_rms_g": 0.84
}
A tool change is a separate event that resets the baseline for that pocket:
{"ts": "2026-10-16T11:05:00Z", "event": "tool_changed", "tool_id": "T12-EM10-4F", "reason": "wear_index"}
Publishing per cut, rather than streaming raw samples, keeps traffic small and makes every message meaningful. If you later need raw waveforms for analysis, capture them locally and publish them only on demand.
Wear Index Service in Python
The service below learns the baseline mean power and vibration over the first five cuts of each new tool and operation, then calculates a wear index for every following cut as the ratio to that baseline. When the smoothed index crosses a warning or change limit, it publishes a recommendation that a dashboard or the operator panel can show. It uses paho-mqtt 2.x against the public test broker.
import json
from collections import defaultdict, deque
import paho.mqtt.client as mqtt
PREFIX = "connectmq/demo/e93f10/cnc4"
BASELINE_CUTS = 5
WARN_INDEX = 1.20 # 20 % above fresh-tool power
CHANGE_INDEX = 1.35 # recommend change
VIB_WEIGHT = 0.3 # share of vibration in the combined index
SMOOTH = 3 # median of last N cuts
baseline = {} # (tool, op) -> (power, vib)
learning = defaultdict(list)
recent = defaultdict(lambda: deque(maxlen=SMOOTH))
status = {}
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(f"{PREFIX}/tool/#", qos=1)
def on_message(client, userdata, msg):
d = json.loads(msg.payload)
if msg.topic.endswith("/event") and d.get("event") == "tool_changed":
for key in [k for k in baseline if k[0] == d["tool_id"]]:
baseline.pop(key)
recent.pop(key, None)
status.pop(key, None)
for key in [k for k in learning if k[0] == d["tool_id"]]:
learning.pop(key)
print("reset", d["tool_id"])
return
if not msg.topic.endswith("/cut"):
return
key = (d["tool_id"], d["operation"])
if key not in baseline:
learning[key].append((d["power_mean_kw"], d["vib_rms_g"]))
if len(learning[key]) >= BASELINE_CUTS:
p = sorted(x[0] for x in learning[key])[BASELINE_CUTS // 2]
v = sorted(x[1] for x in learning[key])[BASELINE_CUTS // 2]
baseline[key] = (p, v)
print("baseline", key, baseline[key])
return
p0, v0 = baseline[key]
index = (1 - VIB_WEIGHT) * d["power_mean_kw"] / p0 + VIB_WEIGHT * d["vib_rms_g"] / v0
recent[key].append(index)
smoothed = sorted(recent[key])[len(recent[key]) // 2]
level = "change" if smoothed >= CHANGE_INDEX else "warn" if smoothed >= WARN_INDEX else "ok"
out = {"tool_id": key[0], "operation": key[1], "cut_no": d["cut_no"],
"wear_index": round(smoothed, 3), "level": level}
client.publish(f"{PREFIX}/tool/{key[0]}/wear", json.dumps(out), qos=1, retain=True)
if level != status.get(key):
status[key] = level
print("STATUS", out)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="tool-wear-e93f10")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
The cut messages go to .../cnc4/tool/cut, change events to .../cnc4/tool/event, and the service writes results to .../cnc4/tool/<tool_id>/wear. Because results are retained, the operator panel always shows the current wear index of every tool, even right after a restart.
Note the median smoothing: a single heavy cut caused by a casting with extra stock should not trigger a change. A sudden jump that persists across several cuts, on the other hand, often means a chipped edge and deserves immediate attention. Many shops add a separate rule for that case: if the index jumps sharply between two consecutive cuts, raise an alert regardless of the smoothed value.
Tuning the Limits
The values above are starting points, not universal constants. Tune them per tool family:
- Run with monitoring only. Keep the existing fixed tool life and just record the wear index for a few weeks.
- Inspect worn tools. When tools come out, measure flank wear or rate their condition, and note the index at removal.
- Correlate. Find the index level at which tools reach your acceptable wear limit, and set the change limit slightly below it.
- Extend carefully. Once the index reliably predicts condition, allow tools that are still healthy to run beyond the old fixed count, in small steps.
- Keep a hard cap. Leave a generous maximum count in place as a safety net in case a sensor or the gateway fails.
What the Shop Gains
When tool changes are driven by condition, tools that run in easy conditions are used longer, tools that wear fast are pulled before they break, and the tool crib can plan purchases from real consumption. Wear data per tool also feeds reliability work: tool-related stops become visible in your MTBF and MTTR calculation, and abnormal wear rates point to process problems such as coolant issues or material variation. Combining the wear index with vibration monitoring sensor data on the spindle bearings separates tool problems from machine problems.
Infrastructure Notes
- Edge segmentation keeps the broker load small: one message per cut instead of thousands of samples per second.
- QoS 1 for cut and tool-change messages ensures the service never misses a reset.
- ISA-95 topics such as
acme/plant1/machining/cell2/cnc4/...let the ConnectMQ portal group machines by area and cell in its devices view. - Private broker for production. The public demo is readable by everyone. Use credentials from the portal and TLS on port 8883.
A cloud MQTT broker lets the same data reach the shop floor panel, the tool crib and a process engineer working remotely without opening inbound ports into the machine network. For the broader architecture, see the smart manufacturing guide.
Connect Your CNC Machines to ConnectMQ
ConnectMQ is a fully managed MQTT broker with MQTT 5, TLS, retained messages, a live topic explorer and threshold alerts in the portal. Create a broker on the free Serverless plan at app.connectmq.com, no credit card required, and start recording wear data from your first machine.
Frequently Asked Questions
What is the best signal for tool wear monitoring?
Spindle power or load is the most practical starting signal because many controllers already provide it. Adding spindle vibration improves detection of chipping and chatter.
Can tool wear monitoring replace fixed tool life completely?
It can extend or shorten tool life based on condition, but most shops keep a generous maximum count as a safety net in case sensors or data collection fail.
Why compare each cut with a fresh-tool baseline?
Power depends heavily on the operation, material and tool. Comparing the same tool and operation with its own fresh state isolates the change caused by wear.
How much data does this send over MQTT?
Only one small message per cut plus tool-change events. Raw high-frequency signals stay at the edge unless you explicitly need them.



