Machsupport Forum

Mach Discussion => Mach4 General Discussion => Topic started by: Havoc340 on September 20, 2018, 03:51:03 PM

Title: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on September 20, 2018, 03:51:03 PM
Ok, so my brain is not working like it used to. I haven't even heard of Lua before today. I have a macro from Mach3 that does exactly what I need it to, however since I'm runing a pokeys57u on my lathe, and want all of the features... I'm going to need to resort to Mach4.

Can someone please help me out?

Here is a Macro I found for Mach3 to control the PCturn Turret, using the factory internal encoder setup. I have everything wired up and mechanically ready to test.


The thread is short, but http://www.machsupport.com/forum/index.php/topic,16685.0.html is my source.

****************************************************************************************************************************************************

'M6Start.M1s
'Input1 is an optical sensor used to count tool positions
'Input2 is from a microswitch used to determine tool 0 position
'OUTPUT6 drives the tool changer forward, de activating it allows the tool changer to rotate back against the ratchet pawl at low power and is the default
'Un comment the Open statement, various write# statements and the close# function to write a logfile for diagnostic purposes

'Close #1
'Open "M6start_log.txt" For Output As #1 'open a file to write logs to
NewTool = GetSelectedTool()
'NewTool = 2
'Write #1, "NewTool ", NewTool
OldTool = GetCurrentTool()
'Write #1, "OldTool ", OldTool
MaxToolNum = 6 'Max number of tools for the changer
CurrPos = OldTool

While (NewTool > MaxToolNum)
    NewTool = Question ("Enter New Tool Number up to " & MaxToolNum)
Wend

    'there is nothing to do so we just exit
If (NewTool = OldTool) And (NewTool > 0) Then
   'Write #1, "New tool number is the same as old tool number. Nothing to do "
       Exit Sub
End If

'If OldTool is 0 that means we dont know where the tool changer is currently positioned and need to reference to the microswitch for tool 1 position.
    'need to establish tool 0 position from microswitch
If (OldTool = 0) Then
   'Write #1, "Old tool number is zero, looking for reference position"
   ActivateSignal(OUTPUT5)' Set toolchanger for full speed move
        'Write #1, "Activated Output 5 to enable toolchanger motor"
        ActivateSignal(OUTPUT6)' rotate tool changer forward
        'Write #1, "Activated Output 6 to set forward direction"
    While Not IsActive(INPUT2)
    Wend
    ' Input 2 must Now be active so the microswitch has been triggered at position 1
    CurrPos = 1
    'Write #1, "Reference position found "
    ' Decide whether to just stop for the normal toolchange process
    If ( CurrPos <> NewTool) Then
       DeActivateSignal(OUTPUT6)
       DeActivateSignal(OUTPUT5)
    Else
    ' Or if we actuallly wanted tool 1 then stop and lock
           DeActivateSignal(OUTPUT5) 'stop rotating forward, rotate backward now
      'Write #1, "DeActivateSignal Output 5 toolchanger reverse "
           SetCurrentTool(NewTool) 'sets up the current tool variable as the start point for a future tool change
           'Write #1, "Setting CurrentTool to NewTool value ", NewTool
           Sleep(2500) 'Allow a time interval for the toolchanger to settle back against the ratchet pawl
           'Write #1, "Waited 2.5 seconds for toolchanger to lock "
           DeActivateSignal(OUTPUT6) 'Disable toolchanger motor
           'Write #1, "DeActivateSignal Output 6 toolchanger stop "
    End If
End If

If (CurrPos <> NewTool) Then 'write the start condition to a variable
   If IsActive(INPUT1) Then
      PreviousSensorState = "Active"
   Else
      PreviousSensorState = "Inactive"
   End If
   'Write #1, "PreviousSensorState =", PreviousSensorState
   ActivateSignal(OUTPUT5)' Set toolchanger for full speed move
          'Write #1, "ActivateSignal Output 6 toolchanger go"
        ActivateSignal(OUTPUT6) 'start rotating forward
        'Write #1, "ActivateSignal Output 5 toolchanger forward "
       While CurrPos <>  NewTool
          'Some logic to ensure that we only count on the leading edge of a slot in the toolchanger optical disk
           If IsActive(INPUT1) Then
              SensorState = "Active"
           Else
              SensorState = "Inactive"
           End If
           'Write #1, "SensorState =", SensorState
           If SensorState <> PreviousSensorState Then
              If SensorState = "Inactive" Then
                 CurrPos = CurrPos +1
                 If CurrPos = 7 Then
                    CurrPos = 1
                    'Write #1, "CurrPos reached 7, reset to 1 "
                 End If
              End If
              'Write #1, "CurrPos =", CurrPos
              PreviousSensorState = SensorState
           End If
           If CurrPos = NewTool Then
                 DeActivateSignal(OUTPUT5) 'stop rotating forward, rotate backward now
                 'Write #1, "DeActivateSignal Output 5 toolchanger reverse "
                 SetCurrentTool(NewTool) 'sets up the current tool variable as the start point for a future tool change
                 'Write #1, "Setting CurrentTool to NewTool value ", NewTool
                 Sleep(1500) 'Allow a time interval for the toolchanger to settle back against the ratchet pawl
                 'Write #1, "Waited 1.5 seconds for toolchanger to lock "
                 DeActivateSignal(OUTPUT6) 'Disable toolchanger motor
                 'Write #1, "DeActivateSignal Output 6 toolchanger stop "
           End If
           sleep(200) ' just slows the iterations down a bit
           'Write #1, "Waited 0.2 second "
       Wend
       'Write #1, "should be job done "
       'Close #1
