Remap and code execution order

31 Mar 2024 10:19 #297269 by andyandy26
Hey All,

I'm trying to setup my CNC mill, and am configuring the "tool changer". It does not have an ATC, majority of my tooling is collet-based, and I don't have bed room for a tool setter.

Thus, my process for doing this is:
1 - Whilst the code is running with the current tool, I manually prepare the next tool in another tool holder, and measure the tool offset with some equipment
2 - The program gets to a M10 Pxx command (my stand in for a tool change to tool xx).
3 - The program does some minor stuff and raises the Z height to 0mm.
4 - The program asks for the tool offset of tool xx, and sets the tool-table entry.
5 - The program asks me to put in the new tool, I do so and acknowledge.
6 - Program loads new tool offset and continues.

I have this working through an M10 remap to a Gcode subroutine, which calls some code provided a while ago by Andypugh.

I'm getting 2 strange behaviours;
1. The code doesn't execute in the proper order of my subroutine, the Z doesn't raise until after M22 (the offset dialog) occurs, and
2. The M22 (dialog), is occuring after the M6 tool change... again?

The number entered into this second dialog box doesn't end up getting used.

I've attached my INI, python files for the dialog, and my subroutine file. Can someone please help explain to me what I'm doing wrong?

Please Log in or Create an account to join the conversation.

31 Mar 2024 10:55 - 31 Mar 2024 10:56 #297270 by Aciera
Generally you need to be aware that the Gcode (and with it your remap code) will be ingested by the read ahead some time before the machine movement actually happens. The read ahead will interpret the line of code and add the requested commands to a queue to be executed. The read-ahead can be thousands of lines ahead of actual machine movment.
In your case your python code will be executed when the read ahead ingests the remapped Mcode so you'll probably need to look at stopping the read ahead in the right places to get the machine movement to sync with your remap code.

Your remaps end with
return INTERP_OK
that means the read-ahead just simply executed the python code and ingests the next line in your gcode program.

The first thing you could try is to end your remaps with:
return INTERP_OK
Which will make sure the read-ahead waits for programm execution to catch up before ingesting and executing your next line of gcode.

Since you are not using any self.execute() commands you can also use 'yield INTERP_EXECUTE_FINISH' in other places of your remap code if necessary.
Last edit: 31 Mar 2024 10:56 by Aciera.

Please Log in or Create an account to join the conversation.

31 Mar 2024 12:26 #297275 by andyandy26
Thank you sir!

I'll give it a try tomorrow and see how I go!

I'm still learning the backend of linuxcnc, quite complex under the hood!

Please Log in or Create an account to join the conversation.

01 Apr 2024 00:51 - 01 Apr 2024 00:55 #297317 by andyandy26
This post got mangled by the edit, so I reposted below.
Last edit: 01 Apr 2024 00:55 by andyandy26.

Please Log in or Create an account to join the conversation.

01 Apr 2024 00:56 #297319 by andyandy26
So I've tried implementing the following at the end of my M22 command (that displays the dialog box)
return INTERP_OK

However this gives the following error on opening a program file.
G-Code error in setup1.ngc
Near line 0 of
pycall: remap.m22:
StopIteration: INTERP_OK

The code still will execute when run, however the issues persists where the G0 rapid move occurs after the M22, and the M22 occurs a second time after the M6.

After some reading of other posts:
Indicates that I shouldn't be returning an argument after the yield (no INTERP_OK)?

Does the documentation have any examples of this usage I can read into?

Please Log in or Create an account to join the conversation.

01 Apr 2024 08:54 #297349 by Aciera
There seems to be a fair bit of confusion about how to actually do it properly and I'm afraid I cannot give you any definite answers but I have recently completed a fairly substantial remap which seems to be working fine.
Here is part of it that may give you some ideas:

Warning: Spoiler!

Please Log in or Create an account to join the conversation.

01 Apr 2024 09:02 #297350 by Aciera
What we certainly cannot do after 'yield INTERP_EXECUTE_FINISH' is use 'self.execute(...)' but I'm not having any problem using 'return INTERP_OK'.

Please Log in or Create an account to join the conversation.

04 Apr 2024 02:17 #297555 by andyandy26
Hi again, sorry for the delay in replying, got the flu and it's been kicking my butt...

Thank you Aciera, with your help I did work out a solution to this, mostly using trial and error, using the following python code did the trick:
import sys
from interpreter import *
from tkinter import *
#from util import lineno

toolOffset = 0.0
nextTool = 0.0

def setToolOffset(self, dialog, entry):
    global toolOffset
    val = entry.get()
    if val.isdigit:
        toolOffset = float(val)

def m10_prolog(self, **words):
    if not self.task: 
        return INTERP_OK
    sys.argv  = [""]
    #Stop spindle and raise head
    self.execute("G53 G0 Z0") 
    return INTERP_OK

#M10 Pxx where xx is tool number
def m10(self, **words):
    if not self.task: 
        return INTERP_OK
    sys.argv  = [""]

    if not hasattr(sys, 'argv'):
        sys.argv  = [""]

    global nextTool, toolOffset

    # inspect controlling block for relevant words, get tool number
    c = self.blocks[self.remap_level]
    nextTool = float(c.p_number) if c.p_flag else 0
    #Request new tool offset
    dialog = Tk()
    dialog.title("Enter tool offset...")
    Label(dialog, text="OFFSET").grid(row=1)
    entry = Entry(dialog)
    entry.grid(column=1, row=1)
        entry.insert(0, self.params[_OFFSET])
    b1 = Button(dialog, text='OK', command=lambda: setToolOffset(self, dialog, entry))
    b1.grid(row=2, column=0, sticky=W, pady=4)
    b1.bind('<Return>', lambda x: setToolOffset(self, dialog, entry))

    #Block the code from continueing whilst listening for events on button
    self.execute("G10 L1 P%f Z%f" % (nextTool, toolOffset)) #Set tool offset in tool table
    self.execute("T%f M6 G43" % (nextTool)) #Request tool change to new tool and set Z offset from tool table

    return INTERP_OK

With remap:
REMAP = M10 modalgroup=10 argspec=P python=m10 prolog=m10_prolog 

The error I was getting was seemingly because if you had a yield in one spot (the end), you need to have them before EVERY return. I could be wrong though.

I had to separate the prelog routine to first raise the head, as if I did this in the same python function, it would get thrown into the queue, and wouldn't action until after the Tk dialog box got destroyed. 

Also I found that if I separate the Tx M6 G43 into two separate self.execute lines, then the G43 seems to occur before the preceeding G10?

I think the interpreter has a funny way of queueing the code, I'm sure that over time I'll get better versed with it.
For now it's working though, so I'm happy!

So when I order an M10 Pxx (my remap);
 - my head raises to max height,
 - asks for the new tool offset (tool Pxx), this gets loaded into the tool table,
 - then asks me to place the tool into the spindle (through QTDragon's manual tool change).
 - The current tool is then set with the tool offset and the program continues 

Thanks again for your help!

Please Log in or Create an account to join the conversation.

Time to create page: 0.095 seconds
Powered by Kunena Forum