Universal-G-Code-Sender icon indicating copy to clipboard operation
Universal-G-Code-Sender copied to clipboard

macros don't work with gcode

Open nesetburak opened this issue 6 years ago • 25 comments

Feature request

How can ı use macros with g code. ı am UPLOAD this gcode; G21 G90 G01X10
T1 M6 spindle move to X10 coordinate but don't start ''T1 M6'' macros macro_ugs_t

Problem description

macros don't work with gcode.this is not a bug but ı don't solved this problem.

Expected Behavior

ı don't want to push macros button. 0 1 if ı send a special code from Gcode file, macros name catch this code and start macros GCode.

Thank you for interst winder

nesetburak avatar Dec 05 '18 01:12 nesetburak

@nesetburak UGS will try to send this to the controller rather than process the command a macro; and GRBL, TinyG and Smoothie still don't support M6 tool change yet (I only use GRBL).

Workaround:

I have an idea that may make it easy to add to UGS, but for the moment, you might need to use a "Find / Replace" strategy to edit the G-code in Notepad (or VS Code / Atom / Brackets, any of these editors are good with G-code extensions).

Recommended approach for entry level systems like this is to have tool changes in separate files, and to use something like the Workflow plugin, and to touch / probe either manually (such as the macro you have written) or to use the Probe plugin.

My implementation idea (for developers):

Inside Tools -> Options -> UGS -> Controller Options there's a regular expression remover. If we change this from a 'remover' to a 'replacer', we can keep existing functionality with blank text, but a 'replacer' would add some very powerful things like tool changing, and some canned cycles. Want me to investigate this?

carneeki avatar Dec 06 '18 11:12 carneeki

unfortunately solved my problem with other programs(uccnc). but ı want to use UGS.

@carneeki your idea so good."regular expression remover". maybe will add new function just like "regular expression changer"

But why UGS don"t use or support macro. what is macro's complication. for example mach3 ,uccnc... supports macro and hasn't any problem.

nesetburak avatar Dec 06 '18 12:12 nesetburak

Mach3 has at least 17 years of development time, and was a fork of LinuxCNC (back when it was called EMC), it has had time to implement things like this. UCCNC since at least 2011, maybe earlier. It's just a matter of time. :)

Looking at the UCCNC page, macro support looks like it would be very useful for so much more than just my examples of canned cycles and tool change - so I'll look at it this weekend, if it's a simple change, I'll post a commit and do some simple tests, but I might need you to test it to see if it works the way you expect it. I'm a little nervous about regular expressions and end users as regular expressions have some funny syntax and can be quite scary if you haven't seen them before, but simple "find/replace" should be just fine. More complex things like drill cycles may need more time to work out, but right now, I think most of us just use CAM to expand canned cycles to many G0/G1 codes.

I'll update this ticket in a few days with my findings.

On Thu, 6 Dec 2018 at 23:34, nesetburak [email protected] wrote:

unfortunately solved my problem with other programs(uccnc). but ı want to use UGS.

@carneeki https://github.com/carneeki your idea so good."regular expression remover". maybe will add new function just like "regular expression changer"

But why UGS don"t use or support macro. what is macro's complication. for example mach3 ,uccnc... supports macro and hasn't any problem.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/winder/Universal-G-Code-Sender/issues/1158#issuecomment-444856570, or mute the thread https://github.com/notifications/unsubscribe-auth/AAdYqLlhZsGO_p2QZa5ydV8pOWErQOOdks5u2Q7wgaJpZM4ZB0TN .

-- Adam "carneeki" Carmichael p: +61 415 37 1990 w: http://bigneek.com e: [email protected] i: 2207644

carneeki avatar Dec 06 '18 12:12 carneeki

@carneeki Your Remover -> Replacer idea sounds like a great improvement, and a Macro Expander would be an interesting feature as well. I think we're only scratching the surface on what could be done with the gcode processing engine in UGS. I don't know if that would be the best way to implement canned cycles though, having a dedicated canned cycle expander might be necessary.

Both of these should be almost trivial to implement due to the existing plugin engine. You can see the existing Pattern remover is pretty basic. Most of the work for that feature is GUI related. Even though it was a simple bit of code, it was useful enough trivialize some of the other features (like the whitespace and comment processors).

winder avatar Dec 06 '18 13:12 winder

Hi All, is there any progress on this? It would be great if UGS could intersect parts of the Gcode and transform them in macros especially for an Automatic Tool Changer as bCNC and CNCjs are doing with M6.

