Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macros don't work with gcode #1158

Open
nesetburak opened this issue Dec 5, 2018 · 25 comments
Open

macros don't work with gcode #1158

nesetburak opened this issue Dec 5, 2018 · 25 comments

Comments

@nesetburak
Copy link

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

@carneeki
Copy link
Contributor

carneeki commented Dec 6, 2018

@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?

@nesetburak
Copy link
Author

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.

@carneeki
Copy link
Contributor

carneeki commented Dec 6, 2018 via email

@winder
Copy link
Owner

winder commented Dec 6, 2018

@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).

@ione2k
Copy link

ione2k commented Jul 22, 2019

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.

@winder
Copy link
Owner

winder commented Jul 22, 2019

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:

To replace the "remover" with a "renamer" some tweaks will be needed in the GUI, to add/remove/save an extra parameter:

@CNCNoob
Copy link

CNCNoob commented Mar 11, 2020

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

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 18, 2021

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'.

@winder
Copy link
Owner

winder commented Jul 18, 2021 via email

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 18, 2021

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
Copy link
Contributor

AndyCXL commented Jul 19, 2021

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.

@winder
Copy link
Owner

winder commented Jul 19, 2021

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"

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 19, 2021

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 :"

@winder
Copy link
Owner

winder commented Jul 19, 2021 via email

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 20, 2021

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

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 20, 2021

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.

@winder
Copy link
Owner

winder commented Jul 20, 2021

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.

@AndyCXL
Copy link
Contributor

AndyCXL commented Jul 20, 2021

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
Copy link
Contributor

AndyCXL commented Jul 21, 2021

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
Copy link
Contributor

AndyCXL commented Jul 22, 2021

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
Copy link
Contributor

AndyCXL commented Jul 23, 2021

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
Copy link
Contributor

AndyCXL commented Aug 5, 2021

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).

@marshr32
Copy link

marshr32 commented Apr 4, 2022

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.

@AndyCXL
Copy link
Contributor

AndyCXL commented Apr 4, 2022

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...

@marshr32
Copy link

marshr32 commented Apr 4, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants