Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: beezerlm on September 26, 2016, 08:14:44 PM

Title: Macro - Pause until input triggered
Post by: beezerlm on September 26, 2016, 08:14:44 PM
Is there a simple way to pause motion until an input is triggered within a macro? 

I would like to ensure my Z axis returns home before the macro ends because after the macro would be an X-Y move. This is a cylinder where I have output 1 activate the "up" direction and output 0 activate the "down" direction. 

Something like this:

1. activate output_1 (up)
2. wait for Z home switch to trigger
3. end macro.

What is the best way to code step 2 (wait for input) in a Macro?
Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 27, 2016, 02:40:49 AM
Take a look at the api docs for mcSignalWait located in the mach4 docs directory.

DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 27, 2016, 11:09:54 AM
Thanks.  I gave it a try by adding it to the end of the macro.  For some reason it does not wait for the "Z home" signal before moving on to the next line of the Gcode program ( a G0 X/Y axis positioning move ).   I also tried WAIT_MODE_LOW and it did the same thing.  I was hoping the machine would stop all movement until the Z axis reached the home position. Any Ideas what I am doing wrong?

Code: [Select]
function M100()
   
    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
    local z_home_sig = mc.mcSignalGetHandle(inst, mc.OSIG_ZHOME) -- Get handle for Z axis home switch
   

    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then                   --If input_20_State equals 1, then the signal is active.
            wx.wxMessageBox("Signal is already active!")

        else                                                   --If input_20_State does not equal 1, then the signal is inactive.

            mc.mcSignalSetState(input_20, 1)
            mc.mcSignalWait(inst, z_home_sig, WAIT_MODE_HIGH, 20)   

        end
    end
end

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

Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 27, 2016, 11:32:59 AM
Your trying to wait for a signal handle not a signal id like mc.OSIG_ZHOME

Try something like this but signal should be the INPUT of your Z Home

Code: [Select]
mc.mcSignalWait(inst, mc.ISIG_MOTOR0_PLUS, WAIT_MODE_HIGH, 20)
DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 27, 2016, 11:59:15 AM
Hmmm....I changed the signal to "mc.ISIG_MOTOR3_HOME"  which is mapped to the Z axis home switch and it still just moves on to the next line in the main G-code program?



Code: [Select]

function M100()
    
    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
    local z_home_sig = mc.ISIG_MOTOR3_HOME -- Get signal for Z axis home switch
  


    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then        
            wx.wxMessageBox("Signal is already active!")

        else    --If input_20_State does not equal 1, then the signal is inactive.
          
            mc.mcSignalSetState(input_20, 1)
            mc.mcSignalWait(inst, z_home_sig, WAIT_MODE_HIGH, 20)    
        end
    end
end

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

Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 27, 2016, 12:54:37 PM
In the default screens of the later dev versions the ref all home buttons run the RefAllHome function as a coroutine. This was modified to provide an example for those interested in doing something similar. It will reference all axis and (only after motion is finished) pop up a message box saying referencing is complete. You may be able to do something similar to get the results your looking for.

Code: [Select]
--Button script
--RefAllHome()
wait = coroutine.create (RefAllHome) --Run the RefAllHome function as a coroutine named wait.

--Screen Load Script
---------------------------------------------------------------
-- Ref All Home() function.
---------------------------------------------------------------
function RefAllHome()
    mc.mcAxisDerefAll(inst)  --Just to turn off all ref leds
    mc.mcAxisHomeAll(inst)
    coroutine.yield() --yield coroutine so we can do the following after motion stops
    ----See ref all home button and plc script for coroutine.create and coroutine.resume
    wx.wxMessageBox('Referencing is complete')
end

--PLC Script
-------------------------------------------------------
--  Coroutine resume
-------------------------------------------------------
if (wait ~= nil) and (machState == 0) then --wait exist and state == idle
local state = coroutine.status(wait) --Get the status of the coroutine named wait
    if state == "suspended" then --Coroutine named wait is suspended
        coroutine.resume(wait) --Resume coroutine named wait
    end
end
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 27, 2016, 02:36:03 PM
Well a gave it a go as and I get a lua error in the macro "Error while running chunk"  it doesn't seem to want to run my function (GrindCycle) in the Screenload script from within the Macro(M100)?

