I explain why the GUI occurs on this post:
http://www.machsupport.com/forum/index.php/topic,36013.msg246649.html#msg246649What you have told the control to do is execute "G91 G31 Z-5 F1000" and wait until it is done. And that is exactly what it is doing.
mc.mcCntlGcodeExecuteWait() really shouldn't be used in a button script. Most of the time, what you want is the plain old mc.mcCntlGcodeExecute() call with multiple lines passed to it. If you find yourself REALLY actually needing to wait on a task, it is better to start the task with a buttons script and "wait" on it to finish in the PLC script. This involves using what is called (in the programming world) a state machine. Typically it is implemented with a global variable that is defined in the screen load script. Call it "Zprobe" or something and set it to zero
Add this to the screen load script:
Zprobe = 0 -- the initial state of the state machine. 0 == not running.
The button script would contain just a small bit of code to start the action:
if (Zprobe == 0) then -- Only start the task is it isn't already running.
Zprobe = 1 -- 1 == start the Z probe.
end
In the PLC scrip, you "watch" Zprobe and act on it accordingly:
controlState = mc.mcCntlGetState(inst) -- what state is the control in?
if ((Zprobe == 1) and (controlState == mc.MC_STATE_IDLE)) then
mc.mcCntlGcodeExecute(inst, "G91 G31 Z-5 F1000") -- start the Z probe. Notice that we don't use the Wait version of this function
--Wait on the machine to NOT be idle. This won't take long at all. But we need to make sure that the control has entered the running state.
while (controlState == mc.MC_STATE_IDLE) do
controlState = mc.mcCntlGetState(inst)
end
Zprobe = 2 -- change the state. 2 == Z probe running.
elseif ((Zprobe == 2) and (controlState == mc.MC_STATE_IDLE)) then
-- the task is done. Record the Z probe pos, if needed, and retract the spindle to
local zMachineProbePos = mc.mcAxisGetProbePos(inst, mc.Z_AXIS, 1); -- Do something with it? I dunno... :)
mc.mcCntlGcodeExecute(inst, "G53 G00 Z0") -- Raise Z to machine pos Z0. Notice that we don't use the Wait version of this function either.
--Wait on the machine to NOT be idle. This won't take long at all. But we need to make sure that the control has entered the running state.
while (controlState == mc.MC_STATE_IDLE) do
controlState = mc.mcCntlGetState(inst)
end
Zprobe = 3 -- change the state. 3 == Z retracting.
elseif ((Zprobe == 2) and (controlState == mc.MC_STATE_IDLE)) then
-- everything is done. Simply change the state of your state machine.
Zprobe = 0 -- change the state. 0 == not running.
end
In this example, all the button does is set a variable. That is extremely fast and will not "lock" the GUI. Then, the PLC script watches that variable every time it is run and also does things that don't take a long time to do. The tasks are simply "handed off" to the interpreter.
The reason why the GUI locks up on long running tasks is because of the way the Windows Operating System handles the application's event loop. In the C/C++ programming world, we usually get around this by using multiple threads of execution. And the button press event would "launch a thread" to handle the event. But LUA is not multi-threaded, so we just can't do it. LUA has something like threads, called coroutines, which can be used. But coroutines are not preemptive. It is more of a cooperative model and thus harder to use. To me, implementing a state machine in the PLC script is the far easier and more logical/understandable method.
Steve