Hello Guest it is December 08, 2019, 05:16:29 AM

Author Topic: Is it possible to call an M code from a different M code?  (Read 594 times)

0 Members and 1 Guest are viewing this topic.

Is it possible to call an M code from a different M code?
« on: February 18, 2019, 02:09:59 PM »
In my ATC script I have a cycle that sets the depth of the the tool. I copied this code in to a new File named M1000.mcs. and placed it in the same directory as my M6 file.

In my M6 code I call the M1000 and the cycle just stops.  I can't get it to call an external M command to work, it always hangs.

For example i tried:
Code: [Select]
function m1000()   
    inst=mc.mcGetInstance()   
    mc.mcCntlSetLastError(inst, 'Call M1000 Success!')
end

if(mc.mcInEditor()==   1) then
    m1000()
end

And calling from my M6 with
Code: [Select]
mc.mcCntlGcodeExecuteWait(inst, "M1000")

Any idea how to do this?

I would like to be able to add a button to my screen to just call the tool measurement command. Then I can just insert a tool, measure, and go. I don't want to have the same code in 2 different places, that's a maintenance nightmare.

Offline MN300

*
  •  107 107
    • View Profile
Re: Is it possible to call an M code from a different M code?
« Reply #1 on: February 18, 2019, 07:41:19 PM »
All you need to call your depth setting function from m6 is the line 
     M1000()

That's just like it's done in the line after        if(mc.mcInEditor()==   1) then

The way you tried is causing an error.

If you are not calling your m1000 from G Code you might want to name it something else to avoid confusion with real M code.

Re: Is it possible to call an M code from a different M code?
« Reply #2 on: February 19, 2019, 09:06:33 AM »
The M1000 function is in a different file. I will try tonight.

The reason i want it in a different file and in it's own M code is that I would like to be able to tie the  command to a button, use it in my M6 routine, and call it from a Gcode file. It is working well but if I ever find an error or update it I only want to fix it in one place.

Offline Chaoticone

*
  • *
  •  5,633 5,633
  • Precision Chaos
    • View Profile
Re: Is it possible to call an M code from a different M code?
« Reply #3 on: February 19, 2019, 11:30:46 AM »
Code: [Select]
The M1000 function is in a different file.
This is true but all macros get compiled into the single mcLua.mcc file (chunk). So functions in one macro are available to other macros unless they are made local within the macro they are created in. So MN300's suggestion is spot on. Use m1000() in other macros. Call the m1000 as gcode from buttons.

Another way you could do it is to put your depth setting function in a module and call it from various macros, screen buttons, etc. but the above solution is simpler.

;D If you could see the things I have in my head, you would be laughing too. ;D

My guard dog is not what you need to worry about!
Re: Is it possible to call an M code from a different M code?
« Reply #4 on: February 19, 2019, 10:13:05 PM »
Hi,
an interesting side note.......when Machs Gcode interpreter reads a line of Gcode it reduces all letters to lowercase
and strips out leading zeros.