Here is what I have now:

Add to the ScreenLoad script:

Code: [Select]

--My GrindCycle function starts here:
   
function GrindCycle()

    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
   
    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then --If input_20_State equals 1, then grind cycle active signal is High.
            wx.wxMessageBox("Signal is already active!")

        else    --If input_20_State does not equal 1, then the grind cycle signal is inactive.
            mc.mcSignalSetState(input_20, 1) -- set grind cycle signal active
            mc.mcSignalWait(inst, z_home_sig, WAIT_MODE_HIGH, 20) -- wait for z to get home
            coroutine.yield () --yield coroutine so we can do the following after motion stops
            wx.wxMessageBox("Grind Cycle Complete")
        end
    end
end

--My GrindCycle function ends here:


In the M100 macro:

Code: [Select]

function M100()
    wait = coroutine.create (GrindCycle) --Run the GrindCycle function as a coroutine named wait.
end

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


Added to the PLC script:

Code: [Select]

-------------------------------------------------------
--  Coroutine resume
-------------------------------------------------------
if (wait ~= nil) and (machState == 0) then --wait exist and state == idle
local state = coroutine.status(wait) --Get the status of the coroutine named wait
    if state == "suspended" then --Coroutine named wait is suspended
        coroutine.resume(wait) --Resume coroutine named wait
    end
end


Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 27, 2016, 02:58:57 PM
Cant remember of top of my head but think macros and gcode run in a different lua instance than the gui??

DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 27, 2016, 03:24:06 PM
Yup, that is right Daz........ my bad.
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 27, 2016, 04:29:36 PM
Is there a function to inhibit motion?  I looked through the API but didn't see one. If there is, maybe I could inhibit motion somehow until the Z home signal goes high?  The Z would still move home even if all motion is inhibited since it is a pneumatic cylinder and mach4 only controls up/down via output_0 and output_1.
Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 27, 2016, 04:50:31 PM
The only problem I can see is if your home switch is also the limit this could cause mach4 to disable, just as a thought have you thought of using something like mc.mcCntlGcodeExecuteWait(inst, "G0 Z-1 F50") this will halt the gcode.
I have been looking into the mc.mcSignalWait and all works well when using any of the ISIG_INPUT0 to 63 etc but not working on anything else???

DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 09:58:52 AM
Daz - I mapped the Z home signal to Input_21 and I still can't get mc.mcSignalWait to work? The API says to use the signal handle, are you using the handle?  I haven't tried the others yet.

Current M100:

Code: [Select]
function M100()
   
    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
    local z_home_sig = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT21) -- Get handle for Z axis home switch
    --local z_home_sig_state = mc.mcSignalGetState(z_home_sig) --Get state of  signal

    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then --If input_20_State equals 1, then the signal is active.
            wx.wxMessageBox("Signal is already active!")

        else    --If input_20_State does not equal 1, then the signal is inactive.
            --wx.wxMessageBox("Setting input_20 high")
            mc.mcSignalSetState(input_20, 1)
            mc.mcSignalWait(inst, z_home_sig, WAIT_MODE_HIGH, 20)
        end
    end
end

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

Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 10:28:15 AM
I looked at mc.mcCntlGcodeExecuteWait. I don't know how I could use it because the Z axis is not controlled via G-code.
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 10:38:49 AM
I got mcSignalWait to work.  I was wrong API does not say to use handle.  It worked by putting the signal ID.
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 28, 2016, 10:43:48 AM
Was just looking at that myself.

From the manual......
sigId      A valid signal ID. (NOT a signal handle)

Glad you got it sorted.  :)

How about post the code that worked so others will see what right looks like.
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 10:51:52 AM
Here is the code that works:

Code: [Select]

function M100()
    
    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
    local z_home_sig = mc.ISIG_INPUT21 -- Get Signal ID for Z axis home switch
    
    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then --If input_20_State equals 1, then the signal is active.
            wx.wxMessageBox("Signal is already active!")

        else    --If input_20_State does not equal 1, then the signal is inactive.
            --wx.wxMessageBox("Setting input_20 high")
            mc.mcSignalSetState(input_20, 1)
            mc.mcSignalWait(inst, z_home_sig, 1, 0)
        end
    end
