Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: Raymondo on August 16, 2019, 05:20:41 AM

Title: Lua script problems
Post by: Raymondo on August 16, 2019, 05:20:41 AM
I am using a wirless transmitter to turn on and off the dust exreaction system I need it to turn on the output 50 for about half a second then turn it off  then the same again to stop the dust extraction so I need a pulse on output50
I use a delay function calles wait in MC6 tool changer and though I could call that from here but no if I include the wait function in this code I get the same error even if I call it some thing different it still has the same error
This is the error

C:\Mach4Hobby\ZeroBraneStudio\bin\lua53.exe: C:\Users\Raymondo\AppData\Local\Temp\leA8EB.mcs:14: attempt to call a nil value (global 'wait')
stack traceback:
   C:\Users\Raymondo\AppData\Local\Temp\leA8EB.mcs:14: in main chunk

Here is the script

-- Dust Collector button script
-- M110/M111 Output 50 signal 1100
inst = mc.mcGetInstance()

local hSig, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT50)
 
    mc.mcSignalSetState(hSig, 1)

 wait(1)
     mc.mcSignalSetState(hSig, 0)

And I added this  with or without it it is the same but this in in MC6 and works fine in MC6

function wait(seconds)
  local start = os.time()
  repeat until os.time() > start + seconds
end

 
any idea I just need about .3 to .5 seconds delay between turning  on output50 and turning it off
regards Ray
Title: Re: Lua script problems
Post by: KatzYaakov on August 16, 2019, 11:56:26 AM
in the new version you cant use same function name in 2 M function
or use public main or change the name in each M function
Title: Re: Lua script problems
Post by: smurph on August 16, 2019, 12:48:18 PM
wait(1) is the main problem.  At least that is what the error log said.  In order to use it, it must be defined ABOVE the code from which you want to call it.  It looks like you were nesting that wait function inside another function?  Possibly the m110() function? 

This should work:
Code: [Select]
-- Dust Collector button script
-- M110/M111 Output 50 signal 1100

function wait(seconds)
  local start = os.time()
  repeat until os.time() > start + seconds
end

function m110()
    inst = mc.mcGetInstance()
    local hSig, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT50)
 
    mc.mcSignalSetState(hSig, 1)
   
    wait(1)
    mc.mcSignalSetState(hSig, 0)
end --end function m110

Also, you may run into a even more hard to deal with problem if several macro scripts define a wait() function.  Only the LAST loaded wait() function will be used!  Now which one will it be?  The answer is "You don't know!"

The best way to use common functions that are available to ALL macro scripts is by using modules. 

But you don't even need to define the wait() function or use modules for this.  Fortunately, we have LUA with wxWidgets bindings and you can use its' wx.wxMilliSleep() function.  If you want to wait 1 second, then do wx.wxMilliSleep(1000).  Half a second is 500, etc...

Steve
Title: Re: Lua script problems
Post by: Raymondo on August 16, 2019, 11:40:35 PM
Thank you
the wx.wxMilliSleep() command did ever thing I wanted and I now have it running perfect again
I was using the wait function and it was nested inside another function M6.mcs  but I will alter that get rid of the wait function and use wx.wxMilliSleep() instead
Thanks again for the help you guys are the legends
Regards Ray
Title: Re: Lua script problems
Post by: Eveider on November 04, 2022, 04:10:32 AM
hi there

I almost have the same problem but mine seems to be worst
I am trying to get a the delay working in the signal script and up to now i have not succeeded.
as soon as i saw the wait function i wen ahead and used it but right after that i got an error.
i also tried using the wx.wxMilliSecond(), but it forces me to shut down the Mach 4

here is script with the picture of the error

local inst = mc.mcGetInstance()
local hsig = mc.mcSignalGetHandle(inst,mc.ISIG_INPUT1)
local ISigFDBK = mc.mcSignalGetState(hsig)

local hsignal = mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT5)
local OSigFDBK = mc.mcSignalGetState(hsignal)

local hsignale = mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT6)
local OSigFDBKs = mc.mcSignalGetState(hsignale)

