Machsupport Forum
Mach Discussion => Mach4 General Discussion => Topic started by: KDRusty72 on August 08, 2023, 06:06:03 PM
-
Does anyone know why a custom m5 will work fine in MDI but not in a GCode file or mc.mcCntlGCodeExecuteWait?
It will hang and do nothing if I use it in a GCode. I can't seem to figure it out—most of the time I have to restart CNC and Mach4 to get it working correctly again.
I needed a custom m5 to start a timer when the spindle is turned off.
Does anyone see anything wrong with the code below? I copied most of the code from another m5. Doesn't seem to many examples of m5 macros to go by.
-- Custom M5 to record last Spindle Stop time for ATC
-- Need to make sure spindle is completely stopped before
-- performing tool change
--
function m5()
local inst = mc.mcGetInstance()
mc.mcCntlSetLastError(inst, "m5: Turning off spindle")
dir = mc.mcSpindleGetDirection(inst)
if dir ~= mc.MC_SPINDLE_OFF then
mc.mcSpindleSetDirection(inst, mc.MC_SPINDLE_OFF)
--save the time the spindle is turned off
hreg = mc.mcRegGetHandle(inst, "iRegs0/lastSpindleStopTime")
mc.mcRegSetValue(hreg, os.time())
end
end
--testing
if (mc.mcInEditor() == 1) then
m5()
end
-
Sorry, I made a mistake in the original posts. I meant to say the m5 works perfectly in MDI and GCode file but not when it is in another macro.
Example, my m6 and m30 both use a mc.mcCntlGcodeExecuteWait with an m5 and both will hang at the m5. Prior to making my own m5, both the m6 and m30 worked fine with the m5 in them. I think the problem is with my custom m5 macro.
Kenny
-
I just can't seem to figure this one out. I cannot get to work when calling an m5 from within another macro (ie. m30, m6, etc.). It works absolutely fine when the m5 is in a GCode or MDI.
If I am in MDI, and enter a
s18000 m3
g04 p5.00
m5
It works and the spindle shuts off.
but...
s18000 m3
g04 p5.00
m30
doesn't work. The spindle won't shut off and mach4 becomes useless. I have to restart the ESS and reboot to get mach4 to work again.
I even tried stripping the m5 macro so the only thing it does is mc.mcCntlSetLastError(inst, "m5: Turning of spindle"). Same thing...shows the message if m5 is entered in MDI, but not when called from inside another macro (ie. m30).
BTW, if I delete the custom m5 macro and use the built-in one, everything works as it should.
Does anyone know what might be going on?
-
I am sure you have already done this but first thing to check is make sure that your m5 macro is in the macros directory and uses lowercase file name. m5.mcs and make sure you don't have another macro with a function m5() defined in that same directory.
https://www.machsupport.com/forum/index.php?topic=33831.msg235284#msg235284
I would also make your dir variable local.
HTH
RT
-
m5 macro is in the correct directory and used all lowercase in the file name and in the .mcs file.
Work fine in GCode or MDI when calling the m5 directly. Just doesn't work when called from within another macro (ie. m6 or m30) using the mc.mcCntlGCodeExecuteWait. That is why I'm confused. If I delete the custom m5 and use the built-in m5, it works fine.
-
instead of mc.mcCntlGCodeExecuteWait try mc.mcCntlGCodeExecute
i found that some places one did not work well for me either.
-
I thought about testing it by replacing the mc.mcCntlGCodeExecuteWait to the non-wait(or the mc.mcCntlMdiExecute) version but was concerned about where else it might pop up. The m30 is a stock macro from AVID and is the one place I know it is used beside my own m6 macro. I wasn't sure if there might be another script somewhere else that uses the wait version that I don't know about.
-
Should have checked first but the M30 macro doesn't use the wait version. I added the wait to the GCodeExecute and got the same result.
-
Can you post your m6 and m30 macro?
-
Sure...
m6 - I removed the m5 from it and used a mc.mcSpindleSetDirection(inst, mc.MC_SPINDLE_OFF) to stop the spindle.
function m6()
local inst=mc.mcGetInstance()
mc.mcCntlSetLastError(inst, 'Tool change in progress')
------ Get and compare next and current tools ------
local SelectedTool = mc.mcToolGetSelected(inst)
local CurrentTool = mc.mcToolGetCurrent(inst)
if (SelectedTool == CurrentTool) then
mc.mcCntlSetLastError(inst, "Next tool = Current tool")
mc.mcCntlGcodeExecute(inst, "G43 H"..CurrentTool) --Turn on tool length offset for current tool
do return end
end
mc.mcCntlSetLastError(inst, 'Break 0')
------ Define slide distance and direction ------
------ Only 1 of these should have a non-zero value -----
------ Changing from a positive to negative slide value, or vice-versa, will change the direction that the tool slides into the tool fork -----
local XSlide = 0.00
local YSlide = 2.00
local dwell = 8.00
------- Declare Position Variables ------
local XPos = 0
local YPos = 0
local ZPos = 0
------ For spindles that have a partial tool push out, define the amount of movement here -----
local ZBump = 0.100
------ Define the OUTPUT# for the drawbar signal -----
local DrawBarOut = mc.OSIG_OUTPUT6
------ Define the OUTPUT# for the dusthood signal -----
local DustHood = mc.OSIG_OUTPUT7
------ Get current state ------
local CurFeed = mc.mcCntlGetPoundVar(inst, 2134)
local CurFeedMode = mc.mcCntlGetPoundVar(inst, 4001)
local CurAbsMode = mc.mcCntlGetPoundVar(inst, 4003)
------ Raise Dust Hood if dust hood is down ------
local dhsig = mc.mcSignalGetHandle(inst, DustHood)
local dhstate = mc.mcSignalGetState(dhsig)
if (dhstate == 0) then
mc.mcSignalSetState(dhsig, 1)
end
------ Check to if spindle is on, if on, turn off spindle -------
dir = mc.mcSpindleGetDirection(inst)
if dir ~= mc.MC_SPINDLE_OFF then
mc.mcSpindleSetDirection(inst, mc.MC_SPINDLE_OFF)
mc.mcCntlSetLastError(inst, "Turn off spindle")
hreg = mc.mcRegGetHandle(inst, "iRegs0/lastSpindleStopTime")
mc.mcRegSetValue(hreg, os.time())
end
------ Check when was last turned off and pause to allow time for spindle to stop ------
local hreg = mc.mcRegGetHandle(inst, "iRegs0/lastSpindleStopTime")
local SpindleStopTime = mc.mcRegGetValue(hreg)
local currentClockTime = os.time()
local secondsSinceSpindleStop = currentClockTime - SpindleStopTime
if secondsSinceSpindleStop > 0 then
dwell = dwell - secondsSinceSpindleStop
end
if dwell > 0 then
local GCode = ""
GCode = GCode .. string.format("G04 P%.4f", dwell)
mc.mcCntlGcodeExecuteWait(inst, GCode)
--mc.mcCntlSetLastError(inst, string.format("Wait for spindle to stop. Dwell time: %.0", dwell)
end
------ Move to current tool change position ------
local tool = CurrentTool
--You will need to enter the tool position below.
--Once you enter them, copy and paste the area defined
--below to the second set of positions further down in
--the script. The two sets of tool positions must match
--exactly, or unexpected motion will occur!!!
-----------------Copy Start-------------------
----- Define Tool Postions ------
--Tool 1--
if tool == 1 then
XPos = 7.161
YPos = 49.144
ZPos = -6.283
--Tool 2--
elseif tool == 2 then
XPos = 11.447
YPos = 49.144
ZPos = -6.283
--Tool 3--
elseif tool == 3 then
XPos = 15.733
YPos = 49.144
ZPos = -6.283
--Tool 4--
elseif tool == 4 then
XPos = 20.005
YPos = 49.144
ZPos = -6.283
--Tool 5--
elseif tool == 5 then
XPos = 24.322
YPos = 49.144
ZPos = -6.283
--Tool 6--
elseif tool == 6 then
XPos = 28.593
YPos = 49.144
ZPos = -6.283
--Tool 7--
elseif tool == 7 then
XPos = 32.859
YPos = 49.144
ZPos = -6.283
--Tool 8--
elseif tool == 8 then
XPos = 37.126
YPos = 49.144
ZPos = -6.283
--Tool 9--
elseif tool == 9 then
XPos = 41.432
YPos = 49.144
ZPos = -6.283
--Tool 10--
elseif tool == 10 then
XPos = 45.755
YPos = 49.144
ZPos = -6.283
---------------Copy Stop------------------
else
wx.wxMessageBox("Invalid tool #. Cancelling tool change!\nYour requested tool will now be set as the current tool in the spindle.\n****Ensure that the tool station that you have selected is empty!****")
mc.mcToolSetCurrent(inst, SelectedTool)
mc.mcCntlGcodeExecute(inst, "G43 H"..SelectedTool) --Turn on tool length offset for selected tool
------ Lower DustHood if originally was down at start of m6------
if (dhstate == 0) then
mc.mcSignalSetState(dhsig, 0)
else
mc.mcSignalSetState(dhsig, 1)
end
do return end
end
local GCode = ""
GCode = GCode .. "G00 G90 G53 Z0.0\n"
GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", (XPos-XSlide), (YPos-YSlide))
GCode = GCode .. string.format("G00 G90 G53 Z%.4f\n", ZPos)
GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", XPos, YPos)
mc.mcCntlGcodeExecuteWait(inst, GCode)
------ Open drawbar ------
local hsig = mc.mcSignalGetHandle(inst, DrawBarOut)
mc.mcSignalSetState(hsig, 1)
------ Raise spindle, after releasing tool ------
GCode = ""
GCode = GCode .. string.format("G01 G90 G53 Z-3.00 F250.0\n")
mc.mcCntlGcodeExecuteWait(inst, GCode)
------ Move to next tool change position ------
tool = SelectedTool
-----------------Copy Start-------------------
----- Define Tool Postions ------
--Tool 1--
if tool == 1 then
XPos = 7.161
YPos = 49.144
ZPos = -6.283
--Tool 2--
elseif tool == 2 then
XPos = 11.447
YPos = 49.144
ZPos = -6.283
--Tool 3--
elseif tool == 3 then
XPos = 15.733
YPos = 49.144
ZPos = -6.283
--Tool 4--
elseif tool == 4 then
XPos = 20.005
YPos = 49.144
ZPos = -6.283
--Tool 5--
elseif tool == 5 then
XPos = 24.322
YPos = 49.144
ZPos = -6.283
--Tool 6--
elseif tool == 6 then
XPos = 28.593
YPos = 49.144
ZPos = -6.283
--Tool 7--
elseif tool == 7 then
XPos = 32.859
YPos = 49.144
ZPos = -6.283
--Tool 8--
elseif tool == 8 then
XPos = 37.126
YPos = 49.144
ZPos = -6.283
--Tool 9--
elseif tool == 9 then
XPos = 41.432
YPos = 49.144
ZPos = -6.283
--Tool 10--
elseif tool == 10 then
XPos = 45.755
YPos = 49.144
ZPos = -6.283
---------------Copy Stop------------------
else
wx.wxMessageBox("Invalid tool #. Retrieving previous tool!")
SelectedTool = CurrentTool
mc.mcCntlGcodeExecute(inst, "G43 H"..CurrentTool) -- Turn on Tool Length Offset to CurrentTool
mc.mcSignalSetState(dhsig, 0) -- Lower DustHood
end
GCode = ""
GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", XPos, YPos)
GCode = GCode .. string.format("G00 G90 G53 Z%.4f\n", ZPos + ZBump)
mc.mcCntlGcodeExecuteWait(inst, GCode)
------ Clamp drawbar ------
mc.mcSignalSetState(hsig, 0)
GCode = ""
GCode = GCode .. string.format("G01 G90 G53 Z%.4f F50.0\n", ZPos)
GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", (XPos-XSlide), (YPos-YSlide))
mc.mcCntlGcodeExecuteWait(inst, GCode)
------ Move Z to home position ------
GCode = ""
mc.mcCntlGcodeExecuteWait(inst, "G00 G90 G53 Z0.0\n")
mc.mcCntlGcodeExecute(inst, "G43 H"..SelectedTool) -- Turn on Tool Length Offset to selected tool
------ Reset state ------
mc.mcCntlSetPoundVar(inst, 2134, CurFeed)
mc.mcCntlSetPoundVar(inst, 4001, CurFeedMode)
mc.mcCntlSetPoundVar(inst, 4003, CurAbsMode)
------ Set new tool ------
mc.mcToolSetCurrent(inst, SelectedTool)
mc.mcCntlSetLastError(inst, string.format("Tool change - Tool: %.0f", SelectedTool))
------ Lower DustHood if originally was down at start of m6------
if (dhstate == 0) then
mc.mcSignalSetState(dhsig, 0)
else
mc.mcSignalSetState(dhsig, 1)
end
end
if (mc.mcInEditor() == 1) then
m6()
end
m30
function m30()
local inst = mc.mcGetInstance("m30()");
local msg = "Avid: m30()";
local rc = mc.MERROR_NOERROR;
-- Set Part Finish output signal
local hsig, rc = mc.mcSignalGetHandle(inst, mc.OSIG_PRTSF);
if (rc ~= mc.MERROR_NOERROR) then
mc.mcCntlLog(
inst,
string.format("%s failure to get signal handle, rc=%s", msg, rc),
"",
-1
);
else
mc.mcSignalSetState(hsig, 1);
end
-- Save persistent cycle time
local cycleTime = mc.mcCtrlGetRunTime(inst);
local hreg, rc = mc.mcRegGetHandle(inst, "iRegs0/AvidCNC/GCode/Last_Cycle_Time");
if (rc ~= mc.MERROR_NOERROR) then
mc.mcCntlLog(
inst,
string.format("%s failure to get register handle, rc=%s", msg, rc),
"",
-1);
else
mc.mcRegSetValueString(hreg, tostring(cycleTime));
end
--[[ Additional items that need to be included so
our custom M30 macro perfrorms all the functions
of the stock M30 macro.
--]]
-- Cutter comp, coolant, mist, and spindle OFF
rc = mc.mcCntlGcodeExecute(inst, "G40\nM09\nM05");
if (rc ~= mc.MERROR_NOERROR) then
mc.mcCntlLog(
inst,
string.format("%s failure to execute gcode, rc=%s", msg, rc),
"",
-1
);
end
end
if (mc.mcInEditor() == 1) then
m30()
end
-
I upgraded mach4 from 4.2.0.4809 to 4.2.0.5125. Still not working.
-
I'm getting the same result as you, trying to execute a custom macro within another macro causes it to hang. You will have to turn off the spindle in the m30 using mc.mcSpindleSetDirection like you did in the m6.. it's probably the better way to do it anyway
-
Glad to hear it is not only me. Wasn't seeing many responses so I was beginning to think it was something with my installation or setup.
I will probably do a mc.mcSpindleSetDirection for now in my m30 but I would like to know what is causing the issue. I am in contact with Trevor from machsupport so I hope to have a resolution soon.
-
I thought I should update this thread in case anyone is interested.
Trevor didn't give me an exact reason why a custom m5 macro doesn't work when used in a mc.mcGCodeExecuteWait beside it wasn't proper to call a macro from within a macro. I ended up replacing them with an m5(). it worked fine that way.
I can tell you this, calling a macro inside of another macro isn't the way to do it typically as you can avoid it 99% of the time, however, if you are calling another macro within your macro make sure it's not called with a GCODEEXECUTEWAIT(inst, "M5") as I believe you should just call the m5() function that is contained within that macro.
So this changes from:
mc.mcGCODEEXECUTEWAIT(inst, "M5")
to
m5()
All the macros get compiled together so you should have access to all the macro functions within all macros.
For instance, if you make an M5.mcs file with nothing in it and you have a m6000.mcs file as well, you can define the m5() function within the M6000 macro because they all get compiled together.
-
Calling a macro from another macro with mcCntlGcodeExecute/Wait() is not the best practice. You are writing a script that should call script functions where possible. So if M5 called mc.mcSpindleSetDirection(inst, mc.MC_SPINDLE_OFF), then your M30 script should too INSTEAD of calling mcCntlGcodeExecute/Wait(inst, "M5") Why? Because the interpreter is already RUNNING an M code that is backed by a script. Some M codes are built in (no script) and they will run.
So what if you M5 does some multiline complex operation and it is hard to edit EVERYTHING to do that operation? Especially if you made changes to it and want to update everything. This is where code sharing via modules becomes a good idea.
Steve