end

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

Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 28, 2016, 11:02:34 AM
Nice, thanks!

Does this work as well?

Code: [Select]
function M100()
    
    local inst = mc.mcGetInstance()
    local input_20 = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT20) -- Get handle for input 20
    local input_20_State = mc.mcSignalGetState(input_20) -- Get input 20 state
    
    if input_20 == 0 then
        wx.wxMessageBox("Could not locate signal!")

    else

        if input_20_State == 1 then --If input_20_State equals 1, then the signal is active.
            wx.wxMessageBox("Signal is already active!")

        else    --If input_20_State does not equal 1, then the signal is inactive.
            --wx.wxMessageBox("Setting input_20 high")
            mc.mcSignalSetState(input_20, 1)
   mc.mcSignalWait(inst, mc.ISIG_INPUT21, 1, 0)
        end
    end
end

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

Also, just wondering what this is.........  mc.mcSignalSetState(input_20, 1)

Shouldn't that be turning on an output to fire the raise solenoid?
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 11:22:56 AM
Actually I am using input 20 as a "In automatic Cycle" signal. The M100 is interacting with the PLC script to monitor the Z-axis encoder and change direction when necessary.  I am still working on the Z axis reciprocation and automatic grinding cycle part at the moment, but as of now, yes the input 20 is setting the output_1 high in the PLC script which sends the Z axis home.

Yes your sample works also.
Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 28, 2016, 11:51:21 AM
yay you lot have been busy, glad its working for you now.

DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 28, 2016, 11:55:11 AM
Is there a simple way to pause motion until an input is triggered within a macro?  

I would like to ensure my Z axis returns home before the macro ends because after the macro would be an X-Y move. This is a cylinder where I have output 1 activate the "up" direction and output 0 activate the "down" direction.  

Something like this:

1. activate output_1 (up)
2. wait for Z home switch to trigger
3. end macro.

What is the best way to code step 2 (wait for input) in a Macro?

Good, thanks for testing!

This does not do any error checking and the time it waits for the input to go high is indefinite (neither of which are very good ideas) and it does not take your "In automatic Cycle" into account but it should be all that is needed to do what you were looking for originally.

Also note the 2 M100's were changed to m100 so should be saved as m100.mcs. Early on their was some debate about whether or not M codes should be upper or lower case in the scripts themselves. The answer is lower case. It should prevent some possible issues in non Windows OS's.

I would also delete any other M100 files (M100.mcs, M100.mcc, M100.bak) each time you edit the macro and before testing. If not, your changes may not take effect until you do.

Code: [Select]
function m100()
    
    local inst, hSig
    inst = mc.mcGetInstance()
    hSig = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- Get handle for output 1
    
    mc.mcSignalSetState(hSig, 1) --turn on output 1
    mc.mcSignalWait(inst, mc.ISIG_INPUT21, 1, 0) --Wait indefinitely (0) for input 21 to become active
  
end

if (mc.mcInEditor() == 1) then
    m100()
end
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 28, 2016, 12:02:58 PM
yay you lot have been busy, glad its working for you now.

DazTheGas

Thanks Daz!

I have not had a use for the mc.mcSignalWait API call yet so hadn't used it beofre but bet I will find a use for it real soon now. :)

Love it when a plan comes together! The devil is in the details. Thankfully the details are covered pretty good in the help file.
Title: Re: Macro - Pause until input triggered
Post by: beezerlm on September 28, 2016, 12:56:30 PM
Quote
This does not do any error checking and the time it waits for the input to go high is indefinite (neither of which are very good ideas) and it does not take your "In automatic Cycle" into account but it should be all that is needed to do what you were looking for originally.

Could you recommend the proper error checking for this? I have been neglecting that too much while focusing on getting the code to work.
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 28, 2016, 03:09:55 PM
This should work. I changed the time to 5 seconds but you can adjust as needed.

Note, I have it putting the first checks in a MessageBox, the last 2 checks write them to the status bar or message bar in Mach. All of them write a message even if there is no error (MERROR_NOERROR).

Code: [Select]
function m100()

local inst, hSig, rc
inst = mc.mcGetInstance()
hSig, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- Get handle for output 1