-- delay function

function wait(seconds)
  local start = os.time()
  repeat until os.time() > start + seconds
end

-- turning on output five, wait for 5 seconds then turn on 6 or turn all off

if (ISigFDBK == 1)then
   mc.mcSignalSetState(hsignal,1)
    wait(5)
   mc.mcSignalSetState(hsignale,1)   
 else
   mc.mcSignalSetState(hsignal,0)
   mc.mcSignalSetState(hsignale,0)
end
Title: Re: Lua script problems
Post by: KatzYaakov on November 04, 2022, 04:17:20 AM
It's old issues here you can search on history
Solution
G04
Title: Re: Lua script problems
Post by: Eveider on November 04, 2022, 07:48:11 AM
Hi KATZYAAKOV

i am not sure i understand what to do please assist me
Title: Re: Lua script problems
Post by: Stuart on November 04, 2022, 08:39:58 AM
many years ago before the WWW and internet was thought about, I built a computer based on a Zilog z80 from scratch , the only was to get help was by post to the club HQ all I got back was a note "read the programming manual supplied "( note this was machine code pre dating assembler ) I thought what the heck and did read the manual and learnt how to program .
there is a LUA manual supplied with Mach 4 I would advise you to read it then read it again it will help you to sort it out
Title: Re: Lua script problems
Post by: smurph on November 04, 2022, 03:55:22 PM
hi there

I almost have the same problem but mine seems to be worst
I am trying to get a the delay working in the signal script and up to now i have not succeeded.
as soon as i saw the wait function i wen ahead and used it but right after that i got an error.
i also tried using the wx.wxMilliSecond(), but it forces me to shut down the Mach 4

wx.wxMilliSleep(), not wx.wxMilliSecond(). 

Anyway, waiting 5 seconds in a script that is supposed to take nanoseconds to execute is GOING to cause problems.  The signal script is processed from a GUI messaging event.  The Windows GUI has ONE event queue.  So a signal changes in the core and that fires one event to the GUI.  Just like pressing a button sends a "clicked" event to the GUI.  Well, while your signal event is waiting for 5 seconds, no other event is processed.  This means no DROs get updated, no buttons will work on the screen, and the whole GUI just seems frozen.  So even if your script didn't produce an error, it would have not worked well. 

So what to do to solve the problem?  Well, there are several ways to solve the issue gracefully.  You can split the process up and let the PLC script count down and fire the second output signal signal (OSIG_OUTPUT6).  This is the old school multi thread model.  It is probably the most flexible but also the hardest to implement and really not needed for your application but I thought I would share it in case you or others may find it useful in the future:

1. Create a global flag variable and a global counter variable in the screen load script.
2. Set this global flag variable and initialize the counter variable In the signal script when ISIG_INPUT1 drives OSIG_OUTPUT5 high in the signal script.
3. In the PLC script, look for this flag and if it is set, start decrementing the counter variable by the refresh time of the screen (default of 50 milliseconds).
4. When the counter variable reaches zero, fire the OSIG_OUTPUT6 signal. 

Next, there is the PMC.  A simple PMC object can do this with a single rung.  Attached are the sample PMC file and screen shot.  You just have to change the output to match your system as the ones I used were from the Sim plugin.  It is dead nuts simple and probably my favorite way of handling these logic oriented tasks. 

And finally, there are the screen timer objects.  Drop one on the screen, set the properties according to the attached screen shot (enabled all states, 5000ms, oneshot, and the name property to 'tmrOutput6Delay'), switch to the timer control's event properties and provide an event scrip[t that turns on your Output6, and modify your signal script to the following:
Code: [Select]
if (ISigFDBK == 1)then
    mc.mcSignalSetState(hsignal,1)
    scr.SetProperty('tmrOutput6Delay', 'Command', 'START'); -- start the one shot timer.
else
    mc.mcSignalSetState(hsignal,0)
    mc.mcSignalSetState(hsignale,0)
end

But again, I like the PMC method the best. 

Steve