Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: thespindoctor on December 18, 2016, 09:54:39 PM

Title: Understanding Lua
Post by: thespindoctor on December 18, 2016, 09:54:39 PM
i note in the screen for probing for  Measure Z that Prb.SingleSurfZ  is the function called but in
the probing module it is called Probing.SingleSurfZ     How can that be?

THanks
Keith
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 05:25:38 AM
Prb is a derived class (or module for lua) of Probing.

when requiring a module the module name is replaced by what we tell it, in this case its prb, so although you will see Prb.SingleSurfZ its actually running Probing.SingleSurfZ.

seems weird but look at it this way, lets take a module that creates a button called btnCreate and within that module there is a function btnCreate.createButton(coords etc)

we need 3 buttons so we can do this

local btn1 = require btnCreate
local btn2 = require btnCreate
local btn3 = require btnCreate



btn1.createButton(coords etc)
btn2.createButton(coords etc)
btn3.createButton(coords etc)

so btn1 -2 and 3 becomes derived classes/modules of btnCreate.

DazTheGas
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 07:12:24 AM
Ok, so to call a function in a module from a script, we would be correct for instance to call Probing.SingleSurfZ in the probing module to use mcProbing.SingleSurfZ in a screen button? but here they have used require to switch mcProbing to prb.  

Looking at mcTouchOff.lua module, the functions are named without a probing or Touch prefix.  This is confusing.  function TouchOffZNeg0 would be called from a button script by mcTouchOff.TouchOffZNeg0   Or we could use

local TO = require "mcTouchOff"

then call TO.TouchOffZNeg0 in the script

Is that correct?

Appreciate the help!!

Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 07:16:38 AM
Daz, the module has a name like mcTouchOff.lua    Within the module are functions with names.  In the Probing module they put Probing. in front of every function.  In the mcTouchOff.lua module they just name the functions without a prefix.  What is the proper way to call a function in a module versus calling a function in my own script like load script or plc script.   

Thanks
Keith
Title: Re: Understanding Lua
Post by: Chaoticone on December 19, 2016, 08:41:54 AM
Let me try to help and hopefully Daz will correct any mistakes I make.

The reason mcTouchOff's functions do not have a prefix (mcTouchOff.) is because none of its functions are called or available for use from outside the module. The only one that is, is the Dialog which is called from outside the module. It opens the dialog or user interface. Any other functions are only called form it. Not that the functions could not be used from outside the UI but from a support stand point its not something we wanted to do.

I did this example a few days ago. Its a very simple module that simply pops up a message box and displays the message parameter you pass it. You have 5 things to do to see all of.

1) Create and save a module.
2) Load the module with the screen so it can be used form screen elements.
3) Load the module with the macros so it can be called from macros (Mcodes).
4) Call the module passing it your message from a button.
5) Call the module passing it your message form a custom Mcode (m110 in the example).

Play with it. Break it, fix it, add to it and have some fun.

Code: [Select]
--This is the mcUserScript.lua module that goes in the modules folder
local mcUserScript = {}

function mcUserScript.UserMessage(Message)
if (Message == nil) then --No message was passed
Message = "No message passed" --If no message is passed this will be the default message
end
wx.wxMessageBox(Message)
end

return mcUserScript -- Module End

--This is what loads the module above.
--Add this to the modules load section of the screen load script so you can call its functions from buttons on the screen.
--Add this to the load_modules.mcs file in the macros folder of the profile that will be using it so you can call its functions from M codes.
package.loaded.mcUserScript = nil
us = require "mcUserScript"

--Put this in a buttons clicked script and when you click it a message box will pop up that says... No message passed
us.UserMessage() --This is not passing a message for the Message parameter so the message will be the default

--m110 goes in the macros folder of the profile that will be using it
function m110()

us.UserMessage("This is my message")

end

if (mc.mcInEditor() == 1) then
 m110()
end
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 10:23:11 AM
Nice example ;-)

Simple way to put it is Private and Public Functions

No prefix = Private function being used internally by the module and cannot be run from outside of the script
With prefix = Public function that can be run/called externally using the prefix you gave it during requiring.

DazTheGas
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 11:50:55 AM
That helps very much.  I will work with it.  As I have said in the past, so much to learn!  But once learned, so much power over the machine!  Satisfying when it works!

Keith
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 12:50:21 PM
I made a lua file in the mach4hobby/modules directory called mcUserScript.lua containing the script below--

local mcUserScript = {}

function mcUserScript.UserMessage(Message)
   if (Message == nil) then --No message was passed
      Message = "No message passed" --If no message is passed this will be the default message
   end
   wx.wxMessageBox(Message)