Thus:
M6
M06
m6 and
m06
all mean the same thing to Mach. In most cases its perfectly OK to call M06, say in your Gcode but when Mach
searches for the code to execute it will be looking for 'm6' not 'M06'. Filenames in Windows is case insensitive
so it works, but occasionally it screws up too! My recommendation (Smurph's tip) is to use lowercase letters
without leading zeros.

Quote
If you are not calling your m1000 from G Code you might want to name it something else to avoid confusion with real M code.

There are predefined m codes in Mach, like m3, m4, m30 etc. When the Gcode interpreter encounters such a call it searches
first the macros folder of the active profile, if it doesn't find it there it executes the standard code that ships with Mach.
So you can write your own m3 for instance and if its in the first search path it will be used instead of the standard m3.

Craig
My wife left with my best friend...
     and I miss him!
Re: Is it possible to call an M code from a different M code?
« Reply #5 on: February 20, 2019, 06:39:23 PM »
Hi,
I have been thinking a bit more about your question 'can you call an M code from a different Mcode'....

What you have attempted is to call m1000 from an m6 macro. As you have discovered it does not work in the manner that
you attempted. Why?

Lets assume you are running a Gcode job, that is to say that the machine and its motion controller is under exclusive
control of Machs Gcode interpreter. It encounters an m6 code and therefore searches for the code pertaining to m6.
It relinquishes control of the motion controller to the macro but the interpreter just waits UNTIL the macro returns.

If, in executing m6, it encounters an instruction like:
mc.mcGcodeExecuteWait(inst,'m1000')....there is a problem. The instruction in essence asks the Gocode interpreter to
find and execute the code of m1000. BUT the Gcode interpreter is busy, its busy waiting....waiting for m6 to return.
There is only one Gcode interpreter ie it is single threaded so it cant respond to the mc.mcGcodeExecuteWait() instruction
because it doing something else, thankyou very much!.

This reflects that the Gcode interpreter cannot be both 'caller and callee'

The method described by MN300 and confirmed by Chaoticone uses an approach that avoids that trap.
Namely if your m6 macro includes an instruction like:
m1000()......the m6 macro becomes the caller and it calls the function m1000(). Provided Mach can find the code within the chunk
it will run and when it completes return to it caller, namely m6. Then when m6 completes it will return to its caller, namely the
Gcode interpreter. No clash.

Craig
My wife left with my best friend...
     and I miss him!
Re: Is it possible to call an M code from a different M code?
« Reply #6 on: February 21, 2019, 05:53:39 PM »
Unfortunately it still doesn't work

Here Is my code calling it:

Code: [Select]
M1000()
It still just hangs when it gets to that line. I understand why it would hang if I called it from G-Code now. Joe's comment makes sense. But I'm not sure why my code isn't working.

I've attached both my M6 and M1000 files. (Had to ad the copy to the names so it would upload)
Re: Is it possible to call an M code from a different M code?
« Reply #7 on: February 21, 2019, 07:34:57 PM »
Hi,
I think you are still doing the same thing:

Code: [Select]
function SetDepth()
    ------ Auto Depth Setting ------ 
   function SetDepth()
    ------ Auto Depth Setting ------ 
    mc.mcCntlGcodeExecuteWait(inst, "G00 G53 X35.93 Y2.75\n") -- go to point over depth setter
    mc.mcCntlSetLastError(inst, 'Setting Tool Height')
    mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-4 F50") --probe the new tool
    mc.mcCntlGcodeExecuteWait(inst, "G91 G0 Z+0.1") --Retract from the probe
mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-0.15 F5") --Probes at slow speed
local measure_1 = mc.mcAxisGetPos(inst,2) --Saves probed Z position

    mc.mcCntlSetLastError(inst, 'Setting Tool Height')
    mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-4 F50") --probe the new tool
    mc.mcCntlGcodeExecuteWait(inst, "G91 G0 Z+0.1") --Retract from the probe
mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-0.15 F5") --Probes at slow speed
local measure_1 = mc.mcAxisGetPos(inst,2) --Saves probed Z position

OK, m6 calls M1000(), so m6 is caller. M1000 calls SetDepth(), so M1000 is caller. Now SetDepth attempts to execute:
mc.mcCntlGcodeExecuteWait(inst, "G00 G53 X35.93 Y2.75\n") -- go to point over depth setter, the first
mc.CntlGcodeExecuteWait() instruction and fails because the GCode interpreter is busy.....still.

May I suggest you try some diagnostic code. First put a few wxMessageBox statements so that you can confirm that
program control reached that juncture. The second is that you are going to have to test the return code of the
mc.CntlGcodeExecuteWait() instruction. The third is to report the machine state.

Modify your code like this:

Code: [Select]
local inst = mc.mcGetInstance()
local ZGageBlockHeight = 3.3091

function  m1000()
------ Auto Depth Setting ------ 
wx.wxMessageBox("M1000() called")
SetDepth()
   
end

function SetDepth()
    ------ Auto Depth Setting ------ 
wx.wxMessageBox("SetDepth() called")
local rc= mc.mcCntlGcodeExecuteWait(inst, "G00 G53 X35.93 Y2.75\n") -- go to point over depth setter
local mcState=mc.mcCntlGetState(inst)
wx.wxMessageBox(tostring(rc)..'      '..tostring(mcState))
    mc.mcCntlSetLastError(inst, 'Setting Tool Height')
    mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-4 F50") --probe the new tool
    mc.mcCntlGcodeExecuteWait(inst, "G91 G0 Z+0.1") --Retract from the probe
mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-0.15 F5") --Probes at slow speed
local measure_1 = mc.mcAxisGetPos(inst,2) --Saves probed Z position

When you run your code I expect to to get three message box notifications.
The first will be "M1000() called", ie that m6 has successfully called M1000.
The second will be "SetDepth() called", ie that M100 has successfully transferred control to SetDepth().
The last is the truly critical notification. If the mc.CntlGcodeExecuteWait() instruction completed normally
then the return code will be "0". If it does not complete correctly I suspect the return code will be "-18".
That corresponds to the error MERROR_NOT_NOW which is just another way to say the Gcode interpreter is busy.
The same message notification will provide a numeric value for the machine state. My guess is it will be either 108 or 207.
Either way it will tell us more.

Try the code and report how you get on.

Craig
My wife left with my best friend...
     and I miss him!
Re: Is it possible to call an M code from a different M code?
« Reply #8 on: February 21, 2019, 08:23:00 PM »
Hi,
I was just looking through the m6 file that you posted.....I can't find anywhere in the file M1000().....what
gives? Does m6 call M1000() or does it not?

Craig
My wife left with my best friend...
     and I miss him!
Re: Is it possible to call an M code from a different M code?
« Reply #9 on: February 21, 2019, 08:39:30 PM »
Hi,
another question:

Code: [Select]
function  m1000()
------ Auto Depth Setting ------  local inst = mc.mcGetInstance()
local ZGageBlockHeight = 3.3091

SetDepth()
   
end

function SetDepth()
    ------ Auto Depth Setting ------ 
    mc.mcCntlGcodeExecuteWait(inst, "G00 G53 X35.93 Y2.75\n") -- go to

Why the hell have you put:

local inst = mc.mcGetInstance()
local ZGageBlockHeight = 3.3091

outside of the two functions. They are declared as local variables and if they are to be used in a function they must be declared
WITHIN that function.

The only other alternative is NOT to declare them as local variables which would make them global variables
available throughout the chunk.

Second question is why you declared M1000() at all? All is does is call yet another function SetDepth().
The function M1000() is redundant.

While it may look really nice to have extensive comments throughout a macro and is certainly helpful to anyone inspecting
the macro for the first time.....it sure ups the word count and probably the confusion factor. Simple lean code it usually
the most robust code........comments are help that not confuse it.
My wife left with my best friend...
     and I miss him!