ione2k avatar Jul 22 '19 06:07 ione2k

If someone wants to take a stab at this, it's a great first project in UGS. The Processor interface is not very complicated and everything is configured with json files and has very good test coverage.

You can see a simple one here which detects M3/M4 and inserts an extra command: https://github.com/winder/Universal-G-Code-Sender/blob/master/ugs-core/src/com/willwinder/universalgcodesender/gcode/processors/SpindleOnDweller.java

Arguments (i.e. pattern/substitution) are parsed out of a file here here: https://github.com/winder/Universal-G-Code-Sender/blob/4da7db7d9ed144dca9a2b442cf8b44af1dd48441/ugs-core/src/com/willwinder/universalgcodesender/gcode/util/CommandProcessorLoader.java#L193

To replace the "remover" with a "renamer" some tweaks will be needed in the GUI, to add/remove/save an extra parameter: https://github.com/winder/Universal-G-Code-Sender/blob/c6c85d53c99cbe7cfe99875cc1d188b9e3438a67/ugs-core/src/com/willwinder/universalgcodesender/uielements/panels/ControllerProcessorSettingsPanel.java#L151

winder avatar Jul 22 '19 13:07 winder

Is there anything that's happened on this????

CNCNoob avatar Mar 11 '20 03:03 CNCNoob