end

return mcUserScript -- Module End

Flummoxed right off the bat...

Keith

Then when mach4 loads there is an error that no such module exists
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 01:00:33 PM
You will need to make sure the path to the module  is included before the require, this is already set in the screen load script but still ok to put again

Code: [Select]
    local profile = mc.mcProfileGetName(inst)
    local path = mc.mcCntlGetMachDir(inst)
   
    package.path = path .. "\\Profiles\\" .. profile .. "\\Modules\\?.lua;" .. path .. "\\Modules\\?.lua;"

when using require it will look in these path locations for the module

DazTheGas
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 04:48:08 PM
Got it now.  I had mc.UserScript instead of mcUserScript

Thanks!
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 05:07:39 PM
I have it working in a screen button .

Now I don't know how to get it to work in the m110 macro  m110 in mdi causes an error expecting a number

Tired to make a file load.modules.mcs in the macros directory of the profile containing

 local profile = mc.mcProfileGetName(inst)
    local path = mc.mcCntlGetMachDir(inst)
   
    package.path = path .. "\\Profiles\\" .. profile .. "\\Modules\\?.lua;" .. path .. "\\Modules\\?.lua;"

package.loaded.mcUserScript = nil
us = require "mcUserScript"
Title: Re: Understanding Lua
Post by: Chaoticone on December 19, 2016, 05:12:50 PM
Where are you defining the inst variable your using in the first 2 calls?

inst = mc.mcGetInstance()
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 05:13:55 PM
Change the filename to  load_modules.mcs

DazTheGas
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 05:35:10 PM
Changed file to load_modules.mcs
Added inst = mc.mcGetInstance() to load_modules.mcs

Still not running with m110 in MDI
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 06:28:39 PM
This is where I have place files

C:\Mach4Hobby\Modules\mcUserScript.mcs

Code: [Select]
local mcUserScript = {}

function mcUserScript.UserMessage(Message)
if (Message == nil) then --No message was passed
Message = "No message passed" --If no message is passed this will be the default message
end
wx.wxMessageBox(Message)
end

return mcUserScript -- Module End

both the m110.mcs and load_modules.mcs goes in your profiles own macro directory

load_modules.mcs

Code: [Select]
local inst = mc.mcGetInstance()
local profile = mc.mcProfileGetName(inst)
local path = mc.mcCntlGetMachDir(inst)
   
package.path = path .. "\\Profiles\\" .. profile .. "\\Modules\\?.lua;" .. path .. "\\Modules\\?.lua;"

package.loaded.mcUserScript = nil
us = require "mcUserScript"

m110.mcs

Code: [Select]
function m110()

us.UserMessage("This is my message from m110")
 
  end

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


This is working within the mdi no problem but still debugging why its not working when called from within gcode, my bet is its something to do with the messagebox not being able to show in the gui from gcode. when running gcode its run within another lua instance that does not have access to the lua instance that is within the gui.

DazTheGas
Title: Re: Understanding Lua
Post by: DazTheGas on December 19, 2016, 06:42:57 PM
Yep changing the code to below without the messagebox worked fine using mc.mcCntlSetLastError(inst,Message) instead

Code: [Select]
local mcUserScript = {}
local inst = mc.mcGetInstance()

function mcUserScript.UserMessage(Message)
if (Message == nil) then --No message was passed
Message = "No message passed" --If no message is passed this will be the default message
end
--wx.wxMessageBox(Message)
mc.mcCntlSetLastError(inst,Message)
end

return mcUserScript -- Module End

with this now working it should give you something to play with ;-)

DazTheGas
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 07:45:32 PM
Thanks, it works for me. 
I appreciate the follow through.  Learning!

Keith
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 07:49:58 PM
Only difference is
C:\Mach4Hobby\Modules\mcUserScript.mcs should be
C:\Mach4Hobby\Modules\mcUserScript.lua ??

Thanks
Keith ???
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 08:01:54 PM
When I create a gcode file with one line m110 it bombs out the gui?
Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 08:05:47 PM
Gcode FILE  with

G0 X0Y0
M110
G0 X1Y0

works fine


Title: Re: Understanding Lua
Post by: thespindoctor on December 19, 2016, 08:48:37 PM
Works fine in all instances button script, g code, mfunction, even with wx.wxMessageBox(Message)

