If you’ve got an older machine that doesn’t have macros or a probe and you need to detect broken tools, here’s how to do it.

The Basic Idea

Mount a limit switch to your table and save its position as a work offset. Wire that switch to one of your M21–25 relays and to the M-Fin pin. Whenever you want to check for a broken tool, have your program call a subprogram that rapids over to the switch, presses it in, and fires an M21, which will cause the machine to wait for the M-Fin signal. If the switch is pressed in, it will immediately see the signal and go on its merry way. If the tool is broken, it will keep waiting until you come along to fix it. That’s the overview. Here are the details:

The Switch

You’ll need a normally open limit switch with an IP67 rating so you can spray it with coolant. I used this one from Automation Direct. I machined a block to mount it to the table and bolted it in the far corner.

The position at which a tool will press the switch is saved as a work offset so you can send the tool to X0 Y0 Z0.

To set the switch up, save the point at which the button closes the contacts as a work offset so you can bring a tool to X-Zero Y-Zero Z-Zero to touch off. This switch repeats to .002" supposedly but I set the Z-Zero to .005" below the switch close point just to be safe.

To route the wires in a way the machine won’t eat them, I used these handy magnet hooks stuck to the inside of the enclosure(I might try running them through a carabiner clipped to the eye bolt to make it easier to run new cables or modify the setup):

Wiring the Switch

Speaking of wires, this was the scary part for me since prior to this I’d never hooked up any wires to the Haas control. My machine has an M-Function port that I think is used for Haas indexers. It uses a 4-pin DIN connector but I didn’t have one of those laying around so I opened up the cabinet and cut those wires (easy enough to reconnect later if I want to). Here’s what the wiring looks like before you bugger it all up:

The wiring as Haas intended it.

And here’s what it should look like after you wire up the switch:

The wiring as hacks like us intended it. If you need the M-Function port you can wire it up to retain this functionality. You’d just use another M-relay for the broken tool switch. It’s okay for multiple sources to fire the M-Fin signal.

The Code

So once you have everything wired up, you’ll need to tell the machine to do your breakage-detection bidding. This involves three parts:

Your subprogram Your part program Your post processor

Your Subprogram

O02030 (Tool Breakage Detection)

G53 G0 Z0. (retract Z to safe level)

G129 (set Tool probe Work Offset)

M5 (make sure spindle is stopped)

M9 (turn off coolant)

G0 X0. Y0. (go to switch)

G0 Z.25 (rapid close to switch)

M8 (turn on coolant to blast chips away)

G1 Z0. F10. (slowly press switch)

M9 (turn off coolant)

M21 (waits for M-Fin signal)

G53 G0 Z0. (retract Z to safe level)

M99 (back to part program)

%

Your Part Program

Whenever you want to detect a broken tool, you need your gcode to look like the code below. You’re just calling the detection subprogram and then resetting the prior work offset you had before calling the subprogram.

M98 P02030 (Call your subprogram)

G112 (Make sure to reinstitute your prior work offset)

Your Post Processor

I use Fusion 360 for CAM so these instructions are for that. Keep in mind I’m a super-noob at this so take these instructions with a strong warning to do your own due diligence. This works for me but might not work for you.

Fusion 360 lets you turn break control on for specific tools.

I modified the generic Haas post. Here’s what it looked like before I monkeyed with it. This block starts on line 1889 for me:

case COMMAND_BREAK_CONTROL:

if (!toolChecked) { // avoid duplicate COMMAND_BREAK_CONTROL

onCommand(COMMAND_STOP_SPINDLE);

onCommand(COMMAND_COOLANT_OFF);

writeBlock(

gFormat.format(65),

"P" + 9853,

"T" + toolFormat.format(tool.number),

"B" + xyzFormat.format(0),

"H" + xyzFormat.format(properties.toolBreakageTolerance)

);

toolChecked = true;

}

And here’s what I changed it to:

case COMMAND_BREAK_CONTROL:

if (!toolChecked) { // avoid duplicate COMMAND_BREAK_CONTROL

onCommand(COMMAND_STOP_SPINDLE);

onCommand(COMMAND_COOLANT_OFF);

writeBlock(mFormat.format(98), "P" + "02030");

if (currentWorkOffset < 6) {writeBlock(gFormat.format(53 + currentWorkOffset));

} else {

{writeBlock(gFormat.format(103 + currentWorkOffset));

}

}

toolChecked = true;

}

Some explanation: This just inserts the subprogram call where the tool check should go, then follows that up with the current work offset. My machine likes G54-G59 and G110-G129 so the if-statements are just looking for the WCS offsets from Fusion 360 and outputting the correct range. If you use the G154 offsets you’ll want to rewrite that portion.

In Conclusion

So that’s it. If you’ve got any ideas for how to improve this let me know. This won’t work on my face mill since it only detects at the center point but you could probably build some logic into the subprogram to offset X-Zero Y-Zero for certain tools. Good luck.