I would like to get into UGS, and have some level of coding experience (mostly SQL, Python and a little C/C#). This 'Replacer' sounds like a good introduction... If the enthusiasm and (modest) experience qualifies me, then I am up for trying - I use the 'Remover' in my current setup to identify Tool Change entries and strip them as " ^[mM]6\s*[tT][0-9].*$ ".

The Grep-like pattern to identify patterns in the stream of gcode text is well known and already defined, the 'remover' processor contains exactly this functionality. This initial framework can be taken as a starting point. So the questions will become:

  1. Will a second GUI field be required to supply the replacement string or pattern? Grep is (to my understanding) a pattern finder, so the 'and then replace with' has to be able insert any new content not in the original text, and the place in the GUI for the user to define this new text.
  2. I can assume that the new text may well want elements of the original 'hopped across', eg: if there was a number to retain, that the new text will use - using Grep-like functionality and the supplied match expression can yield the 'donor' text, which may need further processing to identify a particular element from it to hop across to the output.
  3. I can also assume that the scope of what is proposed is 'line at a time', processing each line on its own and no concept of 'whole file' or 'previous matches or content'.
  4. Some consideration will be needed to use cases where 'I just wish to insert the following, it is not replacing anything'. This could be achieved through inclusion of a 'donor text' coming from the original post-processor - say for example a special comment string that can be replaced with the supplied string.

It would be very useful to have some 'I would like to/I need to' examples of use cases so I can form or refine the basis.

I could also do with pointers to HowTo GitHub and make proposed contributions etc. As I said, 'some experience'.

AndyCXL avatar Jul 18 '21 08:07 AndyCXL

Hi Andy, this is a good first project.

The processor system is fairly self contained, and has some good documentation: https://winder.github.io/ugs_website/dev/gcode_processor/

  1. Maybe a 3rd column can be added to provide the new command.

  2. There are regex capture groups for hopping values across, maybe borrow sed syntax for inserting the captured text in the replacement? It could also do something like lookup a macro and use that as a replacement.

Regex: ^[mM]6\s*tT$ Replacement; ToolChangeMacro\1

  1. The processor is a standalone object which processes every line, so it can cache parts of the history if needed. The processor framework keeps track of things like the current location and state, so those are provided to the process call.

The biggest limitation is that processing happens ahead of time, so a processor can't interrupt a running program in real time.

  1. I think this is a subset of the Regex case, the design you mentioned would support it.

For development we use a standard GitHub fork/pr workflow. There is some information about how that works here: https://gist.github.com/Chaser324/ce0505fbed06b947d962

On Sun, Jul 18, 2021, 4:41 AM AndyCXL @.***> wrote:

I would like to get into UGS, and have some level of coding experience (mostly SQL, Python and a little C/C#). This 'Replacer' sounds like a good introduction... If the enthusiasm and (modest) experience qualifies me, then I am up for trying - I use the 'Remover' in my current setup to identify Tool Change entries and strip them as " ^[mM]6\s*[tT][0-9].*$ ".

The Grep-like pattern to identify patterns in the stream of gcode text is well known and already defined, the 'remover' processor contains exactly this functionality. This initial framework can be taken as a starting point. So the questions will become:

  1. Will a second GUI field be required to supply the replacement string or pattern? Grep is (to my understanding) a pattern finder, so the 'and then replace with' has to be able insert any new content not in the original text, and the place in the GUI for the user to define this new text.
  2. I can assume that the new text may well want elements of the original 'hopped across', eg: if there was a number to retain, that the new text will use - using Grep-like functionality and the supplied match expression can yield the 'donor' text, which may need further processing to identify a particular element from it to hop across to the output.
  3. I can also assume that the scope of what is proposed is 'line at a time', processing each line on its own and no concept of 'whole file' or 'previous matches or content'.
  4. Some consideration will be needed to use cases where 'I just wish to insert the following, it is not replacing anything'. This could be achieved through inclusion of a 'donor text' coming from the original post-processor - say for example a special comment string that can be replaced with the supplied string.

It would be very useful to have some 'I would like to/I need to' examples of use cases so I can form or refine the basis.

I could also do with pointers to HowTo GitHub and make proposed contributions etc. As I said, 'some experience'.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/winder/Universal-G-Code-Sender/issues/1158#issuecomment-882021955, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA6URMUSW5PV54VNWYZ7VLTYKHRZANCNFSM4GIHITGQ .

winder avatar Jul 18 '21 12:07 winder

A little reading up on grep and sed, plus thinking how 'replacer' command would integrate and/or replace 'remover' command leads me to believe that replacer with a blank 'replace with' string will give identical results to the current 'remover', meaning that any existing JSON entries could be arranged to seamlessly transition to the new 'replacer' command.

My proposal is therefore;

  • Add an extra String field to the JSON config/file to hold the 'replace with' text
  • Adapt the UI config to retrieve, display, save and as appropriate delete with this extra string present
  • Arrange the change such that an existing user install will transition from 'remover' to 'replacer' with no user action required, beyond noticing that the capabilities of the command have been extended
  • First Functionality goal:
  • 1> Keep the grep 'find what to remove or replace' functionality to identify the line/characters in the passed gcode stream
  • 1> Simply replace this with static text as populated in the 'replace with' string. If this string is empty, return an empty string and thus behave identically to 'remover'
  • Second Functionality goal:
  • 2> Create the ability to hop some aspect of the original, grep identified string across to the return string. Suitable syntax (based on grep or sed) will need to be defined or borrowed
  • 2> Include in this syntax the ability to specify and thus run one or more named macro(s) that return(s) a string and will become part of the return string

It is a presumption on my part that compiling the package locally is necessary to both prove the code compiles, but also for initial testing purposes. I have the latest version of Net Beans Dev Environment, but seem to be having difficulties with it - is there a version best suited to this work? I would also like to develop a plugin at some point, so the same question and hopefully same answer with that in mind

AndyCXL avatar Jul 18 '21 22:07 AndyCXL

A further thought... If the existing JSON string 'pattern' is interpreted as grep or sed, depending on what is there, then maybe only one field is needed. If pattern contains, say " ^[mM]6\s*tT$ " then is is a grep only sequence, and should be treated as if a sed " s/^[mM]6\s*tT$/ " string and provide an empty replacement for the match (remove). If pattern contains " s/^[mM]6\s*tT$/ " then is is a deliberate remove command, whereas " s/^[mM]6\s*tT$/M6T1 " would replace the match with M6T1. The prefix of s/ is the data signature that this IS sed, no prefix means assume it is s/grep/ and behave as remover.

AndyCXL avatar Jul 19 '21 06:07 AndyCXL

If I'm understanding correctly, these are the options you're choosing between:

  1. New "replace with" field in table, this defaults to an empty string for backwards compatibility (removal) and can be filled in with something else for the new replacement feature. For example "^[mM]6\s*tT$" and "M6T1" to use T1 for all toolchanges.

  2. Add some new syntax to the "pattern" field to define the entire sequence inline. For backwards compatibility "^[mM]6\s*tT$" implicitly translates to "s/^[mM]6\s*tT$/", and the new functionality can be used with "s/^[mM]6\s*tT$/M6T1".

I slightly prefer the first option, it seems like it would be easier to use. But both would work, there is a help button so a full description of how to define the pattern can be written. (see ugs-core/src/resources/MessagesBundle_en_US.properties, sender.help.patternRemover and settings.processors.help"

winder avatar Jul 19 '21 12:07 winder

I have First Functionality written, successfully builds and runs. What I am struggling with is debugging what is happening...

If I set the pattern, in preferences>UGS>Controller Options, to be " s/^[mM]6\stT$ " it works, and successfully 'removes' the M6T from the command. If I set the pattern to be " s/^[mM]6\stT$/M123 " to replace the M6T with something 'silly' to see it working, it fails to remove the M6T at all and the M123 makes no appearance as far as I can tell - grbl complains about the M6T command.

The process I have followed to achieve this is in PatternRemover to split the regexPattern on "/" into String[] variable s3, like sed does, and test if the first String[] element is "s" with s3[0].equals("s") - if it is, then compile p with p = Pattern.compile(s3[1]) and if there is a third element in s3 .add this to a new final private List called r to be available to ProcessCommand. If there is no third element, I simply r.add(""); to behave as a 'remover'. Nice and simple.

In processCommand I then have ret.add( p.matcher(command).replaceAll(r.get(0)) ); which, I believe, should work. But the testing says 'not quite'.

With more enthusiasm than knowledge... Any pointers as to how I can set about resolving and debugging what is happening? I have tried using System.out.println() to get a debug transcript from within processCommand(), but I get no output despite having read how earlier authors have done just this (eg: within GcodeModel.java outputting "Num Line Segments :"

AndyCXL avatar Jul 19 '21 23:07 AndyCXL

Writing some tests is probably the easiest way to debug this. I don't think the pattern processor has any tests, but you can use one of the other files here as a template: https://github.com/winder/Universal-G-Code-Sender/tree/master/ugs-core/test/com/willwinder/universalgcodesender/gcode/processors

Once you have a test you can also try running with the debugger to help inspect the code while it runs.

On Mon, Jul 19, 2021, 7:09 PM AndyCXL @.***> wrote:

I have First Functionality written, successfully builds and runs. What I am struggling with is debugging what is happening...

If I set the pattern, in preferences>UGS>Controller Options, to be " s/^[mM]6\stT$ " it works, and successfully 'removes' the M6T from the command. If I set the pattern to be " s/^[mM]6\stT$/M123 " to replace the M6T with something 'silly' to see it working, it fails to remove the M6T at all and the M123 makes no appearance as far as I can tell - grbl complains about the M6T command.

The process I have followed to achieve this is in PatternRemover to split the regexPattern on "/" into String[] variable s3, like sed does, and test if the first String[] element is "s" with s3[0].equals("s") - if it is, then compile p with p = Pattern.compile(s3[1]) and if there is a third element in s3 .add this to a new final private List called r to be available to ProcessCommand. If there is no third element, I simply r.add(""); to behave as a 'remover'. Nice and simple.

In processCommand I then have ret.add( p.matcher(command).replaceAll(r.get(0)) ); which, I believe, should work. But the testing says 'not quite'.

With more enthusiasm than knowledge... Any pointers as to how I can set about resolving and debugging what is happening? I have tried using System.out.println() to get a debug transcript from within processCommand(), but I get no output despite having read how earlier authors have done just this (eg: within GcodeModel.java outputting "Num Line Segments :"

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/winder/Universal-G-Code-Sender/issues/1158#issuecomment-882919599, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA6URIAP6E475U7IJZS52DTYSWB7ANCNFSM4GIHITGQ .

winder avatar Jul 19 '21 23:07 winder

Brilliant - got a test script setup and debug running with breaks and watches. Nice.

AndyCXL avatar Jul 20 '21 09:07 AndyCXL

Is there a trigger within the pattern processor architecture to flag that the user has edited the regexPattern and this will need to be re-compiled? It appears for now that this is parsed and compiled once and used as-is, or have I missed something? Nearly complete on Functionality Goal 1 (auto detect regex or sed, simple text replacement), just testing every scenario I can think of to be sure it is robust.

AndyCXL avatar Jul 20 '21 15:07 AndyCXL

I believe the processors are loaded when you open a gcode file. We should probably reload the gcode file if the processor config changes, but I don't think it happens currently.

winder avatar Jul 20 '21 16:07 winder

Understood. I think what I have is ready for a pull request, so will do that during this evening. I have ideas for how to hop values from the original matched regex via sed to the return pattern, and that may too facilitate accessing macro expansion - but the latter needs reading up from my part as to how to key into the macros.

AndyCXL avatar Jul 20 '21 16:07 AndyCXL

For Functionality Goal 2: looking at enumerating macros with getSettings().getMacros(), but need access to a backend instance. Where can I get hold of the current backend instance?

AndyCXL avatar Jul 21 '21 10:07 AndyCXL

The macro expansion code is working and robust, using sed " s/regex/%macroname% " syntax and has remained a simple piece of code too. I have run into an import find issue which means I will make one small adjustment to the code to switch off the macro expansion but leave its code in place so that the Replacer function can be merged in the meantime if seen as progress.

The commonly used "import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;" paired with a "Backend backend = CentralLookup.getDefault().lookup(BackendAPI.class);" call to get the instance and from that access to the macro list. I cannot fathom why this import fails as other packages make the same import reference and seem to be OK - but I get "package com.willwinder.ugs.nbp.lib.lookup does not exist" error. I overcame it by adding a dependency, but the application won't compile if so owing to a cyclic reference.

I could do with some advice on this, or a pointer to a non-backend dependent way to enumerate .getMacros(). I've left the withdrawn Pull Request in place so the code can be seen - in the PatternRemover package. @winder

AndyCXL avatar Jul 22 '21 21:07 AndyCXL

I have managed to resolve the cyclic dependency by including a 'provided' dependency back to UGSLib, and the app now builds and runs and tests successfully with macro expansion as part of PatternRemover. During testing I establish that a macro expansion does in fact happen when " s/M6T/%1% " is the sed pattern, and a macro with name "1" exists, and this test passes when a test command is passed "M6T". Excellent. Running the app with a real gcode file with a PatternRemover set to "s/M6T/%1%" and macro 1 defined as "G1X0Y0", then a line manually inserted in the gcode file with a line "M6T" results in "Skipping line: M6T" reported in the command console. Every other combination of regex or sed patterns, except those expanding a macro, work correctly (eg: "s/M6T/M6T0"). Tracing the line skipped origin in the source code into the AbstractContoller.java and in all likelihood the following;

public void commandSkipped(GcodeCommand command) Why has the command been skipped? Does invoking the backend to enumerate .getMacros() somehow trip the skipping? Any insight? The code for macro expansion tests out as fully working, but something in the larger ugs app entity gets involved and defeats it...

AndyCXL avatar Jul 23 '21 20:07 AndyCXL

The full functionality of ProcessorRemover to enable Replace and %macro% expansion is completed and tested, and a pull request made.

PatternRemover has been enhanced to support 'replace with' and %macro% expansion by introducing 'sed' syntax to the preferences/UGS/Contoller Options. 'sed' syntax is "s/regex to match/replacement text" so the following now all work;

  • M6T1 command in gcode, "M6T[0-9]+" enabled will REMOVE M6T1 as per original functionality
  • M6T1 command in gcode, "s/M6T[0-9]+/G21" enabled will REPLACE M6T1 with G21 if that is what the user desires
  • M6T1 command in gcode, "s/M6T[0-9]+/%1%" enabled will REPLACE M6T1 with whatever macro "1" is defined as by the user in the Gcode column. User must be aware that the result from macro 1 will be passed through as-is.
  • All REMOVES or REPLACES are logged under INFO to assist user debugging regex and %macro% settings. Confirmed working (Apple and RPi).

Found a typo in jog service.java where getStepSizeZ() was errantly against multiplyABCStepSize(), should have been getStepSizeABC(), which is corrected. Confirmed working (Apple and RPi).

AndyCXL avatar Aug 05 '21 15:08 AndyCXL

What ever happened to this idea? It's brilliant! It'd be really useful to be able to replace M06 with my tool change macro.

marshr32 avatar Apr 04 '22 04:04 marshr32

The pull request has been queued for months now, and I have openly stated that I am at the limit of my Java knowledge and thus a little assistance in getting this finished is needed (some 'code elegance' test is failing, despite a re-write to achieve 'elegance'). It's a shame as the product is really good and the early support for 5-axis grbl/machines is exciting too. If someone can give me some pointers as to what is wrong in the submitted pull request, I am happy to do some more work on this, but unless/until that I am stuck...

AndyCXL avatar Apr 04 '22 07:04 AndyCXL

Gah, that's a bummer. But thanks for your work thus far :)

marshr32 avatar Apr 04 '22 10:04 marshr32