Machsupport Forum

MachPro => MachPro General Discussion => Topic started by: cd_edwards on May 17, 2026, 11:15:20 AM

Title: RC ATC Dustboot
Post by: cd_edwards on May 17, 2026, 11:15:20 AM
I have MachPro setup with a Rapidchange ATC. I need to drop a dustboot into a dock and then pick it up after the tool length setter has finished. I've written a couple of functions todo this for me, however I'm not sure the best place to call these. Currently I have them setup as macro's (m2222/m2223). I had also made it into a loadable lua module where I could call the functions as well.

Where is the best place to do this?
Is there a hook into the tool change cycle I can use?
One suggestion was todo this in my post processor, but that could be an issue.
Also, accessing registers. It would be nice to have a register with the current status of the dust shoe. This would make it more secure. Maybe even a register to ignore the dust boot pickupfor special cases. Press a button, toggle a register to ignore.
Title: Re: RC ATC Dustboot
Post by: paul.stephens on May 20, 2026, 12:49:21 PM
I believe we currently have dust shoe/cover logic built into the core now and can be setup through settings.
Example image of setup:
https://prnt.sc/1oNqaz78JPfj (https://prnt.sc/1oNqaz78JPfj)

I believe the logic is called for every tool change regardless if the settings are defined or not.
Alternatively, we have built in Mcodes for dust cover, m112 dust cover open and m113 for dust cover closed.

We do have additional hooks for open dust cover and close dust cover. We have Pre open logic and post open logic as well as Pre close and post closed logic.
These functions will still be used for the m112 and m113 Mcodes.

Code: [Select]
function UserMCodeModule.TC_PreOpenDustCover()
------------------ Add user code below this line ------------------

------------------ Don't Edit below this line -----------------------
return nil, true, w.FunctionCompleted()
end
function UserMCodeModule.TC_PostOpenDustCover()
------------------ Add user code below this line ------------------

------------------ Don't Edit below this line -----------------------
return nil, true, w.FunctionCompleted()
end
function UserMCodeModule.TC_PreCloseDustCover()
------------------ Add user code below this line ------------------

------------------ Don't Edit below this line -----------------------
return nil, true, w.FunctionCompleted()
end
function UserMCodeModule.TC_PostCloseDustCover()
------------------ Add user code below this line ------------------

------------------ Don't Edit below this line -----------------------
return nil, true, w.FunctionCompleted()
end

In short, if you just need I/O to fire and a delay, just use the settings. This will handle your logic on tool changes automagically. If you need to ever manually fire your Dust cover, you can use m112 and m113. If you need custom pre and post logic applied, you will need to use the functions provided above. This method will ensure that everything works well together. These functions will be called in the UserMCodeModule.

In terms of Tool Change hooks... We have over 500 different hooks that can be called. Could I get a little more of a description of what you're trying to accomplish?

If you want to ignore the Dust cover operation in special cases, you can modify the setting that applies the logic.
https://prnt.sc/AW2WiikpoSyF (https://prnt.sc/AW2WiikpoSyF)
Use the example code below to modify it.

w.SetOEMParamValueString(RegName, val, inst)

Code: [Select]
local inst = mc.mcGetInstance("Function Name")
w.SetOEMParamValueString("AutoToolChangerDCBehavior", "Do Nothing", inst) -- Turns Dust cover behavior to do nothing when function is called.
w.SetOEMParamValueString("AutoToolChangerDCBehavior", "Open", inst) -- Turns Dust cover behavior to Open when function is called.
w.SetOEMParamValueString("AutoToolChangerDCBehavior", "Open-Return To Prev State", inst) -- Turns Dust cover behavior to do Open, and then return to the previous state when finished, when function is called.
w.SetOEMParamValueString("AutoToolChangerDCBehavior", "Open-Close", inst) -- Turns Dust cover behavior to Open and then later close, when function is called.

You can use this same logic for running a Tool Setter as well.
Code: [Select]
w.SetOEMParamValueString("AutoToolSetterDCBehavior", "Do Nothing", inst)

Set this logic to apply on a dashboard button when selected. You can also use w.GetOEMParamValueString(RegName, inst   ) to check its current state.
Title: Re: RC ATC Dustboot
Post by: cd_edwards on May 20, 2026, 12:54:33 PM

-- Dustshoe Entry Settings
local inst = mc.mcGetInstance()

local DustBootX = 45.85   
local DustBootY = 36.4
local DustBootZ = -4.3513
local DustBootRateY = 100
local DustBootRateZ = 50
local DustBootYSlide = 5   
local DustBootSafeZ = -0.1

