Open benagricola opened 2 months ago
I have implementations of this functionality that might be useful:
1: Basic implementation that works exactly the same way as M291
responses - stored on GCodeBuffer
- essentially equivalent to storing return values in a global variable.
2: Slightly more advanced implementation, grabs the previous machine state and writes the return value as a local variable in the parent, so it is cleared up when the parent macro (or file, I guess) is finished. In this case, the retval
named constant simply acts as a standard way of reading the local variable (currently named var._mrv
).
If either of these approaches are acceptable, I'm happy to submit a PR.
Is your feature request related to a problem? Please describe.
It would be helpful if macros had a well-defined API to return data to their calling macro or file, so that there is an obvious single way of passing data. This may open up more advanced custom macro writing where specific behaviour can be more easily broken down into files to e.g. perform calculations.
It would allow for more advanced gcode to be written by multiple people while allowing code to interact in a standard manner (which we already have for getting data into macros, in parameters).
Describe the solution you propose.
Add an
R
parameter toM99
(return from macro), that takes an RRF Expression.When
M99
is executed in the called macro with this parameter, set aNamedConstant
that is available from the calling macro, for exampleretval
. This is almost exactly how theinput
variable works when usingM291
to select aninput
value.Ideally, this
retval
constant would only exist in the local scope of the calling macro, and if a macro were to callM99
without theR
parameter this value would be set tonull
.Describe alternatives you've considered
When writing complex macros or sets of macros (in my case, probing for CNC machines), returning values from a macro to wherever it was called can be performed by setting a global variable in the called macro and reading it in the calling macro.
However, this requires boilerplate code in each calling / called macro to manage the global variable, and once created, that variable will always exist (taking up space in the object model to store the variable name even if the value is
null
).It is up to macro writers to decide what their global variable will be called, and with macros written by multiple people (for example with macro libraries) it is very likely that the global namespace will be polluted by return variables.
The other side of this is if there is any mismanagement of the global variable, a calling macro might receive unexpected data and cause errors.
Another alternative I have considered is to allow functions to be executed from a file as part of a meta gcode expression, but this looks to be much more of a task to implement than using the existing macro functionality.
Provide any additional context or information.
Discussion here
As an example, I need absolute co-ordinates all the time when calculating probing moves and positions. Originally I started with using
machinePosition
, but this is problematic because it is affected by backlash compensation.To get around this, I use
userPosition
but add it to the workplace and tool offsets to find the absolute co-ordinates, something like this (untested code, going from memory):This code has to exist everywhere I need the absolute machine position, which means repeating myself often and also means I have to split it into multiple lines due to line length limits.
With an obvious return feature in
M99
, I could rewrite this as a "function macro" that simply returns the right information.