Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: MrPuhur on February 12, 2018, 01:27:44 PM

Title: Lua script detect when the cycle is running
Post by: MrPuhur on February 12, 2018, 01:27:44 PM
I have an M6 lua script set up to automatically do everything required to switch tools on a 2 spindle (main spindle + drill spindle) machine, and it has got to the point of being rather complex and therefore hard to debug and even harder to keep reliable.

There's one thing that 's been coming up recently, which is that, if the machine is disabled or the G-code cycle stopped during M6, the script just keeps on being executed, save the G-code calls from within the lua script through mc.mcCntlGcodeExecuteWait(). This results in the machine's movement stopping as expected, but then signals being set as if it wasn't disabled or stopped at all possibly causing tools to fall out of the spindle among others. I do understand that this is a requirement for some scripts, such as ones meant to act to turn off spindles after a disable command, but for M6 this is not the case.

I have somewhat managed to fix it by calling a function to check if the machine is enabled each time a signal change occurs in the code, so it only proceeds if the function returns true. The function is as follows:

function toolchange_machine_enabled()
    local inst = mc.mcGetInstance()
    local hsig=mc.mcSignalGetHandle(inst, mc.OSIG_MACHINE_ENABLED)
    local val=mc.mcSignalGetState(hsig)
    if val==1 then
        return true
    else
        return false
    end
end

