Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: Dan13 on May 25, 2015, 06:37:04 AM

Title: Mach4 Executing Gcode from LUA
Post by: Dan13 on May 25, 2015, 06:37:04 AM
Trying to execute Gcode from LUA. This script works fine:

local inst = mc.mcGetInstance()
mc.mcCntlGcodeExecute(inst, "G0 X10 Y10\n")

However, with the below function, the numbers in the DROs do not continuously update, but only when the final destination is reached.

local inst = mc.mcGetInstance()
mc.mcCntlGcodeExecuteWait(inst, "G0 X10 Y10\n")

When trying to execute two line of Gcode, like below, the DROs again don't update continously, but only when the final point is reached.

local inst = mc.mcGetInstance()
mc.mcCntlGcodeExecute(inst, "G0 X10 Y10\n")
mc.mcCntlGcodeExecute(inst, "G0 X5 Y5\n")

What is the correct way to programm in order for the DROs to continuously update?

Dan



Title: Re: Mach4 Executing Gcode from LUA
Post by: poppabear on May 25, 2015, 08:57:24 AM
Dan, I suspect that the thing your seeing is internal to Mach4 and how it is dealing with that call.
Submit your finding to Steve in the bug report.

Scott
Title: Re: Mach4 Executing Gcode from LUA
Post by: Dan13 on May 25, 2015, 09:06:36 AM
Is the bug report thread being monitored by Steve?

Dan
Title: Re: Mach4 Executing Gcode from LUA
Post by: poppabear on May 25, 2015, 09:57:04 AM
Your guess is as good as mine
Title: Re: Mach4 Executing Gcode from LUA
Post by: smurph on May 29, 2015, 12:55:45 AM
This isn't a bug. 

mc.mcCntlGcodeExecuteWait() should not be used in a button script if you want the screen to refresh.  When you press a button, the button event is run.  If that button event takes 15 seconds total time, the screen will not refresh for that time.  mc.mcCntlGcodeExecuteWait() does what it implies.  It waits for the given code to be executed.  Meanwhile your button event has not returned and the GUI is frozen.  It is more suited for M code scripts.

mc.mcCntlGcodeExecute() is good for button scripts.  It executes the given G code in a unit of work.  It drops the code off to the interpreter and does <B>NOT</B> wait.  However, It is not meant to be called block by block.  Two consecutive calls to mc.mcCntlGcodeExecute() will act like mc.mcCntlGcodeExecuteWait() because the second call can't be submitted until the first one is done.  If multiple lines/blocks are needed, then they should be concatenated into one single line separated with \n (newline) characters.

local inst = mc.mcGetInstance()
mc.mcCntlGcodeExecute(inst, "G0 X10 Y10\nG0 X5 Y5\n")

Is proper for your last example and your DRO will update.
Title: Re: Mach4 Executing Gcode from LUA
Post by: Screwie Louie on May 29, 2015, 01:29:31 AM
Perfect! That would of been nice to know in the scripting manual. Sticky!

So, as the event is a 'run' any input signal during that run does not count as an 'event'. Which would trigger a function through the signal script to a defined signal table located in the screen load up script.

But yet the mc.mcCntlGcodeExecute(inst, "string") or mc.mcCntlMdiExecute(inst, "string") are loaded into and executed by the interpreter and the movements are passed back to the DRO code and then returned to the GUI for update via the core? ...in the dro mystery code location?...even if the dro code is written to collect interpreter data and pass that data as arguments to a dro function with a return to the GUI wouldn't my signal 'event' be just as important?

why wouldn't my input Event be passed from the signal script,  to the screen load up script,  to a defined table in the screen load up script with a key of that known input and perform a function (as the key's value) and tell the interpreter to stop? It works when jogging and when a Gcode file is loaded and running.