End If   


If you don't know what is going on above, but know Lua somehow... I have a 6 position turret. There are 2 "encoders" in it. One pulses each tool, and the other pulses on tool 1. A single output turned on advances the tool. When the output is turned off, it will automatically lock into place.

Any help would be greatly appreciated! Thanks!
-Bob
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: thosj on September 20, 2018, 05:32:34 PM
Bob,

If someone here can't help, that macro does seem pretty complicated. you can create a ticket at support.machsupport.com and ask them to write the code for you. You can even PAY them to do it!! They have a system where you can prepay with PayPal for some amount of time and they'll use it as required. It starts as a pending transaction with PayPal 'til they actually bill for it, otherwise you're out nothing.

Not that it wouldn't be cheaper if someone here can help, but it's an option.

Tom
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 20, 2018, 05:51:06 PM
Hi Havoc340,
one of Mach4 strengths is its ability to be customized. That requires that you code in Lua.

That can be a steep learning curve, I could help but am not inclined to do it for you wthout
you helping yourself. Do you want to do so?

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on September 20, 2018, 07:30:45 PM
Thanks for the replies!

Tom, that is an idea for sure!

Craig,  I can totally appreciate your process of helping me learn vs doing it for me. I am willing to learn however I'm a slow learner with the code.

If it were Arduino, I could hobble something together just fine. I know what needs to happen in the tool change process, I just do not know the Lua words. There are easily defined tutorials. With Lua everything I have come across is to create programs, and user interfaces, and way more technical stuff. None of the terminology makes any sense, and the tutorials go straight into randomization, UI, etc... and none of it really is pertaining to my issue. I have looked for other tool changer examples and haven't found any I can work from.
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 20, 2018, 07:59:41 PM
Hi,
'its not that I'm a slow learner....but I am a quick forgetter!'

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on September 20, 2018, 08:38:36 PM
Super quick haha.

So to break it down...

How do I define inputs and outputs in Lua?
I need to turn an output on "output 1" and then wait for encoder pulses.
How do I count? I would like to be able to index tool 1 and save it's position, then increment from there on each tool pulse.
Once the correct tool is reached, I need to turn off that output.

It would be nice to store the current tool location so the next tool change from T2 to T3 does not need to cycle all the way through to T1, and then count to 3... but honestly if it works I'll deal with it.

Then I need to be able to exit the macro telling MACH that the correct tool is loaded.

That is pretty much the jist of it.
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 20, 2018, 08:49:06 PM
Hi,
inputs and outputs are handled in a different fashion in Mach4.

Inputs cause a lot of confusion when learning this from new.
In particular Mach makes use of the one and only data structure in Lua, the table.

I have this link open almost continuously when coding Lua:
https://www.lua.org/manual/5.2/ (https://www.lua.org/manual/5.2/)
Note that it varies slightly from 5.3 Open the link and read about tables.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 21, 2018, 05:56:58 AM
Hi,
in Mach3 the program would stop what it was doing every 10ms or so and read all the inputs. If one of the inputs was active it would
execute the code associated with that input. This behavior is called 'polling'. Its quite inefficient, it reads only every so often and then it has to read
ALL inputs when you may in fact only be interested in a few of them.

In Mach4 there are lots (hundreds) of signals, not just inputs but other signals internal to Mach. When any one of them changes Mach executes the signal script.
Mach only knows the signal handle and the new state of the signal with that handle. This happens very quickly indeed, a few usec at most.

The signal script as shipped with Mach4 is:
Code: [Select]
if SigLib[sig] ~= nil then
    SigLib[sig](state);
end

Thus when a signal changes Mach knows it only as the variable 'sig' and it has a state 'state'. When the signal script executes Mach is directed to look in the tabe
'SigLib' at the table index 'sig'. If there is an entry in the table for that signal it executes the function associated with that entry SigLib[sig] with the
parameter (state).

If the signal is of no interest to us then it wont have an entry in the signal library (SigLib) and so it will go back to what it was doing. If we are interested however,
for instance in ISIG_INPUT5, ie input #5 because its hooked to a switch, then we will have an entry in the table for it and a function to be executed if
the signal happens.

Note that there will be two instances when the function will be called, once when its state changes from off to on and again when it changes from on to off.
Thus your function must have a test to determine if some action is to be taken.