(It's intentionally non-compact and readable.)
I'd like to hear from you suggestions to make it better so that it would return true only if mc.mcCntlGcodeExecuteWait() would execute. OR, if there's another way of solving the problem that is more correct, I'd be happy to hear on those.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 13, 2018, 01:54:02 AM
Hi,
I don't know if this would help:
Quote
LUA Syntax:
cycle, rc = mc.mcCntlIsInCycle(
      number mInst)

Also you may have to check the return code of GcodeExexcuteWait(). It will only execute if the control state is idle. There are occasions when it does not
execute even when the control is idle. Under those circumstances the return code is -18 or MERROR_NOT_NOW.

Just as a matter of interest do you check the control state before making the GCodeExecuteWait() call? I found if I didn't and the control is not idle then I would crash
Mach altogether!

Craig
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 13, 2018, 01:56:02 PM
I don't check anything before calling mc.mcCntlGcodeExecuteWait(), Mach seems to be taking care of stopping any actions specified by it whenever required. I call my function before changing signals, as in outputs. However, now I'm thinking that maybe I should, if an error like you described could pop up.

Your example, while it seems to work for G-code files, doesn't work if ran under MDI (returns 1 if G-code file, 0 if MDI or machine disabled or stopped).

Here's what I used to test it - an M-code. I tested it by stopping or disabling the machine during the G4 time delay and comparing the results to occasions on which I let it complete.

function m400()
    local inst = mc.mcGetInstance()
    print("starting")
    mc.mcCntlGcodeExecuteWait(inst,"G4 P3")
    cycle, rc = mc.mcCntlIsInCycle(inst)
    print("cycle: "..cycle.." rc: "..rc)
    if (cycle == 1) then
        print("Cycle running")
    else
        print("Cycle not running")
    end
end
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 14, 2018, 01:06:06 AM
Hi,
I think there is a difference between InCycle and MC_STATE_IDLE.

For any code  to produce motion requires the use of the motion planner. If for instance you want to run a Gcode file the sequence of events would be:
Is there a process or code currently using the Planner?
----If there is terminate the process/code
----If not the control will be idle and if idle the planner is available for use
Submit the Gcode job to the Planner

The code could be a Gcode file or an MDI command or a GcodeExecuteWait() API call or a screen script. In any case the control must be idle before a new stream
of motion instructions can be run.


When a Gcode file OR MDI command is run there must be a CycleStart command and thereafter the CntlIsInCycle() would return true. If a later CycleStop is executed
the CntlIsInCycle() would return false. What happens however if a FeedHold is encountered, is it still InCycle? Also what happen if it yields as part of a coroutine pair?
It is not clear to me that InCycle is the same as MC_STATE_IDLE

As I posted earlier I recently discovered that if I executed a GcodeExecuteWait() statement without first ensuring the control state is Idle then I could crash Mach bigtime.
As a consequence I put this line of code in:

if (mc.mcCntlGetState(inst) ~=0)then mc.mcCntlCycleStop(inst)end

Note that control state idle is numerically equivalent to 0. This statement checks that the control is idle and if it isn't issues a CycleStop to make it so.

The next issue I encountered is that even though the control is idle sometimes the GcodeExecuteWait() will not execute and will return MERROR_NOT_NOW.
If you were relying on the statement to make some move but for whatever reason did not move you could have a crash if you made some other move in expectation
that the previous move had been made. Thus I had this test:

local rc=mc.mcGcodeExecuteWait(inst,'g0......')
if rc==-18 then wx.wxMessageBox('GcodeExecuteWait() failed to complete') end

In fact my code became a little more sophisticated than that, if my GcodeExecuteWait() did not complete I would issue a MachDisable MachEnable pair and try again
for up to five times before the wxMessageBox error warning. This made my code pretty robust.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: sour kraut on February 14, 2018, 07:07:35 PM
So I decided to download mach4 to my travel computer and do some testing before I get home.  Here's what I did and what I found.  I added the following 2 lines to the standard M6.mcs file after the IF THEN ELSE END. I then moved the O9010 file from the subroutine sample directory into the subroutine directory and added an incremental move in it.
 
Code: [Select]
mc.mcCntlSetLastError(inst, "INSIDE MACRO M6")
mc.mcCntlGcodeExecuteWait(inst,"M98 P9010")
 

I created a simple file to run.

Code: [Select]
G90
M6
M30

So mach called the macro and the error printed.  It then DID make the incremental motion but it didn't seem to like it really waited like the command asks for .  I then reverse the process and called a macro from a subroutine and it seemed to work the same way.  I'll have to test this in more detail when I get home.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 14, 2018, 10:18:25 PM
Hi,
I was reading about subroutines and macros last night in Peter Smids book which is pretty much the standard
for both Fanuc and Mach4.

He doesn't call them subroutines or macros but calls all of them subprograms. Your bit of testing suggests they can be
used interchangeably as well.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: sour kraut on February 14, 2018, 10:48:38 PM
$h!t, I replied in the wrong post. Sorry.
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 15, 2018, 12:24:09 PM
I think we might be getting a bit overcomplicated here. What I need would just be something to check so as to not execute a piece of code, if a Gcode or an MDI program isn't running. In other words, if the G-code or MDI program is stopped during executing an M-script, the script could know and halt itself. Checking mcCntlIsInCycle() works for G-code programs, but I couldn't find anything that would work for MDI.

The piece of code isn't related to the motion planner, rather changing the state of signals.

However, I'm really thankful that you mentioned GcodeExecuteWait() could return an error, which I had overlooked since it had never happened to me.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 15, 2018, 12:56:48 PM
Hi,

Quote
The piece of code isn't related to the motion planner, rather changing the state of signals.

No that's correct but if you check that the control state is Idle then that will determine that no code is running, Gcode or MDI or screenscript.

Quote
LUA Syntax:
mcState, rc = mc.mcCntlGetState(
      MINSTANCE mInst)

local mcState,rc=mc.mcGetState(inst)
if (mcState==mc.MC_STATE_IDLE) then
--
-- execute your code as the control is idle and ready for use
--
else
--
-- the control is not idle and not available to be tasked
-- if required you can terminate the current task
--
end

Craig

Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 15, 2018, 02:07:07 PM
Thanks, it seems to be suitable. Just to clear it up, for me it would be the opposite:

local mcState,rc=mc.mcCntlGetState(inst)
if (mcState==mc.MC_STATE_IDLE) then
    --
    -- Don't execute code, as the program was terminated (either the machine was disabled or the stop button was pressed) and the M-script should not proceed.
    --
else
    --
    -- The program is still running, and therefore it is safe to proceed execution
    --
    --
end

Now this might not be totally safe, as there may be other states under which code should not execute, yet which will take the 'else' route in this example. Is there a list of states and their descriptions? I couldn't find one in the docs or by using Google.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 15, 2018, 04:15:33 PM
Hi,

http://www.machsupport.com/forum/index.php/topic,36548.0.html (http://www.machsupport.com/forum/index.php/topic,36548.0.html)

No, what I am saying is that IF you try to execute code when the control is NOT idle then you'll
crash Mach.

What you are asking is: 'how did the control become idle...did the previous code execute and exit normally...
did it get aborted or did it fail to execute?'

I can see that you may not wish to execute your code if the previous code ended abonrmally, this test does'nt
help it that decision. It does tell if you 'could' execute your code.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 16, 2018, 09:50:46 AM
I'm not talking about separate scripts, but rather a single M-script and code within it. There are 2 ways this can work out:

1. M6 gets called by either MDI or G-code and nothing interrupts it. The execution starts at the top of the script and ends at the bottom, with nothing left out in between.

2. M6 gets called by either MDI or G-code but the machine is stopped or disabled halfway through by the operator. The execution starts at the top, YET STILL ENDS AT THE BOTTOM, since Mach actually doesn't stop executing until the whole thing has been gone through. AND, G-code calls won't do anything, because they actually seem to check if the machine is enabled and not stopped. This means that some things will be left out, yet others (like signal changes) won't be. This is an obvious problem since no-one wants to have a script execute only partially with some things arbitrarily left out.

What I wanted to do was simply make everything else in my M6 script also check if the machine was enabled and not stopped, so after the latter, nothing inside M6 would actually be executed. I'm sorry if I wasn't clear on this. Your solution is still appliccable, though.
Title: Re: Lua script detect when the cycle is running
Post by: DazTheGas on February 16, 2018, 01:20:31 PM
May I suggest that you actualy post your m6 code, its very hard to give advice with only partly knowing what you are doing, you never know there may be a completely different solution to what you need.

DazTheGas
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 16, 2018, 02:10:47 PM
https://pastebin.com/QcUSfu7E

Here you go. This one still has a lot of print() uses instead of mc.mcCntlSetLastError(), shouldn't really matter though.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 16, 2018, 02:12:17 PM
Hi,
I'm with Daz and am unsure that I understand the problem you are describing.

Quote
but the machine is stopped or disabled halfway through by the operator. The execution starts at the top, YET STILL ENDS AT THE BOTTOM, since Mach actually doesn't stop executing until the whole thing has been gone through.

I'm not sure about this....surely the M6 starts at the top but the code stops at the point that you disable or stop it? The only way I can think that the code would continue
to execute but not actually physically move would be if the motors/servos were disabled while Mach remained enabled and therefore carried on executing?.

You may have noted a current and fairly long running thread where a guy wanted an 'Offline' button on his machine. The solution was to disable the physical motion of
the servos while allowing normal operation of Mach. When the machine is to be re-instated it is necessary to apply a machine coordinate correction so the machines
referencing remains consistant. Eventually I got the code to work pretty well, regrettably the OP is being rather obtuse and refuses to follow the steps required to get it
to work on his machine but it works fine here.

With the solution I proposed for his "Offline' button the servos stopped motion but if a signal changed state as a result of Mach's continued execution while the servos
are offline that could cause problems. Is this the concern you have?

Craig
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 16, 2018, 02:20:01 PM
It doesn't stop. Maybe I've made a rookie mistake somewhere along the line though, that causes it to not stop properly.

Nevertheless, I've tested it, and you can too. Try this M-script. if you press either disable or stop while G4 is delaying (any other G-codes that take up time also work), you still see the prints near the end.

function m401()
    local inst = mc.mcGetInstance()
    print("starting")
    mc.mcCntlGcodeExecuteWait(inst,"G4 P3")
    local mcState,rc=mc.mcCntlGetState(inst)
    if (mcState==mc.MC_STATE_IDLE) then
        print("IDLE")
    else
        print("ELSE")
    end
    print("end")    
end
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 16, 2018, 02:42:21 PM
Hi,
I had to modify your script slightly to get it to run, my installation wont do anything useful with 'print()'
Also your  G4 P3 statement is interpreted by my machine as 'pause for 3 milliseconds', if you put a decimal point in the P parameter it is interpreted as seconds,
as you see I changed mine to P10.0.

Code: [Select]
function m401()
    local inst = mc.mcGetInstance()
    mc.mcCntlSetLastError(inst,"starting")
    mc.mcCntlGcodeExecuteWait(inst,"G4 P10.0")
    local mcState,rc=mc.mcCntlGetState(inst)
    if (mcState==mc.MC_STATE_IDLE) then
        mc.mcCntlSetLastError(inst,"IDLE")
    else
        mc.mcCntlSetLastError(inst,"ELSE")
    end
    mc.mcCntlSetLastError(inst,"end")   
end
if (mc.mcInEditor()==1) then
    m401()
end
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 16, 2018, 02:54:38 PM
Hi,
whoops posted before I'd actually finished. The code runs fine.
If I leave it to time out its delay it completes with the 'end' message and if I look at the error log it is preceeded with 'else' as it should be. Note that because
m401 is running the control can't be Idle, we happen to know that its busy running our script!
If however I either <Stop> or <Disable> m401 while the rather lengthy pause it running the script end and prints 'end' but doesn't print the 'else' which would
ordinarily preceed it. That is to say it skipped over the mc.mcCntlGetState() and the if-then-else-end code between the point at which I <stop> and the scripts
endpoint. Once the endpoint is reached m401 releases control and control reverts to the state which preceeded the m401 call namely Idle.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 16, 2018, 03:03:21 PM
Hi,
I owe you an apology I misinterpreted what I saw.
When I <stop> the code while the delay is timing the error log shows that CycleStopped has been issued but then Lua is stuck in limbo and it carries on from
the point that it stopped, and you note that now because of the CycleStop the control state is IDLE, then it reaches the end.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 16, 2018, 03:04:26 PM
Now, is it clear what the problem is? Prints happening like that are harmless. However, if you were to have a call to change a signal there instead, say for releasing a tool from the spindle, it becomes quite dangerous, doesn't it?
Checking if the machine hasn't been stopped each time I need a signal switched would solve the issue, and something to check for that is what I requested assistance with at the beginning.

FYI, I'm running Mach4 version 4.2.0.2872.
Title: Re: Lua script detect when the cycle is running
Post by: joeaverage on February 16, 2018, 03:17:04 PM
Hi,
that can be done.

Note that the one thing which determines if your M6 has been stopped or the machine disabled is the state of the control. If the m6 is progressing normally
the control state is busy and you wish to leave it alone. If however it has been stopped then the control state would be Idle and you wish to RETURN.

How about this:

if (mc.mcCntlGetState(inst)==mc.MC_STATE_IDLE) then return end

So if the control is in Idle state, and we know it shouldn't be if every thing is normal, then cause the macro to return immediately.

Craig
Title: Re: Lua script detect when the cycle is running
Post by: MrPuhur on February 18, 2018, 12:59:37 PM
Thank you for your time. Here's what I ended up doing:

A function to ask if the machine hasn't been disabled or stopped, used each time there is a signal change or any other physical or Mach-related change, except some specific cases, more on them later.

Code: [Select]
function toolchange_machine_enabled()
    local inst = mc.mcGetInstance()
    local mcState = mc.mcCntlGetState(inst)
    if mcState==mc.MC_STATE_IDLE then
        return false
    else
        return true
    end
end

An example of its usage:

Code: [Select]
function toolchange_boringhead_motorOFF()
    if toolchange_machine_enabled()==true then
        local inst = mc.mcGetInstance()
        mc.mcSignalSetState(mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT4), false)
    end