I would really appreciate your advice. Thanx. (didn't mean to hijack a thread, but shoot it is a legitimate programming question)

Why wouldn't this type of information be written into the Mach4 scripting manual (the GcodeExecute vs. Wait vs. Mdi) to know which type of function call is applicable in which specific environment? Thank you for sharing. I know there are other posts describing this...from 2014. Daniel referenced them a couple of days ago.
Title: Re: Mach4 Executing Gcode from LUA
Post by: smurph on May 29, 2015, 02:06:41 AM
I was speaking of GUI events.  Button presses, menu selection, etc...  Windows has an event loop.  The application updates it's controls with the very same event loop.  Signal events are external.

The MDI and GcodeExec functions load the G code into the interpreters and run it.  The movement happens at the motion controller and the motion controller updates the core with it's positions.  These positions are immediately sent to the Mach 4 screen.  If there were no long running button event, the screen would update within milliseconds.  There is no mystery location.  Each DRO has a list of what it is to control/display.  The values can be accessed with the scr.* LUA functions if you are wanting to track them.  I have never had a need to though.

I have no idea why a signal script would pass info to a screen load script.  The load script is loaded upon initial display of the screen.  Functions in the load script can be called if they are included in the load script.  But make no mistake, the load script is only actually run once.  It sounds like you need to use the PLC/signal scripts to me.  That is what should be used to process and input event.

One thing I have noticed is that there are a lot of fancy code snippets floating around for the LUA scripts.  And that is all great and wonderful.  But sometimes simple brute force code is best and in the end, more readable.  I'm not a LUA expert by any means, so I tend to keep it simple.

Signal script.  In the example, Input #1 is tied to a stop button on the panel.  If the machine is running, this will stop it just like hitting the stop button on the screen.  Input #2 is tied to a Start button.
Code: [Select]
    local inst = mc.mcGetInstance();
   
    if (sig == mc.ISIG_INPUT1) then
        if (state == 1) then
            mc.mcCntlCycleStop(inst);
        end
    end
    if (sig == mc.ISIG_INPUT2) then
        if (state == 1) then
            mc.mcCntlCycleStart(inst);
        end
    end

It is not elegant or fancy.  But it is damned effective. 

It is important to note that the signal script only gets called when a signal is changed.  So holding down the stop button will not continually call mcCntlCycleStop().  The signal changes state from low to high once when you press the button (the signal script is then called with state set to 1) and then from high to low when you let off the button (and the signal script is called again with state set to 0).

I didn't write the scripting manual.  So I really can answer that!  I'm sure it is a work in progress. 

Steve
Title: Re: Mach4 Executing Gcode from LUA
Post by: Dan13 on May 29, 2015, 02:23:16 AM
Thanks for explaining this Steve. So I get it that if I had several lines of Gcode I wanted to execute I'd have to concatenate them as a string like in the examples? 

Dan
Title: Re: Mach4 Executing Gcode from LUA
Post by: simpson36 on May 29, 2015, 07:29:03 AM
This topic has already been reported and discussed in the 'Bug Report' thread, and a bit of research turned up that the proper use of this function is actually documented. Specifically [emphasis added]:

"If the control is in the idle state, this function will execute the G code in MDI mode.

It is important to note that this function does not wait for the G code to complete. It is an error to execute G code with this function one line after another. Instead, the lines should be combined into one string separeated with newline characters (\n)."


It's hard to say whether the code is executed in the MDI as indicated, but there is an explicit function to execute in the MDI, so that's an alternative to try. I have used it in buttons and elsewhere and it works fine.

An important part of the usage statement is does not wait for the G code to complete. and this is the case with either Gcode Execute or MDI execute. It is unclear to me why one would use one method over the other, but in either case, users should make sure to add wait states if needed so that the move completes before subsequent actions take place.


Title: Re: Mach4 Executing Gcode from LUA
Post by: dude1 on May 29, 2015, 07:36:32 AM
by smurph don't for get to give credit
Title: Re: Mach4 Executing Gcode from LUA
Post by: Screwie Louie on June 02, 2015, 01:23:16 AM
Hi Dan,

Are you good now? I feel like a di@I( head asking a question on top of yours. I got some things working pretty good if your're stuck. Hope all's well.

-josh
Title: Re: Mach4 Executing Gcode from LUA
Post by: Dan13 on June 02, 2015, 05:14:51 AM
I will be writing a macro for probing, so will see if I manage it OK.

Dan
Title: Re: Mach4 Executing Gcode from LUA
Post by: abarry54 on July 01, 2015, 02:20:52 PM
Have any of you run into problems when trying to call a custom M command through this method? I can get it to run regular gcode but the moment I put in say M10 (just activates an output signal) m4 locks up. I wonder if it is because of using a function within my new function..?

The code I am using looks like:
Code: [Select]
function m31() --  Load New Board
    local state, rc = mc.mcSignalGetState(mc.mcSignalGetHandle(0, mc.ISIG_INPUT3)) -- obtain loader signal state
    local inst = mc.mcGetInstance()
    if (state == 1) -- Check States for Board Loader Signal
        then
           --mc.mcCntlMdiExecute(inst, 'M12') -- used for testing (works for a button), freezes upon use
           mc.mcCntlGcodeExecute(inst, 'G00 X1700\nM10\nG00 X0\n') --goes to 1700, then freezes
        else
          -- do nothing
    end
end

m31();

if (mc.mcInEditor() == 1) then
    m31();
end

Any insight is greatly appreciated!
Title: Re: Mach4 Executing Gcode from LUA
Post by: Screwie Louie on July 01, 2015, 02:36:29 PM
try using:

if state == 1 then mc.mcScriptExecute (inst, "m12.mcs", 0) end
Title: Re: Mach4 Executing Gcode from LUA
Post by: smurph on July 01, 2015, 02:55:51 PM
For macro scripts (not screen or buttons scripts), The M code functions are available in the calling M code.

if state == 1 then
  m12();
end

Steve
Title: Re: Mach4 Executing Gcode from LUA
Post by: abarry54 on July 01, 2015, 03:06:42 PM
Thanks! Calling the m12() worked smurph (should have guessed that would work  :-[), the execute script function still crashed m4 unfortunately louie, not sure what exactly is the reason.

Is there a cleaner way of piecing together my code aside from:

Code: [Select]
if (state == 1)-- Check States for Board Loader
        then
            mc.mcCntlGcodeExecute(inst, 'G00 X1700.');
            m12();
            mc.mcCntlGcodeExecute(inst, 'G00 X0.');
    end

That code works totally fine, just seems clunky, especially when I have much longer macros planned  :D