The upshot is that Mach interrogates the table anytime a signal changes but it only ever executes some extra code if it is a signal we are interested or waiting for.
It is very computationally efficient. At first glance it can appear confusing but its speed and reliability are miles ahead of Mach3.

Craig

Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 23, 2018, 02:45:15 AM
Hi,
having probably confused you....you can now start to use what you have learnt.

You have at least one input, the index switch. You have at least one other, tool position encoder, can you tell us about how that works.

For the one input that we are sure of, we can make an entry in the signal library table for it.

When writing Lua code you will often find that you will write some parts in the form of macros which will end up in the macro folder
but there will be code fragments that end up in the screen load script and other places, this little addition to the signal library table is an example.
Its a good idea to set aside a temporary folder where you can write and maybe test these little fragments of code. Once you are happy with them
THEN you put them in their final location.

May I suggest that you open the main Mach4 folder and make a new folder within your current profile called 'tempfolder' or similar.

Now open the Script Editor under the Operator tab and you will have an untitled script page that you can save in the tempfolder you have created.
This tempfolder will hold all the little bits of code that you will put together.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on September 23, 2018, 03:25:49 AM
Hi,
now open the script editor and put this code in it:

Code: [Select]
[mc.ISIG_INPUT3]=function(state)
if state==1 then
toolindex=1
else
toolindex=0
end
end

Save it as 'siglib' or some other unique name.

Note that I have declared a variable 'toolindex', and I have not put 'local' in front of it. It is therefore a global variable and as it is declared,
or least will be when its finished and put in its permanent location, in the screen load script and is therefore visible throughout the GUI.
We may have to get a bit creative if we wish to pass it to a macro because a macro is not technically in the GUI. Anyway that's for the future.

You might ask why I chose input #3? If you look in the screen load script and the signal library table in particular you will see that Mach is already
using, or at least has table entries for inputs #1 and #2. I didn't want to confuse you, or me come to that so I left those out.

If you look on the machine diagnostic page, if the lathe screen set even has such a page you will see that there are LEDs for the first six inputs.
It is convenient to use those to start with because if you reach over and flick the index switch by hand you should see the LED on the diagnostic screen
light up. At a later date you might chose to reassign the switch to input #19 say, of course you wont have an onscreen LED to tell you whether Mach
has seen the switch or not, but by then you have already experimented with it enough to know it works.

If you can tell me how the tool position encoder works we can make a start on that code as well.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on October 02, 2018, 12:57:24 PM
Craig, you were right. I was completely confused. I had tried to dig a little more through the initial information in the lua manual and got frustrated.

From there, my mach4 pc was a huge turd, and with other things going on in life I just put it on the back burner. Now I'm ready to take another crack at it.

I hadn't noticed your replies until now. I'm reading what you have posted and re-reading it. Hopefully it starts making some sense.

As for the "encoder" on the tool turret, it is just pulse indexing. As each tool is indexed, a pulse is sent. As tool 1 is indexed, a separate signal pulse is sent as well. So it's like an encoder but it's not technically. It operates in this order through the turret rotation:

Tool: Input 1, Input2

 Tool 1: 1-1
Moving: 0-0
 Tool 2: 0-1
Moving: 0-0
 Tool 3: 0-1
Moving: 0-0
 Tool 4: 0-1
Moving: 0-0
 Tool 5: 0-1
Moving: 0-0
 Tool 6: 0-1
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on October 02, 2018, 01:49:13 PM
I don't know how to store a state, but I am not totally new to state based programming. I didn't realize that this is what Mach4 uses. As I am reading and re-reading your posts I think it's starting to sink in just a little.

I think I could get by with something like this, just in the right language.

To index all six postitions something like this might work:

If input (the tool pulse) 1 is on, and input 2 (turret index) is on State =0 (Tool 1)
If Input 1 is on, and input 2 is off and state =0, change state to 1 (tool 2)
If Input 1 is off, and input 2 is off and state =1, change state to 2 ( I think a "dead state" may be nessicarry to prevent cycling/looping through all states automatically once the input/outputs are triggered).
If Input 1 is on, and input 2 is off and state =2, change state to 3 (Tool 3)
If Input 1 is off, and input 2 is off and state =3, change state to 4
If Input 1 is on, and input 2 is off and state =4, change state to 5 (Tool 4)
If Input 1 is off, and input 2 is off and state =5, change state to 6
If Input 1 is on, and input 2 is off and state =6, change state to 7 (Tool 5)
If Input 1 is off, and input 2 is off and state =7, change state to 8
If Input 1 is on, and input 2 is off and state =8, change state to 9 (tool 6)
If Input 1 is off, and input 2 is off and state =9 change state to 10
If Input 1 is on, and input 2 is on and state =10, change state to 0 (reset to state 0, and tool 1)

