Hello Guest it is May 07, 2021, 12:46:29 AM

Author Topic: Using modules from Mcodes  (Read 362 times)

0 Members and 1 Guest are viewing this topic.

Using modules from Mcodes
« on: June 03, 2020, 02:38:47 PM »
I know this question has been asked & answered, and I've found those forums posts already -- please read without dismissing, there's a nuance here.

I have a module I've written which connects to a serial device (a small pump).  I wrote button for my screen set to use the module to communicate with the pump, and it works well.  For simplicity, I put the "connect" function of my module in the screen load script.

I also want to be able to turn the pump on & off in m-code macros during movement operations, using the "load_modules.mcs" script which is floating around this forum.  However, when I run the Mcode, the serial port is unavailable -- it's already open in a *separate* lua instance from the screen buttons!  I removed the "connect" function from my screen load script and made a connect/disconnect button on my screen, but the operator will need to remember to disconnect from the pump before running any Gcode w/ macros.

How can I have the Mcode macros and my screen "share" an instance of a module? I can't find any documentation related to passing objets back and forth to macros outside of registers.

How can I make the screen and my macros
Re: Using modules from Mcodes
« Reply #1 on: June 03, 2020, 03:17:42 PM »
Update-  I've discovered from further reading about "coroutines" but it still doesn't seem that a macro can explicitly access the LUA session that the screen uses.
Can I have my module store the serial port object in a register?  Do registers accept lua objects?
Re: Using modules from Mcodes
« Reply #2 on: June 03, 2020, 03:45:19 PM »
M-code just needs to turn the pump on or off? Could have the M-code set an output signal hi/low. In the Sig Lib would be the actual code to turn the pump on/off with your module.
Re: Using modules from Mcodes
« Reply #3 on: June 03, 2020, 04:13:43 PM »
Turning on/off is the most important feature, but setting the rate is important too.
I'm not sure I understand how your suggestion works -- I have the macro update a signal, and the Mach4GUI instance would command it's instance of the module to control the pump?
Re: Using modules from Mcodes
« Reply #4 on: June 03, 2020, 04:31:12 PM »
There are some good resources on the forum about using the signal library in the screen load script. Having the code in there to actually turn the pump on/off would use the GUI instance...the same one you use to open and close the port.

Your M-code would set an unused Mach signal (Output #10 for example), either hi or low. The signal library sees that change and runs whatever function you have in the signal library for "mc.OSIG_OUTPUT10".

To set the rate, the M-code could set a register with your desired rate and also another Mach signal to signify you want to change the rate. The function in your signal library would then get your new desired rate from the register.
Re: Using modules from Mcodes
« Reply #5 on: June 03, 2020, 08:57:16 PM »
That may work.  I will try to dig up some code examples.  Frankly, it seems like setting a status variable and having a timer check it is a hack.

As a side note (puts on computer scientist hat) there really *should* be a way to either have thread-safe ways to pass variables between the two instances (semaphores, locking) or have the same Lua instance run macros and the screen.  I can imagine there's good reasons for keeping the instances separate, but I can easily imagine race conditions arising if we are accessing registers from two separate stacks.

Has anyone thought about a way to do this robustly?  I know realtime actions like GCode execution probably need some sort of thread safety but I do think we should be able to access Mach4 Screen variables from macros.
Re: Using modules from Mcodes
« Reply #6 on: June 04, 2020, 04:43:29 PM »
Has anyone ever implemented a solution like this:

A macro which loads an instance of a module, but checks to see if that module is already loaded by the screen/GUI -- if it is, cleanly unload it (close the serial port, in this case)?

That way, the serial port isn't being passed around or used exclusively by one Lua Instance (screen or macro), but being used on by the Lua runtime which is relevant to the call at the moment
Re: Using modules from Mcodes
« Reply #7 on: July 22, 2020, 08:30:14 PM »
I fixed this problem, albeit in a work-around way.

I wrote a module which has functions to open the serial communication to the device (a syringe pump), close the serial port, and print any commands relevant to me to the serial port.
It turned out that, while not the cleanest implementation, opening and closing the serial port for each and every command string sent was pretty fast; not noticeably slower than opening the serial port once at load time.  I'd imagine this approach can prevent hang-ups if the socket gets broken or something, which is a side-benefit.

The screen loads the module with this code in the screen load script:

package.path = package.path .. ";./Modules/?.lua;"
package.cpath = package.cpath .. ";./Modules/?.dll;"
package.loaded.SyringePump = nil
sp=require "SyringePump"

And I used the following lines at the start of my macro to get the module loaded for the separate Lua instance that runs for macros:

package.path = package.path .. ";./Modules/?.lua;"
package.cpath = package.cpath .. ";./Modules/?.dll;"
sp=require "SyringePump"

In this way, all the commands in my module are available for both the screen and MCodes. 

Again, it's not a very clean implementation -- the serial object could have conflicts if the screen and a macro try to open it at the same time --  but it's code-efficient (the functions live in one file) and it works fairly robustly. What I wouldn't give for some semaphores, or, a single Lua instance, or god forbid some thread-safe implementation of Mach4 :-D

Hope someone finds this useful!
« Last Edit: July 22, 2020, 08:33:41 PM by jm1937 »