A few weeks ago, I made a wooden plate using my mill machine and decided to time how long it would take to mill the whole plate. I found out that I spent 25 minutes out of 67 doing material Z measurement (zero) and Tool Z adjustement after each tool change (I want a toolchanger!)
I realized that a few thing that I could do to streamline operations (and prevent small tool breakage) would be :
- Automated material height sensing (Z). must work with both conductive and non-conductive materials.
- Automated tool length measurement before and after a tool change in order to automatically adjust the current Z position
- 3 axis touch sensor (I already have it, just need to make connection easy to do)
I decided that the biggest time saving would be #2 – Automated tool length compensation so here were go!
Requirements :
- Based on electric contact between tool and a touch plate (all my tools are metallic / conductive)
- Spring loaded touch plate – the probing should prevent any pressure on the plate but I wanted to make sure there was some ‘give’ to ensure no breakage of small tools (ex : 1/32 end mill)
- Use either Mach4 tools table lengths or a ‘safe’ length if no length is provided for the tool
- Fully automated motion from current position to touch plate and then return to original position (with adjusted Z leading to the tip of the tool being to the exact same height as the previous tool
- Watch for any crash when moving Z down in order to prevent tool breakage and graciously handle unexpected contact
- Able to be built at home (using mill / lathe / 3D printer) and available material
- Low-cost
- Positioned where it is un-obstructive as possible but easy to access (we don’t want to waste precious work-area space!)
Here’s the finished sensor installed and wired on the temporary MDF bed. I used an aluminum touch plate for now, I plan to turn a steel one and hardened it in the future
Mach4 M6 macro (tool change)
I then proceeded to write a custom M6 macro in mach4 (m6.msc)
–V0.1 – Feb 17 – Initial code – move + probing
–V0.2 – Feb 18 – Added probestart and no tool length code
–v0.3 – Feb 21 – Added machine state push + homed axis check
–v0.3 – Mar 03 – Removed machine state push and use #var instead
–v0.4 – Mar 04 – Added toolChangeZ, saving / restoring feed + force ui refresh of G-Code modals
–TODO : Probe on all -Z moves
–TODO : Ensure probe did strike
function m6()
local inst = mc.mcGetInstance();
local touchPlateXPos = -0.75; –X position (in machine coord) of the touch plate
local touchPlateYPos = 4.15; –Y position (in machine coord) of the touch plate
local toolChangeZ = -2.5; — abs Z height to move the head for manual tool change by operator
local colletToTouchPos = -5.79; –This is the z position where the end of the spinde is about to touch the sensor, leave about 0.1in clearance
local noToolLen = 1.25; –Length to use if tool lenght = 0 (make sure NO tools can be longer than this);
local probeCode = “G31.1″; –G code of the probe to use
–define motors mapping
local xAxisNb = 0;
local yAxisNb = 1;
local zAxisNb = 2;
–Track original X/Y/Z position
local orgX = mc.mcAxisGetPos(inst,xAxisNb);
local orgY = mc.mcAxisGetPos(inst,yAxisNb);
local orgZ = mc.mcAxisGetPos(inst,zAxisNb);
local requestedTool = mc.mcToolGetSelected(inst);
local currenttool = mc.mcToolGetCurrent(inst);
local currentToolLen = mc.mcToolGetData(inst,mc.MTOOL_MILL_HEIGHT,currenttool);
mc.mcCntlSetLastError(inst,”M6 – Processing tool change from”..currenttool..” to “..requestedTool);
–Ensure a tool change is needed
if requestedTool == currenttool
then
mc.mcCntlSetLastError(inst,”M6 – Current tool and Requested tool are the same, nothing to do”);
return;
end;
–Ensure valid tool length, if not, use default value
if (currentToolLen <= 0.1)
then
currentToolLen = noToolLen;
end
–Keep of copy of the current postion mode, units, feed as we are going to change them
local positionMode = mc.mcCntlGetPoundVar(inst,4003);
local units = mc.mcCntlGetPoundVar(inst,4006);
local feedRate = mc.mcCntlGetPoundVar(inst, 2134);
–Ensure we are fully homed on all axises
local xHomed = mc.mcAxisIsHomed(inst,xAxisNb);
local yHomed = mc.mcAxisIsHomed(inst,yAxisNb);
local zHomed = mc.mcAxisIsHomed(inst,zAxisNb);
if (xHomed == 0 or yHomed == 0 or zHomed == 0)
then
mc.mcCntlSetLastError(inst,”M6 – Tool change : At least one axis is not homed”);
mc.mcCntlEStop(inst);
return;
end
–Compute the z position we need to move the head before probing
local probeStart = colletToTouchPos + currentToolLen;
mc.mcCntlGcodeExecuteWait(inst, “G20 G90 G53 G0 Z0.0”);–Move Z to safe pos
mc.mcCntlGcodeExecuteWait(inst, “G53 G0 X”..touchPlateXPos..” Y”..touchPlateYPos); –Goto x/y of touch pad
–Move Z close the touch pad
–TODO : use probing to stop on contact (safety / prevent tool breakage)
mc.mcCntlGcodeExecuteWait(inst, “G53 G0 Z”..probeStart); — Move to probing pos
–Probe current tool Z pos
mc.mcCntlGcodeExecuteWait(inst,”G91 “..probeCode..” Z-2.0 F10″); –Probe to a max of 2 inches
local didStrike = mc.mcCntlProbeGetStrikeStatus(inst);
–TODO : Ensure probe did touch
local currentToolZ = mc.mcAxisGetPos(inst,2);
local newToolDesc = mc.mcToolGetDesc(inst,requestedTool);
mc.mcCntlGcodeExecuteWait(inst, “G90 G53 G0 Z”..toolChangeZ);–Move Z back to safe pos for tool change
–Prompt user
wx.wxMessageBox(“Please change to tool number “..requestedTool..” (“..newToolDesc..”) and press ENTER to continue”);
–At this point, the tool has been changed, recalc new values
currenttool = requestedTool;
currentToolLen = mc.mcToolGetData(inst,mc.MTOOL_MILL_HEIGHT,currenttool);
if (currentToolLen <= 0.1)
then
currentToolLen = noToolLen;
end
–Calculate new tool probe Z
probeStart = colletToTouchPos + currentToolLen;
–Move Z close the touch pad
–TODO : use probing to stop on contact (safety / prevent tool breakage)
mc.mcCntlGcodeExecuteWait(inst, “G90 G53 G0 Z”..probeStart); — Move to probing pos
mc.mcCntlGcodeExecuteWait(inst,”G91 “..probeCode..” Z-2.0 F10″); –Probe to a max of 1/2 inch
mc.mcAxisSetPos(inst,2,currentToolZ); — Set Z to old tool probed Z
local rc = mc.mcToolSetCurrent(inst,requestedTool); — Change tool
local newlyToolIdx = mc.mcToolGetCurrent(inst);
mc.mcCntlGcodeExecuteWait(inst,”G90 G53 G0 Z0.0″); — Move Z back to abs 0
mc.mcCntlGcodeExecuteWait(inst,”G90 G0 X”..orgX..” Y”..orgY); — Move X/Y back to org
mc.mcCntlGcodeExecuteWait(inst,”G90 G0 Z”..orgZ); — Move Z to org pos
–Restore Position mode, units & feed
mc.mcCntlSetPoundVar(inst,4003,positionMode);
mc.mcCntlSetPoundVar(inst,4006,units);
mc.mcCntlSetPoundVar(inst,2134,feedRate);
— Execute some G code to force modal label UI to refresh
— else, ui and interal settings are out of sync which can cause operator errors
mc.mcCntlGcodeExecuteWait(inst,”G”..units);
end
if (mc.mcInEditor() == 1) then
m6()
end
Thanks for sharing your code.