Tool Request is translated into state request. So if the machine is currently in state 0, and tool 1 is requested the machine checks the state (T1 State=0) and does nothing.
If tool 5 is requested the macro translates that into needing the machine to be in state 7. Since the machine is in state 0, it turns on two outputs simultaneously Lets call them output 1 and output 2. Output one is an enable relay that energizes the turret. Output two is the signal for the turret to move.

**How this turret works mechanically**
 When this turret is energized (output 1 on), it automatically moves in reverse and locks into position against a ratchet pawl. When the turret gets the "advance" signal (output 2), it moves forward. The ideal situation turns both the turret on, and then energizes it for a forward move. Once it is in position, turn off output 2. it will automatically reverse and lock into position. After a set time, turn off output 1 so the motor isn't constantly powered.


Once the outputs are turned on, the turret starts to move. As it moves it will be triggering the index and pulse "encoder signal", subsequently changing the states.

Once the turret is in the requested state 7 (Tool 5) position, it shuts off output 2 (the turret move signal) and then 10 seconds later it shuts off the output 1, de-energizing the turret motor.

Then if the state = the state requested by the m6, it exits the macro. Maybe it should store the current state. I am not sure. Or when we home the machine upon power up, the turret indexes to tool 1. I am not sure if or how states are stored however if we can save the current state it would prevent the need to cycle the turret through to state 0 and count up from there.

I know this is a long way from an actual program however I feel it is a solid outline of the macro. I just need the correct jargin.

Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 03, 2018, 02:18:23 PM
Hi,
I am digesting what you have said.

When you first turn Mach on it has no idea where the turret is. It will have to step through all the positions in turn UNTIL
it receives an index signal, ie tool 0.

What I propose is that we write a macro/function that advances the turret one position. It will be used not only to home
but later on as you which to advance to a given tool number within the M6 macro.

Given that this function will be called frequently it should be as efficient and fast as we can make it. Thus we wish to test:
IF the turret is ON (output1 is active) then activate output 2, ie advance one position UNTIL input 2 goes active.
IF the turret is not ON then turn it on and wait until input 2 goes active, ie the turret is accurately located at the current tool position THEN activate output 2,
ie advance the turret UNTIL input 2 goes active, ie the turret has advanced to the next consecutive tool position.

Does that sound right?

If you think that's feasible I will try a little code tonight after work.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on October 04, 2018, 12:18:04 PM
I expected the turret to need to home, and cycle once to index itself to the first tool. This happens once the turret has been indexed and the first position established. Then if there was a way to keep track of the state the whole time mach4 was running on the computer (I expect it already does) then the turret would not need re-homed any more than the X or Z axis do.

I am also trying to understand the way you have worded your IF's.
I think I can simplify my explanation of the turret operation.

In order to advance the turret, you must turn Output 1 AND 2 ON simultaneously.
In order to lock the turret into place, Output 1 must be on, for 10 seconds by itself, with Output 2 OFF.  When output 1 is on by itself, the turret rotates backwards and locks against a ratchet pawl.
After the 10 second timer is met, Turn Output 1 Off. At this point, Outputs 1 and 2 are off and the turret is disabled.

To index the turret:
When it is time to home/index advance the turret, you will want to turn OUT1 and OUT2 on simultaneously.
When Input 2 (Index Input pulse) goes active, Turn off OUT2. wait 10 seconds. Turn off OUT1.
The turret is now indexed in the first position.

After the turret is indexed and home, this is what needs to happen for a complete tool change:
When a tool is called and it is time to advance the turret, you will want to turn OUT1 and OUT2 on simultaneously.
When Input 1 (Tool position pulse) goes active, Turn off OUT2. wait 10 seconds. Turn off OUT1.
The turret is now in the next consecutive tool position.

 Now that I know we have states to work with, I figured we would be giving each tool position it's own state. Having the "dead spot" state between tools would help "ratchet" the program through the states, ticking them up through the input changes.  That is how I am thinking about the program.  

 

Without knowing the intricacies of Lua structuring of things, and what needs to happen for something to happen I will say that however it ends up working is fine with me.


And thank you again for your time Craig! I know I am going to end up learning a ton from the way we are doing this. Seeing the way the code is put together to accomplish this task will give me a ton of insight how to get going with other macros. Maybe I'd even get the confidence to retrofit my other machine with a tool changer. I'd love to add a 4th axis to it, but the only way that happens is if I retrofit.
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 05:43:17 PM
Hi,
we can start doing some coding.

I think the best way to proceed is to put the two inputs and the two outputs in registers.

When Mach runs it has, broadly speaking, two chunks, one is the GUI chunk, the other is the Mach Core chunk. Only one can operate at a time
and the data in one chunk is not available to the other. Registers are the way around that, they provide a common repository for data and instructions
which can be accessed by any chunk or plugin throughout Mach.

First open Configure/Plugins/Regfile and make four new registers per the pics. Note you can use any names you feel are appropriate.