Keith
Title: Re: Understanding Lua
Post by: Chaoticone on December 19, 2016, 09:33:46 PM
Great! Can you give us a summary of why that wasn't the case on the first try? This helps make adjustments to samples, docs, etc.
Title: Re: Understanding Lua
Post by: thespindoctor on December 20, 2016, 08:45:04 AM
Next post is correct I believe
Title: Re: Understanding Lua
Post by: thespindoctor on December 20, 2016, 08:56:53 AM
I think your original code was successful except for the filename change to load_modules.mcs from load.modules.mcs

Daz suggestions changed the message method and

C:\Mach4Hobby\Modules\mcUserScript.mcs should be
C:\Mach4Hobby\Modules\mcUserScript.lua

Changes from Daz quote made below

This is where I have placed files

C:\Mach4Hobby\Modules\mcUserScript.lua

Code: [Select]
local mcUserScript = {}

function mcUserScript.UserMessage(Message)
if (Message == nil) then --No message was passed
Message = "No message passed" --If no message is passed this will be the default message
end
--wx.wxMessageBox(Message)
mc.mcCntlSetLastError(inst,Message)
end

return mcUserScript -- Module End

both the m110.mcs and load_modules.mcs goes in your profiles own macro directory

load_modules.mcs

Code: [Select]
local inst = mc.mcGetInstance()
local profile = mc.mcProfileGetName(inst)
local path = mc.mcCntlGetMachDir(inst)
    
package.path = path .. "\\Profiles\\" .. profile .. "\\Modules\\?.lua;" .. path .. "\\Modules\\?.lua;"

package.loaded.mcUserScript = nil
us = require "mcUserScript"

m110.mcs

Code: [Select]
function m110()

us.UserMessage("This is my message from m110")
  
  end

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

DazTheGas

[/quote]
Title: Re: Understanding Lua
Post by: Chaoticone on December 20, 2016, 09:31:58 AM
I am confused. Unless I am misunderstanding you, in the script I originally posted both of those are correct.

Quote
I think your original code was successful except for the filename change to load_modules.mcs from load.modules.mcs

C:\Mach4Hobby\Modules\mcUserScript.mcs should be
C:\Mach4Hobby\Modules\mcUserScript.lua

The reason I point this out is because it really shines a light on the old saying, garbage in is garbage out. To us humans those are very simple mistakes and easily overlooked. But to a computer your talking about different planets all together. I plan on using this as an example many will see over time and I want to make sure it is 100% accurate. I know it works here, I have tested it many times but if exactly what I posted does not work on your end I need to figure out why.
Title: Re: Understanding Lua
Post by: thespindoctor on December 20, 2016, 03:02:35 PM
Those were my mistakes and happened because I did not have the file naming conventions correct.  I think it is correct now.  The way Daz posted it was easier for me to see where to save each file type and how to name each file.  I will proof it again tonight after the first day
of skiing Copper Mountain now.  Not sure why Daz had trouble in a G code file.

Keith
Title: Re: Understanding Lua
Post by: DazTheGas on December 20, 2016, 03:38:23 PM
A big oooooops from me  ??? ??? ??? ??? :o :o :'(,  just had a rather interesting debug session and yep all works well.

It all boils down to forgetting what you did previously, I already have a macro functions file in my macro directory and forgot so by adding the load_modules.mcs file overwrites my "package.path" with the one containing the .lua extension.

my package.path normally consists of both mcs and lua

Code: [Select]
package.path = path .. "\\Profiles\\" .. profile .. "\\Modules\\?.lua;" .. path .. "\\Modules\\?.lua;"
package.path = package.path ..path .. "\\Profiles\\" .. profile .. "\\Modules\\?.mcs;" .. path .. "\\Modules\\?.mcs;"

DazTheGas
Title: Re: Understanding Lua
Post by: Chaoticone on December 20, 2016, 04:27:23 PM
Awesome feedback guys! Thanks!

Have fun skiing! Makes me jealous.  ;D

Thats a good find Daz. That could have taken a very long time to find especially if you did not have intimate knowledge of your setup. No shame in it either. This is what happens. To me it is another perfect example. This is why once folks start customizing any little part, they own it all and have to. This is why we ask all testing be done with all things default. Now with this example no way to do it because we are helping to customize but folks need to always start with a profile (copied) that has all things default, change a little and test. That way its easy to back out till you find the error if you run into one.

It also lets folks see that even the best run into issues at times and just have to dig in and figure out whats going on. Sometimes knowing what doesn't work is as valuable as knowing what does. I remember a bit of code stumping me not so long ago. The problem............ inst was not defined. Another fella spotted it right off. Obviously I understand its importance but being imperfect comes natural.  ;D

I may be wrong but I think topics like this one will be priceless for those starting out and willing to follow.