--  ============================================================ PICKUP DUST SHOE ==========================================================================   
   
function m2223()
   local toolnum, rc = mc.mcToolGetCurrent(inst)
    if (toolnum == 0 or rc ~= 0) then
      do return end
   end
   
   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ)                                       ------ Z UP
   mc.mcCntlGcodeExecuteWait(inst, GCode)                                       ------ Z UP
   
   GCode =  string.format("G00 G90 G53 X%.4f Y%.4f\n", DustBootX, DustBootY-DustBootYSlide)                                  ------ To DustShoe Entry X
   mc.mcCntlGcodeExecuteWait(inst, GCode)
   
   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootZ+0.75)                                 ------ G00 Quick down to 20mm above DustShoe Pick Up
   mc.mcCntlGcodeExecuteWait(inst, GCode)
   
   GCode = string.format("G00 G90 G53 Z%.4f F%.4f\n", DustBootZ,DustBootRateZ/2)                     ------ DustShoe Pick Up
   mc.mcCntlGcodeExecuteWait(inst, GCode)
            
   GCode = string.format("G00 G90 G53 Y%.4f F%.4f\n", DustBootY,DustBootRateY)      ------ DustShoe SlideOutY
   mc.mcCntlGcodeExecuteWait(inst, GCode)

   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ)                                                             ------ PICK UP Z --- DROP SHOE IN HOLDER --
   mc.mcCntlGcodeExecuteWait(inst, GCode)
end   

I need to move to a specific location in XYZ,  then slide forward 5 inches and finally raise Z up to remove my dust boot. To pick it up, I need to go to a specific XYZ, drop Z down ontop of the boot, and slide backwards. It's magnetically attached to the spindle shoe and can not be on the spindle when doing a tool change. is it hicky? maybe, but it's what I've got on my home built machine.

 
Title: Re: RC ATC Dustboot
Post by: paul.stephens on May 22, 2026, 01:06:11 PM
To keep your M codes consistent between your machines, you can keep this MCode. If you want to only run it when a Dust Cover Routine is called. Set your settings to tool changer settings, and have tool changer dust cover behavior set to Open - Close. Then run these two hook scripts.
UserMCodeModule.TC_PreOpenDustCover()
UserMCodeModule.TC_PreCloseDustCover()

This will run your routine before and after every tool change. This also will affect the Dust Cover dashboard routine as well. I believe the standard routine is running M112 as the Mcode deep down. So if you're not overwriting M112, the hooks should work as intended.

Example:

Code: [Select]
function UserMCodeModule.TC_PreCloseDustCover()


 -- Dustshoe Entry Settings
    local inst = mc.mcGetInstance()

    local DustBootX = 45.85   
    local DustBootY = 36.4
    local DustBootZ = -4.3513
    local DustBootRateY = 100
    local DustBootRateZ = 50
    local DustBootYSlide = 5   
    local DustBootSafeZ = -0.1

--  ============================================================ PICKUP DUST SHOE ==========================================================================   
   local toolnum, rc = mc.mcToolGetCurrent(inst)
    if (toolnum == 0 or rc ~= 0) then
      do return end
   end

   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ)                                       ------ Z UP
   mc.mcCntlGcodeExecuteWait(inst, GCode)                                       ------ Z UP

   GCode =  string.format("G00 G90 G53 X%.4f Y%.4f\n", DustBootX, DustBootY-DustBootYSlide)                                  ------ To DustShoe Entry X
   mc.mcCntlGcodeExecuteWait(inst, GCode)

   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootZ+0.75)                                 ------ G00 Quick down to 20mm above DustShoe Pick Up
   mc.mcCntlGcodeExecuteWait(inst, GCode)

   GCode = string.format("G00 G90 G53 Z%.4f F%.4f\n", DustBootZ,DustBootRateZ/2)                     ------ DustShoe Pick Up
   mc.mcCntlGcodeExecuteWait(inst, GCode)

   GCode = string.format("G00 G90 G53 Y%.4f F%.4f\n", DustBootY,DustBootRateY)      ------ DustShoe SlideOutY
   mc.mcCntlGcodeExecuteWait(inst, GCode)

   GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ)                                                             ------ PICK UP Z --- DROP SHOE IN HOLDER --
   mc.mcCntlGcodeExecuteWait(inst, GCode)
end   


This should auto run the routine before the official "Close Dust cover" which means after your Tool Change, it will run this routine Next automatically.
Title: Re: RC ATC Dustboot
Post by: cd_edwards on May 25, 2026, 09:20:24 AM
I spent the weekend attempting to get this working in my UserMCodeModule.mcs   it doesn't seem to matter what I set the tool dust cover settings to, this code will not run via invoking M6. It will run with M112/M113