Once you have defined your new registers then go to Diagnosic/Regfile and expand the instance registers iRegs0. You will see your new registers and their current
values. Note that if you want to change a value just highlight it, click on it and edit it manually. Note also that registers can be persistent (or not).
If they are persistent then the values will be recorded in your profile.ini file at Machs shutdown and be repopulated when you start a new session of Mach.

Ok.....now we need to hook the input signals to Mach and then have Mach update the registers. Note that I'm dealing only with the input signals to start with.
Note also that I'm going to use Input #3 and Input#4 so that I can see the LEDs for testing purposes per my earlier post.

Will post the code shortly.....need to go and hang out the washing!   Its a bastard when real life interferes with your CNC... ;D

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 06:35:34 PM
Hi,
in the temp folder put this code, note that it overwrites the previous version of ISIG_INPUT3 entry:

Code: [Select]
mc.ISIG_INPUT3]=function(state)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/ToolIndex')
if state==1 then
mc.mcRegSetValue(hreg,1)
else
mc.mcRegSetValue(hreg,0)
end
end,
[mc.ISIG_INPUT4]=function(state)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/ToolPosition')
if state==1 then
mc.mcRegSetValue(hreg,1)
else
mc.mcRegSetValue(hreg,0)
end
end,

Note that after each table entry a comma is required to separate the next entry.
If you are happy with this then it is time to put it in its final location, namely the screenload script in the signal library SigLib{}.
Open the screen editor, and then expand the screenload script and note the SigLib{} table near the top. Paste in your two
new entries.
Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 07:20:20 PM
Hi,
note that when you exit and save the screen editior you will have saved a modification to the existing screenset.set.

If you are new to Mach4 then I would guess you already have a separate and individualized profile.ini file. What you may not
realize is that you should have a separate and individualized screenset.set as well.

The reasoning goes like this....if you are using wx4.set (as I do) and then you start making all sorts of additions and tweaks then when you next
update Mach to the newest and greatest build then you will also get a fresh copy of the newest and greatest wx4.set as well overwriting all your work,
and depending on circumstances you may not be able to get it back....double and triple bugger! >:D Ask me how I know.....I will have to answer PM as
the swearing filters would not permit me to post a frank reply!!!!

I recommend you go to the Mah4Hobby folder and find the screenset folder and make a copy of your favorite screen set with an individualized name.

Now when you run Mach go to View/Load Screen and you will be presented with a list of available screens which should include yours, select it and click Open
and that is now the screenset in use and will be recorded in your profile as such. Note mine is called ESSMillwx4.set. It will not be overwritten when you update.

It may be that I am insulting your intelligence by painstakingly laying out these things but I found they were exactly what tripped me up when I was learning.
If you feel slighted I apologise. I hasten to add that there may well be others following this thread and it might have relevance to them even if you find them
trivial.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 09:05:34 PM
Hi,
I like to test as I go. I could go and hook up a couple of switches to my ESS, but that's out in the garage. What I'm going to do instead is use a couple
of keyboard inputs to mimic the switches, means that I can do it all on my laptop.

It is not quite as straight forward as it sounds, you have to use a workaround to get it to work. Its such a valuable technique that it is
worth making the effort to learn, you will use it dozens of times over the coming months/years. I'm copying work that Daz-the-Gaz has already
done. Watch his video:
http://www.machsupport.com/forum/index.php/topic,31585.msg219180.html#msg219180 (http://www.machsupport.com/forum/index.php/topic,31585.msg219180.html#msg219180)

Open Configure/Plugins/Keyboard and add two new keyboard inputs, I used F1 and F2 and called them ToolIndex and ToolPosition respectively.
Now you need some code to go in the PLC. To start with make a temporary file in your temp folder....something like tempplccode.

Code: [Select]
--************************************************************************
--************************************************************************
--TEMPORARY TESTING CODE ONLY

local hsig1=mc.mcSignalGetHandle(inst,mc.ISIG_INPUT62)
local hsig2=mc.mcSignalGetHandle(inst,mc.ISIG_INPUT3)
if mc.mcSignalGetState(hsig1)==1 then
mc.mcSignalSetState(hsig2,1)
else
mc.mcSignalSetState(hsig2,0)
end
local hsig3=mc.mcSignalGetHandle(inst,mc.ISIG_INPUT63)
local hsig4=mc.mcSignalGetHandle(inst,mc.ISIG_INPUT4)
if mc.mcSignalGetState(hsig3)==1 then
mc.mcSignalGetState(hsig4,1)
else
mc.mcSignalSetState(hsig4,0)
end

--END OF TEMP CODE
--*****************************************************************************
--*****************************************************************************

Now open the PLC script and paste the code in just before the end.

You will have to close Mach and restart before these changes take effect.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 09:14:28 PM
Hi,
OK finally we can test what we have done so far.

start up Mach and open the Regfile Diagnostics page and pin it to the top. Make sure that on the jog tab the keyboard inputs are enabled.