if (rc == mc.MERROR_NOERROR) then
wx.wxMessageBox("MERROR_NOERROR")
elseif (rc == mc.MERROR_INVALID_INSTANCE) then
wx.wxMessageBox("MERROR_INVALID_INSTANCE")
elseif (rc == mc.MERROR_SIGNAL_NOT_FOUND) then
wx.wxMessageBox("MERROR_SIGNAL_NOT_FOUND")
end

rc = mc.mcSignalSetState(hSig, 1) --turn on output 1

if (rc == mc.MERROR_NOERROR) then
mc.mcCntlSetLastError(inst, "MERROR_NOERROR")
elseif (rc == mc.MERROR_INVALID_ARG) then
mc.mcCntlSetLastError(inst, "MERROR_INVALID_ARG")
end

rc = mc.mcSignalWait(inst, mc.ISIG_INPUT21, 1, 5) --Wait 5 seconds for input 21 to become active

if (rc == mc.MERROR_NOERROR) then
mc.mcCntlSetLastError(inst, "MERROR_NOERROR")
elseif (rc == mc.MERROR_INVALID_INSTANCE) then
mc.mcCntlSetLastError(inst, "MERROR_INVALID_INSTANCE")
elseif (rc == mc.MERROR_INVALID_ARG) then
mc.mcCntlSetLastError(inst, "MERROR_INVALID_ARG")
elseif (rc == mc.MERROR_NOT_ENABLED) then
mc.mcCntlSetLastError(inst, "MERROR_NOT_ENABLED")
elseif (rc == mc.MERROR_TIMED_OUT) then
mc.mcCntlSetLastError(inst, "MERROR_TIMED_OUT")
end
end

if (mc.mcInEditor() == 1) then
    m100()
end
Title: Re: Macro - Pause until input triggered
Post by: joeaverage on September 29, 2016, 02:14:12 AM
Hi Guys,

reading Robs post and I saw:

if (rc == mc.MERROR_NOERROR) then
      wx.wxMessageBox("MERROR_NOERROR")

I have been writing code similar to:

if(rc==0)then
                wx.wxMessageBo("MERROR_NOERROR")
 
ie I've been testing the numeric value of rc against a list provided by DTG but
this suggests that mc.MERROR_NOERROR is a defined quantity. Is this correct?

If so 'gotta luv C'

Craig

Title: Re: Macro - Pause until input triggered
Post by: DazTheGas on September 29, 2016, 03:14:27 AM
That is correct, 0 is the same as mc.MERROR_NOERROR just like in the command 1 is the same as mc.WAIT_MODE_HIGH, these have been defined in C but can be accessed by the leading mc.

DazTheGas
Title: Re: Macro - Pause until input triggered
Post by: Chaoticone on September 30, 2016, 04:32:40 PM
I am going to look at adding an error check module and the necessary bits to make it work in the default profiles. I have done it and tested it already and got it all working with some help from DTG. I had a very simple mistake and just kept overlooking it.  :-[  Garbage in is garbage out and I'm not immune from giving it some garbage myself. I think most when they start out coding have those moments when they want to kick their own butt. Happens to us all I think so remember that when your ready to give up.

Anyway, the m100 discussed earlier in this topic would like this after its all done. I like this much better..........

Code: [Select]
function m100()

local inst, hSig, rc
inst = mc.mcGetInstance()

hSig, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- Get handle for output 1
if (rc~= 0) then --Check our errors
mc.mcCntlSetLastError(inst, (mcErrorCheck[rc]))
                --wx.wxMessageBox(mcErrorCheck[rc]) --popup a message box with the error
end

rc = mc.mcSignalSetState(hSig, 1) --turn on output 1
if (rc~= 0) then --Check our errors
mc.mcCntlSetLastError(inst, (mcErrorCheck[rc]))
end

rc = mc.mcSignalWait(inst, mc.ISIG_INPUT21, 1, 5) --Wait 5 seconds for input 21 to become active
if (rc~= 0) then mc.mcCntlSetLastError(inst, (mcErrorCheck[rc])) end --In line check our errors works too

end

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

Title: Re: Macro - Pause until input triggered
Post by: beezerlm on October 01, 2016, 10:13:23 AM
Yes that looks nice and clean.