Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: TTalma on February 18, 2019, 02:09:59 PM

Title: Is it possible to call an M code from a different M code?
Post by: TTalma 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.
Title: Re: Is it possible to call an M code from a different M code?
Post by: MN300 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.

Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma 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.
Title: Re: Is it possible to call an M code from a different M code?
Post by: Chaoticone 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.

Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage 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
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage 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
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma 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)
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage 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
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage 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
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage 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.
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma on February 22, 2019, 05:45:17 PM
In m6  I thought I had the M1000() call commented out, i didn't realize I erased it, but ithe M1000() line replace the SetDepth() call. I did this because M1000() call is hanging. So I copied the SetDepth function into the M6 file so I could run my machine.

Ideally SetDepth would only reside in the M1000() file and not in M6 at all. I want to call the M1000 from 3 different areas, From M6, from Gcode, and from a button. I don't want to have to maintain the same code in 3 different areas. I have 14 different bits I use regularly, and only have room to hold 7 tool. But a bunch of my jobs only require one tool so i won't need the autochanger, I'll just need to measure the bit depth and go.

I copied the line setting up the inst variable from the Mach 4 sample code. According to my understanding of LUA declaring those outside of the function does make the globals, and they seem to work that way. But I admitt I do not have a great understanding of the LUA nuances.

I made the change as you suggested adding the debug line, Unfortunately it never shows up.
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage on February 22, 2019, 08:36:13 PM
Hi,
the fact that none of the wxMessageBox notifications have showed up mean that program control has NEVER progressed that far.
Thus your m6 program is never calling m1000.

Where did you get that m6 code from. It seems way wordy....and confusing. Lua code tend to be short, sharp and sweet.

Craig
Title: Re: Is it possible to call an M code from a different M code?
Post by: smurph on February 23, 2019, 02:11:52 PM
Again, a reminder to keep all M code function names and file names lower case. 

Steve
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma on February 24, 2019, 02:07:08 PM
I wrote the M6 code. It's odd that the M1000 call isn't working everything works great when I run the code as is in the file I attached earlier in this thread.

When I step through the code it works great but when calling it from the M6 or the MDI window it doesn't work. Calling it from the MDI window the buttons just flash. As a test I tried turning M1000 in to the following:
 
Code: [Select]
function  m1000()
    mc.mcCntlSetLastError(0, "In m1000")
end

if(mc.mcInEditor() == 1) then
    -- If you are in the mcLua editor, this will cause your script to execute if you Run or Debug
    -- Make sure your Capitalization and numbers match that of the function you are calling
    m1000()
end

And this still does not work!

If you cut and paste this in to a file named m1000() on your machine does the message pop up in the box on the bottom of your screen?

I cut and pasted the 1st 61 lines in my M6 file from the sample code. The rest of the code I wrote. I'm not sure what I could do to shorten it. All of the moves are safe moves and I have to time the positions of the 3 axis with the 3 pneumatic valves. Unfortunately I can't toggle an output in a line of GCode, or I could coordinate the movements, and probably eliminate quite a bit of code. For example there is no reason to pause the motion to close the chuck, other than that is a limitation of how mach works.
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage on February 24, 2019, 03:19:30 PM
Hi,
I have no doubt m1000() works but m6 doesn't call it.

I don't really want to put buggy code into my setup....I may try later today.

Run m6 (lowercase) and see if m1000() is called?.
Is SetDepth() then called?.....whether you use wxMessabe Box or some other method matter less than if you call
m6 then eventually SetDepth() should be called. You need to test the machine state at the time of
the mc.CntlGcodeExecuteWait() call.

Craig
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage on February 24, 2019, 05:35:04 PM
Hi,
I have gone through m6 and regrouped, I hope it might help you.

The main thing I have done is break m6 into several files, the m6() proper, releaseTool(), getTool() and setToolDepth().

Note that I have deliberately reduced the leading letter of each function to lowercase per smurph's recommendation. In truth
the interpreter will reduce subsequent characters to lowercase also but I have retained capitalization of some letters to maintain
readability.

The second thing I have done is on every occasion where a mcCntlGcodeExecuteWait() is called I have tested the return code to ensure
that the function completed. Should it not do so you get a wxMessageBox notification including a number that will help you identify
any particular call which failed and a second number corresponding to the MERROR.

It maybe that once you have worked out how to get all this code to work that you can either delete or comment out
all (24 or so) diagnostic statement groups.....but for the moment they will highlight any errors.