end

The reason I didn't return out of the script if this function returned false, is that G-code states (like whether G90 or G91 is currently active) get recorded at the beginning of my M6 script, and have to be returned to afterwards. The script is complex enough that is actually has its own G-code safe start line similair to one in a G-code program. This is also the specific case during which I don't check if the machine hasn't been stopped - I need the machine returned to the previous state regardless of what happens in the meantime.

For safety regarding mc.mcCntlGcodeExecuteWait(), I made this function that I replaced every direct call of mc.mcCntlGcodeExecuteWait() with:

Code: [Select]
function toolchange_callGcode(gcode)
    local inst = mc.mcGetInstance()
    local rc = mc.mcCntlGcodeExecuteWait(inst, gcode)
    if rc ~=0 then
        mc.mcCntlEnable(inst, false)
        mc.mcCntlSetLastError(inst, "Something went wrong with executing G-code from within M6. The machine was disabled for safety. Error state: "..rc)
    end
end

Knowing the rest of my code can handle the machine stopping, I stop the machine directly from this function, which also saves me from having to track another error flag.


I also found out that if you call a custom M-script from within another custom M-script, Mach freezes, not taking any G-code anymore, yet not stating that there was an error, jogging also retains its function. Consider I was using Mach4 version 4.2.0.2872, and newer versions may not have this issue.