Then on each occasion you hit F1 the input#3 LED should come on and the register iRegs0/ToolIndex should reflect your keypress.
Likewise if you fit F2 then input#4 LED should come on and iRegs0/ToolPosition should reflect the keypress.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 11:08:35 PM
Hi,
sick of me yet!!!

Let me know if you stumble on any of the stuff so far.

Assuming all is good then we can start writing code to do things. The first thing we need is a macro to lock the turret.
I've called it m180....for no particular reason. Its generally considered that macros under 100 are Machs own....go there but
you may be trashing one of Machs macros. Anything above 100 is OK. Note there are some macros there  that you don't want
to trash either. From memory m161 and m162 are related to laser operation. You may not care that they get overwritten but
I would avoid doing so.

Another quirk of Mach4 is that when it reads a macro name it converts all upper case to lower case and strips out leading zeros and spaces.
Thus:
m180,
M 180,
m  0180,
M018   0
all point to the same thing, namely m180. Windows is not case sensitive and so M180 works, try that in Linux and you'll bomb.
It doesn't happen often but it does happen that if you use a non standard name because it 'looks nice' you can introduce an error.
I therefore name everything as Mach reads it, ie lower case, no leading zeros and no spaces. What you choose to do is up to you
but I promise on one of those rare occasions when it throws an error is going to leave you really pissed off.

Here is the m180 macro:
Code: [Select]
function m180()
-- Lock the turret.
local inst=mc.mcGetInstance()
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
if (mc.mcRegGetValue(hreg)==0) then
mc.mcRegSetValue(hreg,1)
mc.mcSignalGetState(hsig,1)
end
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
if (rc==mc.MERROR_NOERROR) then
elseif (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to lock')
return
end
mc.mcCntlSetLastError(inst,'Turret Locked')

end
if (mc.mcInEditor()==1) then
m180()
end
Note I have done some things which you may question and may not work.

The first thing I've done is asked is the register iRegs0/TurretLock on or not. If its not on then turn it on.
Turn on the output Output#3, here I am assuming output#3 is hooked to the turret lock input of your turret.

Thats the easy bit. The next bit might take a little more thinking about. I have written a mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
instruction. You might like to read in the  API.chm document of the documents folder in Mach4. You will as you code Lua be reading
and re-reading...and re-reading....and re-reading the API document....and curse when you realize that its out of date, NFS have added new
stuff which hasn't even got in there yet!

Basically the instruction is saying 'Wait until ISIG_INPUT4 goes high (that's your ToolPosition signal), and time out after 11 seconds.
What I have done is assume that while you say it takes ten seconds for the turret to lock it might take less than that too. Thus when
the TurretLock signal is sent then Mach waits until the ToolPosition signal comes good. If that hasn't happened after 11 seconds you have a problem
and it will put a wxMessage on screen which you will have to clear. I'm not sure yet what you want to do in a fault situation.
If the turret locks within the timeout period then the you get a status message and the function completes normally.

Note that many of the API's have a return code, shortened to rc. The rc will give an indication as to whether the function has finished executing normally
or not. In this case I'm using it to detect a timeout which is an indication of turret lock failure.

Do you think that will work?

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 06, 2018, 11:27:45 PM
Hi,
I've just realized that I have not allowed anyway to turn the TurretLock signal off.

If you are OK with the idea that if the turret is in position as indicated with the TurretPosition switch then the
TurretLock signal could be turned off immediately. That would require only two more lines of code, one to set the
register to zero and the other to your the output off.