I have bundled the module load statement in m6.

Note also that ALL four files need to be saved in the Macros folder of your current profile.

Save as m6.mcs
Code: [Select]
function  m6()
local ZGageBlockHeight = 3.3091
local inst = mc.mcGetInstance()
package.path = wx.wxGetCwd() .. "\\Profiles\\AXYZ\\Modules\\?.lua;"
if(package.loaded.ToolChangePositions == nil) then
tcp = require "ToolChangePositions"
end
    local SelectedTool = mc.mcToolGetSelected(inst)
    local CurrentTool = mc.mcToolGetCurrent(inst)
    local rc=mc.mcCntlGcodeExecuteWait(inst, "m5\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 1 MERROR="..tostring(rc))
do return end
end
local CurFeed = mc.mcCntlGetPoundVar(inst, 2134)
    local CurFeedMode = mc.mcCntlGetPoundVar(inst, 4001)
    local CurAbsMode = mc.mcCntlGetPoundVar(inst, 4003)
    local ToolData = tcp.GetToolData(CurrentTool)
    if (ToolData ~= nil) then
        Num1 = ToolData.Tool_Number
        XPos1 = ToolData.X_Position
        YPos1 = ToolData.Y_Position
        ZPos1 = ToolData.Z_Position
    else
        mc.mcCntlEStop(inst)
        mc.mcCntlSetLastError(inst, "ERROR: Tool number out of range!")
        do return end
    end
    local ToolData = tcp.GetToolData(SelectedTool)
    if (ToolData ~= nil) then
        Num2 = ToolData.Tool_Number
        XPos2 = ToolData.X_Position
        YPos2 = ToolData.Y_Position
        ZPos2 = ToolData.Z_Position
    else
mc.mcCntlEStop(inst)
        mc.mcCntlSetLastError(inst, "ERROR: Tool number out of range!")
        do return end
    end
    local GCode = ""
    GCode = GCode .. "G00 G90 G53 Z0\n"
    GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", XPos1, YPos1)
    local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 2 MERROR="..tostring(rc))
do return end
end
GCode = ""
    GCode = GCode .. string.format("G00 G90 G53 Z%.4f\n", ZPos1)
    local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 3 MERROR="..tostring(rc))
do return end
end
    ------ Release the current tool ------
    releaseTool(CurrentTool)
    ------ Move to next tool change position ------
    GCode = ""
    GCode = GCode .. string.format("G00 G90 G53 X%.4f Y%.4f\n", XPos2 + 2, YPos2)
    local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 4 MERROR="..tostring(rc))
do return end
end
    ------ Get the new tool ------
    getTool(SelectedTool)
    ------ Set Tool Depth ------
    setToolDepth()
    ------ Move Z to home position ------
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G90 G53 Z0\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 5 MERROR="..tostring(rc))
do return end
end
    ------ Reset state ------
    mc.mcCntlSetPoundVar(inst, 2134, CurFeed)
    mc.mcCntlSetPoundVar(inst, 4001, CurFeedMode)
    mc.mcCntlSetPoundVar(inst, 4003, CurAbsMode)
    ------ Set new tool ------
    mc.mcToolSetCurrent(inst, SelectedTool)
    CurrentTool = mc.mcToolGetCurrent(inst)
    mc.mcCntlSetLastError(inst, string.format("Tool changed, now using tool: %.0f", CurrentTool))
end
if (mc.mcInEditor() == 1) then
m6()
end

Save as releaseTool.mcs
Code: [Select]
function releaseTool(CurrentTool)
local inst=mc.mcGetInstance()
    -- Set special casses
    if(CurrentTool == 7) then
        ------ Lower to drop off position ------
        local GCode = ""
        GCode = GCode .. "G00 G53 x36 Y2\n"
        GCode = GCode .. "G00 G53 x39.6 Y2\n"
        GCode = GCode .. "G00 G53 z-6.11\n"
        GCode = GCode .. "G01 G91 Y-2 F100\n"
        local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 6 MERROR="..tostring(rc))
do return end
end
    else
        ------ Lower to drop off position ------
        local rc=mc.mcCntlGcodeExecuteWait(inst, "G01 G91 X2 F100\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 7 MERROR="..tostring(rc))