Code: [Select]
function UserMCodeModule.TC_PreOpenDustCover()
------------------ Add user code below this line ------------------
-- Two persistant registers are needed. One tracks location of the dust boot (docked/undocked), the other set's an ignore flag.

local inst = mc.mcGetInstance()
local DustBootX = 45.79
local DustBootY = 36.4
local DustBootZ = -4.443
local DustBootRateY = 75
local DustBootRateZ = 100
local DustBootYSlide = 5
local DustBootSafeZ = -0.1


local hreg = mc.mcRegGetHandle(inst,"iRegs0/DustBoot/ignoreDustBoot")
local ignore = mc.mcRegGetValue(hreg)
local hreg = mc.mcRegGetHandle(inst,"iRegs0/DustBoot/DustBootStatus")
local val = mc.mcRegGetValue(hreg)

if (ignore == 1) then
mc.mcCntlSetLastError(inst, "Dust boot ignore")
do return nil, false, w.FunctionCompleted()end
end

if val == 0 then
mc.mcCntlSetLastError(inst, "Dust boot already dropped")
return nil, true, w.FunctionCompleted()
end
-- =========================================================== drop dust boot =============================================================================

GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ) ------ Z Up
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode =  string.format("G00 G90 G53 X%.4f Y%.4f\n", DustBootX, DustBootY) ------ TO DUSTSHOE ENTRY Y
mc.mcCntlGcodeExecuteWait(inst, GCode)

-- We need to make sure that we don't wipe out the dust boot dock when moving both x/y
GCode =  string.format("G00 G90 G53 Z%.4f\n", DustBootZ) ------ TO DUSTSHOE ENTRY
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G0 G90 G53 Y%.4f F%.4f\n", DustBootY - DustBootYSlide,DustBootRateY) ------ MOVE Y INTO DUSTSHOE HOLDER
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ) ------ PICK UP Z --- DROP SHOE IN HOLDER --
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode =  string.format("G00 G90 G53 Y%.4f \n", DustBootY) ------ MOVE TO SAFE Y
-- mc.mcCntlGcodeExecuteWait(inst, GCode)
mc.mcRegSetValue(hreg, 0)
return nil, true, w.FunctionCompleted()

end

function UserMCodeModule.TC_PreCloseDustCover()
------------------ Add user code below this line ------------------

local inst = mc.mcGetInstance()

local DustBootX = 45.79
local DustBootY = 36.4
local DustBootZ = -4.3513
local DustBootRateY = 100
local DustBootRateZ = 50
local DustBootYSlide = 5
local DustBootSafeZ = -0.1

local hreg = mc.mcRegGetHandle(inst,"iRegs0/DustBoot/ignoreDustBoot")
local ignore = mc.mcRegGetValue(hreg)
local hreg = mc.mcRegGetHandle(inst,"iRegs0/DustBoot/DustBootStatus")
local val = mc.mcRegGetValue(hreg)

if (ignore == 1) then
mc.mcCntlSetLastError(inst, "Dust boot ignore")
do return nil, false, w.FunctionCompleted()end
end
--  ============================================================ PICKUP DUST SHOE ==========================================================================
local toolnum, rc = mc.mcToolGetCurrent(inst)
    if (toolnum == 0 or rc ~= 0 or val == 1) then
mc.mcCntlSetLastError(inst, "Dust boot already picked up")
do return nil, false, w.FunctionCompleted()end
end

GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ) ------ Z UP
mc.mcCntlGcodeExecuteWait(inst, GCode) ------ Z UP

GCode =  string.format("G00 G90 G53 X%.4f Y%.4f\n", DustBootX, DustBootY-DustBootYSlide) ------ To DustShoe Entry X
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootZ+0.75) ------ G00 Quick down to 20mm above DustShoe Pick Up
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G00 G90 G53 Z%.4f F%.4f\n", DustBootZ,DustBootRateZ/2) ------ DustShoe Pick Up
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G00 G90 G53 Y%.4f F%.4f\n", DustBootY,DustBootRateY) ------ DustShoe SlideOutY
mc.mcCntlGcodeExecuteWait(inst, GCode)

GCode = string.format("G00 G90 G53 Z%.4f\n", DustBootSafeZ) ------ PICK UP Z --- DROP SHOE IN HOLDER --
mc.mcCntlGcodeExecuteWait(inst, GCode)
mc.mcRegSetValue(hreg, 1)

------------------ Don't Edit below this line -----------------------

return nil, true, w.FunctionCompleted()
end