Code: [Select]
function m180()
-- Lock the turret.
local inst=mc.mcGetInstance()
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
if (mc.mcRegGetValue(hreg)==0) then
mc.mcRegSetValue(hreg,1)
mc.mcSignalGetState(hsig,1)
end
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
if (rc==mc.MERROR_NOERROR) then
elseif (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to lock')
return
end
mc.mcCntlSetLastError(inst,'Turret Locked')
mc.mcRegSetValue(hreg,0)
mc.mcSignalSetState(hsig,0)

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

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 07, 2018, 12:48:22 AM
Hi,
now we need a function to advance the turret by one. We need another register....open the Regfile plugin and add another register
iRegs0/TurretPosition. It will record the current position of the turret, from 0 through 5.

Lets assume for the moment that we know, or rather Mach knows that the turret is locked into a position. This code might work:

Code: [Select]
function m185()
--Advance the Turret
local inst=mc.mcGetInstance()
local hsig1=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
local hsig2=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT4)
local hsig3=mc.mcSignalGetHandle(inst,mc.ISIG_INPUT4)
local hreg1=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
local hreg2=mc.mcRegGetHandle(inst,'iRegs0/TurretAdvance')
local hreg3=mc.mcRegGetHandle(inst,'iRegs0/TurretPosition')
if (mc.mcSignalGetState(hsig1)==0) then
mc.mcSignalSetState(hsig1,1)
mc.mcRegSetValue(hreg1,1)
end
mc.mcSignalSetState(hsig2,1)
mc.mcRegSetValue(hreg2,1)
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,10)
if (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to Advance')
return
end
mc.mcSignalSetState(hsig2,0)
mc.mcRegSetValue(hreg2,0)
--************************************************
local inst=mc.mcGetInstance()
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
if (mc.mcRegGetValue(hreg)==0) then
mc.mcRegSetValue(hreg,1)
mc.mcSignalGetState(hsig,1)
end
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
if (rc==mc.MERROR_NOERROR) then
elseif (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to lock')
return
end
mc.mcCntlSetLastError(inst,'Turret Locked')
mc.mcRegSetValue(hreg,0)
mc.mcSignalSetState(hsig,0)
--*************************************************
local hreg4=mc.mcRegGetHandle(inst,'iRegs0/TurretPosition')
local currentTool=mc.mcRegGetValue(hreg4)
local currentTool=currentTool + 1
if (currentTool==6) then currentTool=0 end
mc.mcRegSetValue(hreg4,currentTool)
end
if (mc.mcInEditor()==1) then
m185()
end

The first part just sets up the signals required and turns the TurretLock and TurretAdvance outputs on. Once the ToolPosition
switch makes the TurretAdvance output turns off. The code between the two lines of asterisk is just our m180, or turret lock function.
The last bit of code increases the count of the Turret Position register.

We are getting close now.

Note all this code is pretty ragged and not well tested yet. I'm also beginning to wonder if I've used registers when I haven't needed to. In particular
the four ToolIndex,  ToolPosition, TurretLock, and TurretAdvance are looking redundant. They wont do any harm so I'll leave them be but we may at
a later time decide that they are not required.

The second issue is that this last macro includes the code of another one, can I use a subroutine or is pasting the code in complete better?
In this case I suspect its better to paste the code in directly. It admittedly means that there is some repeated code, but memory is cheap. It may make
the code a little easier to read with subroutines but I think it will run best as repeated code.

In this instance I will go with the repeated code strategy and later try reducing it by subroutines and compare the two.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 07, 2018, 01:17:44 AM
hi,
lets review what we have got, what we need to do yet and some ultimate goal.

We have a macro (m180) that can lock the turret. It still needs to be tested on your hardware.
We have a macro (m185) that advances the turret one position and then locks it place and advances a counter to indicate the new position. Again this needs
to be tested on your hardware.

What remains to be done is have a procedure made up of these two operations that can advance until the Index switch is detected. Mach can then reset its
tool position counter and be assured for the rest of the session it will stay in sync with the tool.

Another useful procedure would be to have a function that advanced two positions, or three positions or more. Thus if the current tool is no.2 and
tool no. 4 is required use the 'advance by two' function.

Why might you ask that I am adding all these functions? Am I not complicating matters.....and the answer is yes...to a certain extent.

My ultimate strategy is to have a table of functions called Turret[].

It will have a function called Lock.
It will also have a function called Advance.
It will have a function called Index.
It will have a function Advance2.
It will have a function Advance3.

and so on.... You can see where this is going. My hope is that Index your machine at startup you will call Turret.Index     That's it! You need do no more.
To go from your current position to two positions further you call Turret.Advance2   That's it! You need do no more.

Code like that is best as a module....but we will come to that later.

First trick is to make some code that works...there is still a little to go yet.  The next thing is to refine the code so that its efficient and robust. THEN if all
is well stick it all in a multifunction table.

Provided we can get code to work you could bail before doing all the table/module stuff, I won't drag you down that rathole unless you want to! ;D

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 07, 2018, 04:01:46 AM
Hi,
I have had some more thoughts about using the registers vs the ISIG_INPUTnnn and OSIG_OUTPUTnnn.

Part of me is convinced I need to use registers so that the data can be used by both the GUI AND Machs core Gcode processor.
The problem as evidenced by the code I have written is that I seem to be duplicating everything.

I realize now what I can do.

We have two input signals from the index and position switches on your turret. They have to be treated as input signals, ie ISIG_INPUT....
That's how we have treated them and recalling the code which we placed in the SigLib table:

mc.ISIG_INPUT3]=function(state)
   local hreg=mc.mcRegGetHandle(inst,'iRegs0/ToolIndex')
   if state==1 then
      mc.mcRegSetValue(hreg,1)
   else
      mc.mcRegSetValue(hreg,0)
   end
end,
[mc.ISIG_INPUT4]=function(state)
   local hreg=mc.mcRegGetHandle(inst,'iRegs0/ToolPosition')
   if state==1 then
      mc.mcRegSetValue(hreg,1)
   else
      mc.mcRegSetValue(hreg,0)
   end
end,
the registers ToolIndex and ToolPosition will always be in lockstep with ISIG_INPUT3 and ISIG_INPUT4. Thus I don't need to use Signal APIs to read the
inputs, just use the Reg APIs instead.

The question is how do we deal with the outputs? The outputs must use the OSIG APIs to cause the output pins of your controller to operate.
However we wish to use the registers TurretLock and TurretAdvance internally. This can only happen if you duplicate the API calls, hardly
code efficient and worse it will fail when Machs Gcode processor is running and starves the GUI of service then the OSOG_OUTPUT APIs wont work.

The answer is that OSIG_OUTPUT3 must be in lockstep with TurretLock and OSIG_OUTPUT4 with TurretAdvance.
This can be achieved by a few lines of code in the PLC script.

This is the code I will put in the PLC script:
Code: [Select]
local hreg=mc.mcRegGetHandle(inst,'iReg0/TurretLock')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
mc.mcSignalSetState(hsig)=mc.mcRegGetValue(hreg)
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretAdvance')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT4)

This will allow some simplification of the two macros we have written thus far:
Code: [Select]
function m180()
-- Lock the turret.
local inst=mc.mcGetInstance()
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
if (mc.mcRegGetValue(hreg)==0) then
mc.mcRegSetValue(hreg,1)
end
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
if (rc==mc.MERROR_NOERROR) then
elseif (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to lock')
return
end
mc.mcCntlSetLastError(inst,'Turret Locked')
mc.mcRegSetValue(hreg,0)
end
if (mc.mcInEditor()==1) then
m180()
end
And m185:
Code: [Select]
function m185()
--Advance the Turret
local inst=mc.mcGetInstance()
local hreg1=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
local hreg2=mc.mcRegGetHandle(inst,'iRegs0/TurretAdvance')
local hreg3=mc.mcRegGetHandle(inst,'iRegs0/TurretPosition')
if (mc.mcRegGetValue(hreg1)==0) then
mc.mcRegSetValue(hreg1,1)
end
mc.mcRegSetValue(hreg2,1)
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,10)
if (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to Advance')
return
end
mc.mcRegSetValue(hreg2,0)
--********************************************************************
local inst=mc.mcGetInstance()
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
if (mc.mcRegGetValue(hreg)==0) then
mc.mcRegSetValue(hreg,1)
end
local rc=mc.mcSignalWait(inst,mc.ISIG_INPUT4,1,11)
if (rc==mc.MERROR_NOERROR) then
elseif (rc==mc.MERROR_TIMED_OUT) then
wx.wxMessageBox('Turret failed to lock')
return
end
mc.mcCntlSetLastError(inst,'Turret Locked')
mc.mcRegSetValue(hreg,0)
--************************************************************************
local hreg4=mc.mcRegGetHandle(inst,'iRegs0/TurretPosition')
local currentTool=mc.mcRegGetValue(hreg4)
local currentTool=currentTool + 1
if (currentTool==6) then currentTool=0 end
mc.mcRegSetValue(hreg4,currentTool)
end
if (mc.mcInEditor()==1) then
m185()
end

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 07, 2018, 04:13:03 AM
Hi,
gross error in the PLC script, try this instead:

Code: [Select]
local hreg=mc.mcRegGetHandle(inst,'iReg0/TurretLock')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
mc.mcSignalSetState(hsig,(mc.mcRegGetValue(hreg)))
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretAdvance')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT4)

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 07, 2018, 04:40:38 AM
Hi.
yet another error:

Code: [Select]
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretLock')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT3)
mc.mcSignalSetState(hsig,(mc.mcRegGetValue(hreg)))
local hreg=mc.mcRegGetHandle(inst,'iRegs0/TurretAdvance')
local hsig=mc.mcSignalGetHandle(inst,mc.OSIG_OUTPUT4)
mc.mcSignalSetState(hsig,(mc.mcRegGetValue(hreg)))

It getting late in the day and I'm making all sorts of mistakes....my apologies to those of you trying to follow what I'm doing.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Havoc340 on October 07, 2018, 11:34:59 PM
I just found all of your replies right now, and wanted to say thank you!

It's late for me right now but I'll be going over all of this in the next day or two and report back!
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: joeaverage on October 08, 2018, 01:52:03 AM
Hi,
we really need to rest it on your hardware. Depending on just exactly how and when the tool-in-position switch operates could
have a major bearing on if it works.

Craig
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Chriscam1983 on February 21, 2022, 03:12:18 PM
Hi Craig,

Apologies for necro-posting, but I've also been struggling with the m6 macro on a similar machine and have followed along with this topic, was hoping for some assistance from here as I am unsure how to go about testing the functions we have here. Thanks!
Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Bill_O on February 23, 2022, 12:20:59 PM
Havoc and Chriscam,

This might help some.
When I was trying to learn Lua I made this for people like me to get started.

https://www.machsupport.com/forum/index.php?topic=45397.0

Title: Re: Need help with M6 Macro, translating from Mach3 to Mach4
Post by: Chriscam1983 on February 23, 2022, 03:14:33 PM
Hi Bill,

This is helpful, thank you!

I am still stuck however, I have the function Craig wrote for advancing the turret but I have no idea where to look to go about testing if it works. The lathe I'm working with is an EMCO PC Turn 55. If there's anyone that got further than this with a similar machine that could provide some insight it would be greatly appreciated.