do return end
end
    end
    ----- Open Drawbar ------
    local DrawbarOPEN = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1)
    mc.mcSignalSetState(DrawbarOPEN, 1)
    ------ Move to Clear position turn off drawbar------
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G91 Z.75\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 8 MERROR="..tostring(rc))
do return end
end
    mc.mcSignalSetState(DrawbarOPEN, 0)   
    ------ Close Drawbar ------
    local DrawbarCLOSE = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT2)
    mc.mcSignalSetState(DrawbarCLOSE, 1)
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G04 P200\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 9 MERROR="..tostring(rc))
do return end
end
    mc.mcSignalSetState(DrawbarCLOSE, 0)
    ------ Move to clear tool position ------
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G90 G53 Z-3.0")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 10 MERROR="..tostring(rc))
do return end
end
end
if (mc.mcInEditor()==1)then
releaseTool()
end

Save as getTool.mcs
Code: [Select]
function getTool(SelectedTool)
local inst=mc.mcGetInstance()
    ------ Lower to blow off start position ------
    if(SelectedTool == 7) then -- Set special casses
        ------ Lower to drop off position ------
        local GCode = ""
        GCode = GCode .. "G00 G53 x39.6\n"
        GCode = GCode .. "G00 G91 Y-2.75\n"
        local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 11 MERROR="..tostring(rc))
do return end
end
    end
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G91 Z-1.75\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 12 MERROR="..tostring(rc))
do return end
end
   
    ------ Turn on Blow off  ------
    local BlowOff = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT0)
    mc.mcSignalSetState(BlowOff, 1)
    ------ Lower to pick up start position shut off blow off, turn on drawbar------
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G91 Z-1\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 13 MERROR="..tostring(rc))
do return end
end
    mc.mcSignalSetState(BlowOff, 0)
    local DrawbarOPEN = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1)
    mc.mcSignalSetState(DrawbarOPEN, 1)
    ------ Move to pickup position position ------
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G91 Z-.5\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 14 MERROR="..tostring(rc))
do return end
end
    ------ Turn off  open drawbar ------
    mc.mcSignalSetState(DrawbarOPEN, 0)
    ------ Close Drawbar ------
    local DrawbarCLOSE = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT2)
    mc.mcSignalSetState(DrawbarCLOSE, 1)
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G91 Z.2\n")
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 15 MERROR="..tostring(rc))
do return end
end
    ------ Stop Closing drawbar ------
    mc.mcSignalSetState(DrawbarCLOSE, 0)
    ------ Move to final tool change position ------
    local GCode = ""
        if(SelectedTool == 7) then
        GCode = GCode .. "G01 G91 Y2 F100\n" -- Clear fork
        GCode = GCode .. "G00 G90 G53 Z0\n" -- Go up
    else
        GCode = GCode .. "G01 G91 X-2 F100\n" -- clear fork
        GCode = GCode .. "G00 G90 G53 Z0\n" -- Go up
        GCode = GCode .. "G00 G53 X33 Y2.75\n" -- Go to clear position read to measure       
    end
    local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 16 MERROR="..tostring(rc))
do return end
end
end
if (mc.mcInEditor()==1)then
getTool()
end

Save as setToolDepth.mcs
Code: [Select]
function setToolDepth()
local inst=mc.mcGetInstance()
local ZGageBlockHeight = 3.3091
    ------ Auto Depth Setting ------ 
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G00 G53 X35.93 Y2.75\n") -- go to point over depth setter
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 17 MERROR="..tostring(rc))
do return end
end
    local rc=mc.mcCntlSetLastError(inst, 'Setting Tool Height')
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 18 MERROR="..tostring(rc))
do return end
end
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-4 F50") --probe the new tool
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 19 MERROR="..tostring(rc))
do return end
end
    local rc=mc.mcCntlGcodeExecuteWait(inst, "G91 G0 Z+0.1") --Retract from the probe
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 20 MERROR="..tostring(rc))
do return end
end
local rc=mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-0.15 F5") --Probes at slow speed
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 21 MERROR="..tostring(rc))
do return end
end
local measure_1 = mc.mcAxisGetPos(inst,2) --Saves probed Z position

local rc=mc.mcCntlGcodeExecuteWait(inst, "G91 G0 Z+0.1") --Retracts from the probe
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 22 MERROR="..tostring(rc))
do return end
end
local rc=mc.mcCntlGcodeExecuteWait(inst, "G91 G31 Z-0.15 F5") --Probes at slow speed
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 23 MERROR="..tostring(rc))
do return end
end
local measure_2 = mc.mcAxisGetPos(inst,2) --Saves probed Z position
   
