This is a generic question for understanding the behavior of the SET_GCODE_VARIABLE command, not related to a specific printer.
My goal was to have a variable that can be either initialized to a specific value or set to -1 to make the macro implementation set the actual value in an automated fashion.
In my simplified example below I wanted to create a variable that I initially set to -1. Whenever the macro detects that it is smaller than 0 it would be set automatically, in the simplified example to 0.
[gcode_macro foobar]
variable_myvar: -1
gcode:
M118 BEFORE {myvar}
{% if myvar < 0 %}
M118 CATCH
SET_GCODE_VARIABLE MACRO=foobar VARIABLE=myvar VALUE={0}
{% endif %}
M118 AFTER {myvar}
My expectation here was that the if condition is met, given that the variable has the value -1, just for the SET_GCODE_VARIABLE macro setting it to 0 then.
The actual behavior though is that the BEFORE debug output produces -1 (as expected, the if condition obviously is met (as seen by the CATCH output, also expected), but then the AFTER debug output still produces -1, though I would have expected SET_CGODE_VARIABLE to change that value.
Obviously, there is something I didn’t fully understand about the construct I am using. If someone could explain to me what I am doing wrong and optimally explain how to fix it, I would be grateful.
Templating happens before execution. When myvar is -1, this is the output of templating that macro:
M118 BEFORE -1
M118 CATCH
SET_GCODE_VARIABLE MACRO=foobar VARIABLE=myvar VALUE=0
M118 AFTER -1
Once this code runs the variable’s value will be updated, but execution can’t reach back in time and affect the templating.
Native Jinja variables are in some ways the opposite: modifying them only applies to the current template evaluation, not to future executions. You can combine the two to have a variable that updates as you go through the template, and is persisted using SET_GCODE_VARIABLE when the code runs.
[gcode_macro foobar]
variable_myvar: -1
gcode:
{% set _myvar = myvar %}
M118 BEFORE {_myvar}
{% if _myvar < 0 %}
{% set _myvar = 0 %}
M118 CATCH
SET_GCODE_VARIABLE MACRO=foobar VARIABLE=myvar VALUE={_myvar}
{% endif %}
M118 AFTER {_myvar}
Another option is to split the response into a separate macro, since that macro will be templated before it’s executed. Something like this (but using your variable instead of the printer state):
Thank you so much! I was not aware that those variables get expanded early but expected the behavior as you pointed out the native Jinja variables do. With that information, I am sure I can now proceed with my project.
Thanks, I will keep that implementation in mind. It would likely be overblown for my current purpose since the native variables recommended above perfectly fulfill my needs.
Spontaneously, I see the main advantage of this DynamicMacros implementation during the development phase to update the macros without needing to reboot the machine and consequently home all axes after each change.
I really wish you wouldn’t recommend that to people. It’s better to teach people how to use the existing features correctly than to encourage them to make questionable modifications to their Klipper install which will make it harder for them to get support.