local measured_average = (measure_1 + measure_2)/2 --Averages two probed values
    local offSet = measure_2 - measured_average
local adjustedHeight = ZGageBlockHeight + offSet

    mc.mcAxisSetPos(inst,2,adjustedHeight) --Sets current Z postion to gage block height with measured offset

GCode = ""
    GCode = GCode .. "G00 G90 G53 Z0\n" --Retract
    GCode = GCode .. "G00 G53 X33 Y2.75\n" -- Move to clear spot
    local rc=mc.mcCntlGcodeExecuteWait(inst, GCode)
if rc~=0 then
wx.wxMessageBox("mcCntlGcodeExecuteWait() did not progress 24 MERROR="..tostring(rc))
do return end
end
end
if (mc.mcInEditor()==1)then
setToolDepth()
end

Scan the code and see what you think. Note that M1000() occurs nowhere. Should you want to call setToolDepth() from
from the main Gcode job, not m6, but the main program, THEN use m1000 and create a function m1000() in your Macros
folder that explicitly calls setToolDepth(). In this way setToolDepth() will exist as only one file but may be called by different
procedures.

Craig

 
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma on February 25, 2019, 09:05:56 AM
Craig, Thanks. I really appreciate all your effort! I will test this tonight and let you know how it goes.
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma on February 26, 2019, 06:14:49 PM
Ok, I had a chance to work on this tonight. I made the files and loaded the code in them. When I step through the m6 command as soon as I get to the line:
Code: [Select]
releaseTool(CurrentTool)
The debugging session ends, The debug window displays:

Code: [Select]
Program starting as '"C:\Mach4Hobby\ZeroBraneStudio\bin\lua52.exe" -e "io.stdout:setvbuf('no')" "C:\Users\CNC\AppData\Local\Temp\.8EAC.tmp"'.
Program 'lua52.exe' started in 'C:\Mach4Hobby' (pid: 5432).
Debugging session started in 'C:\Mach4Hobby\'.
Profiles/AXYZ/Macros/m6.mcs:61: attempt to call global 'releaseTool' (a nil value)
stack traceback:
Profiles/AXYZ/Macros/m6.mcs:61: in function 'm6'
Profiles/AXYZ/Macros/m6.mcs:90: in main chunk
Debugging session completed (traced 2 instructions).
Program completed in 6.82 seconds (pid: 5432).

It's stating that 'releaseTool' is a nil value. It appears it can't find 'releaseTool'! How do I debug this? The releaseTool file is in the folder "C:\Mach4Hobby\Profiles\AXYZ\Macros"
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage on February 26, 2019, 06:30:31 PM
Hi,
when you are in the editor the external function call fails.

If you run Mach then all the functions in the Macros folder get compiled into the chunk and are therefore available
to any other function within the chunk.

The simplest way to get over that is to include the code for the required function in the same file as m6, it would
then be compiled with m6 and available to it.

I thought to separate each function from m6 to reduce the confusion and should you wish to make some changes
it would be easier to find.

When I single stepped through each function but I stepped 'over' the function calls in m6 to avoid calling a none existent
function. As far as the editor is concerned the external functions are 'nil'.

Craig
Title: Re: Is it possible to call an M code from a different M code?
Post by: TTalma on February 28, 2019, 05:51:20 PM
I ran the code split in to the files like you suggested. And it works great! I added an m1000 file that just calls the setToolDepth function. And it works as desired.

Thank you so much for your help! I hope I can help you one day.

The next step is tying the M1000()  command to the empty button in the tool information section.
Title: Re: Is it possible to call an M code from a different M code?
Post by: joeaverage on February 28, 2019, 06:31:32 PM
Hi,
smurph is one of the lead developers of Mach4 and a seasoned programmer. He has repeatedly suggested to all and sundry
that each and every API call return code be tested. I'm slack and only do so when I get into trouble but there are certain
API's where if you don't test the return code you ARE IN TROUBLE......you don't know when but it WILL BLOW UP IN YOUR FACE.

One such API is mc.CntlGcodeExecuteWait(). Another is mcSignalWait. Having being burnt I usually always test them,
I know it adds complexity to the code but it works and saves grief.

The only time I tend not to test them is if the extra (seeming) code complexity will obscure the program logic, particularly
if I'm posting on the forum for others benefit. In that situation clear concise code with minimal clutter conveys the most
understanding. Code that I develop for my own machine includes multiple test points.

Craig