Help with Macro: SET_GCODE_VARIABLE doesnt set my variable

I’m trying to make myself a macro for some calibration prints, to make my life a bit easier. I have an issue in my following Macro:

[gcode_macro HEAT_TEST]
description: Print to determine and the optimal print temperature @ 100mm/s
variable_temp_down: 1
gcode:
{% set TEMP = printer[“gcode_macro Calibration_Tool”].extr_temp|int %}
SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={TEMP}

M104 S{temp_down}
RESPOND TYPE=error MSG=‘{temp_down}’

For some reason, my variable_temp_down is not getting set by SET_GCODE_VARIABLE. In another macro, the same line, works.
I did some testing: the temp_down gets parsed to M104 and RESPOND shows in the console the value of the variable is set to, in this case “1”, if I change the 1 to for example 100, that works too, but ever value I set in the SET_GCODE_VARIABLE, does not get parsed to my variale_temp_down, even if I bypass the {% set… %} and directly put a number as value, instead of the {TEMP}, does not work.

For some context, this macro simply prints a heat tower and lowers the extruder temperature by 5, based on the Print temperature it starts with.

klippy.zip (7.7 MB)

You can use a compression tool like 7zip :wink:

2 Likes

klippy.zip (7.7 MB)

True, had’nt any installed at the time. Heres klippy.zip

Honestly?

You included 3D model gcode files into your printer.cfg?

That is anything but good.

  • It blows up the config file for no reason.
  • If there is a issue, you can’t cancel them because a macro can’t be cancelled.

For your issue:

I see, it’s not the best Idea, I saw it in a video, and read a post about something similar, using various macros to help calibrate the printer. It thought it’s a neat idea, anyway I’m still a Klipper novice after all :slight_smile:

Me, personally, I don’t mind if the config “blows” up, I keep it clean by outsource parts of my config into separate files.
I noticed that I couldn’t cancel the macro, but I think I could live with that. Just in Case, there’s always the emergency stop. But yeah, it’s anything but elegant.

If there’s a better solution, let me know. I haven’t found a way to start a print using a macro and alter the print parameters beforehand.

For my problem, I read it, and his solution was: “So, the mystery is solved… Turns out, parameters of macros need to be defined in ALLCAPS”
I had this issue before and made sure not to make the same mistake twice. So either I’m blind, or the problem is a different one.

Thank you for your time, I appreciate it :slight_smile:

My recommendation:

Thanks for the tip. I already use my own start gcode.
So basically you recommend, to (re)slice the Test Print every time, when I have to use other parameters (If I understand you correctly, my English isn’t my native tongue).
I hoped to streamline it and do it easier/faster, straight out of the Kipper interface, similar to the bed mesh validation pattern from Marlin (G26).

Yes

Well, everyone has his own opinion what streamlining means. For me dialing in a filament means determining:

  • Temperature
  • Flow
  • Z-Offset
  • Pressure Advance
  • Sometimes velocity

I would never ever try to cram this into some macros. But as I said, everybody has his own way of working

I think, I least gonna play around with it and see where it gets me, maybe i lern something on the way :slight_smile:

Anyway, to put aside what I’m doing makes sense or not, there’s still the problem that SET_GCODE_VARIABLE, not setting my variable.

I wrote a little Test Macro, to narrow it down, and I noticed something.

[gcode_macro Test]
variable_test: 1
gcode:
{% set X = params.NUMBER|default(2)|int %}
SET_GCODE_VARIABLE MACRO=Test VARIABLE=test VALUE={X}
RESPOND TYPE=error MSG=‘{test}’

When I run this macro, no matter what I number I put in, for example 3, I always get the variable is set to in the first place, in this case 1, when I run it again, only then it gets the number i putted in, in this case 3. Now when put in for example 5 and run the macro, I again get only 3, and when I run it again, only then it sets to 5.

That would explain why my HEAT_TEST macro, don’t work, because when the variable is read the first time, it first parsed the 0, no matter what SET_GCODE_VARIABLE set it to prior.
Do I misunderstand here something?

That’s because macros are evaluated before they are run. All the variables are “translated” before the macro is executed so if the macro itself changes the value of a variable, that change won’t be reflected during the same execution of the macro. To work around this, create a second macro called something like TEST_RESPOND, have that macro do the RESPOND TYPE=error MSG=‘{test}’ line, and call TEST_RESPOND at the end of TEST. Keep in mind that TEST_RESPOND will need to lookup the value of the test variable from the TEST macro.

2 Likes

That’s explains a lot, thanks. I did as you said, and indeed, it worked … with the Test macro.
I implemented it into my Test Print Macro aaaand … nope, still something is wrong here, but now I get another error message: Requested temperature (-5.0) out of range (0.0:300.0)
I know what it means, but I don’t know where the error is lies known, it’s still not setting the variable and calculate 0 - 5.

Here’s the macro, simplified:

[gcode_macro TEMP_DOWN]
gcode:
M104 S{printer[“gcode_macro HEAT_TEST”].temp_down|int}

[gcode_macro HEAT_TEST]
description: Print to determine and the optimal Printtemperature @ 100mm/s
variable_temp_down: 0
gcode:
{% set TEMP = printer[“gcode_macro Calibration_Tool”].extr_temp %}
SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={TEMP}
START_TUNING_PRINT


Bunch of gcode till height reaches 5mm

SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={temp_down - 5}
TEMP_DOWN


Bunch of gcode till height reaches 10mm

SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={temp_down - 5}
TEMP_DOWN


This goes on till the Print is finished

END_PRINT

klippy.zip (5.4 MB)

When HEAT_TEST is evaluated, the value of temp_down is 0. So every time temp_down appears in the macro, it will be replaced by 0 when the macro is executed. In the snippet you posted after height reaches 5mm you have this line:

SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={temp_down - 5}

Since temp_down was 0 when the macro was evaluated, this command changes the value of the temp_down variable to -5, which is what the TEMP_DOWN macro sees when it’s called, hence the error.

To address this, you can track the changing variable through the macro execution like this:

[gcode_macro HEAT_TEST]
description: Print to determine and the optimal Printtemperature @ 100mm/s
variable_temp_down: 0
gcode:
    {% set TEMP = printer[“gcode_macro Calibration_Tool”].extr_temp %}
    SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={TEMP}
    START_TUNING_PRINT

    ;…
    ;Bunch of gcode till height reaches 5mm
    ;…

    {% set TEMP = TEMP - 5 %}
    SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={TEMP}
    TEMP_DOWN

    ;…
    ;Bunch of gcode till height reaches 10mm
    ;…

    {% set TEMP = TEMP - 5 %}
    SET_GCODE_VARIABLE MACRO=HEAT_TEST VARIABLE=temp_down VALUE={TEMP}
    TEMP_DOWN

    ;…
    ; This goes on till the Print is finished
    ; …

    END_PRINT

This way when the macro is evaluated, the value of TEMP gets progressively updated as expected, then you can “store” that value in the macro variable so it can be accessed externally.

Of course, if this is your ultimate use case for this, you could probably skip using the variable_ and second macro altogether and simply do this:

[gcode_macro HEAT_TEST]
description: Print to determine and the optimal Printtemperature @ 100mm/s
gcode:
    {% set TEMP = printer[“gcode_macro Calibration_Tool”].extr_temp %}
    START_TUNING_PRINT

    ;…
    ;Bunch of gcode till height reaches 5mm
    ;…

    {% set TEMP = TEMP - 5 %}
    M104 S{TEMP|int}

    ;…
    ;Bunch of gcode till height reaches 10mm
    ;…

    {% set TEMP = TEMP - 5 %}
    M104 S{TEMP|int}

    ;…
    ; This goes on till the Print is finished
    ; …

    END_PRINT

It worked, finally, thank you very much :slight_smile: :slight_smile: :slight_smile:
I can’t believe how easy the solution were, and why I didn’t come up with it myself.
For clarification:
are {% set %} local variables while variable are global?
Is the int in M104 S{TEMP|int} needed for it to work?

You can think of it like local/global, but they don’t work precisely like that. It’s better to think of variable_whatever as a user-definable object state that can be accessed across macros, subject to the limitations of the macro-evaluation logic discussed above. And yes, {% set is a local declaration that is used only for that particular execution of that macro that time.

The |int casting isn’t needed for the macro to work. M104 can accept a non-integer number.

1 Like

To add to @theophile excellent answer. You can share these variable objects across different macros like

[delayed_gcode i_depend_on_test]
gcode:
    {% set vars = printer["gcode_macro TEST"] %}
    M117 {vars.my_shared_variable}

[gcode_macro TEST]
variable_my_shared_variable: -1
gcode:
    SET_GCODE_VARIABLE MACRO=TEST VARIABLE=my_shared_variable VALUE={params.MY_SHARED_VARIABLE|default(10)}
    UPDATE_DELAYED_GCODE ID=i_depend_on_test DURATION=0.01

So, once TEST MY_SHARED_VARIABLE=100 is executed, then i_depend_on_test is called and can access the variable’s content, which then is 100.

I understand, thank you for explaining it to me :).

My Macro is now working great, I can do now 4 test prints with them and I don’t have to reslice every time, only to change the Temperature, because I have a new filament to print :), I outsourced it to other files and put them in a folder, to keep the printer config nice and tidy.

If some are interested, I can share it here, just let me know :slight_smile:

Of course, if it is working then go ahead and post it in the “Macro” section. Preferably

  • attached as cfg file
  • including a description, what it does and how it does it
  • potentially some details if, e.g. the bed size is relevant to not crash other users printers (well, luckily, Klipper would error before doing it but anyway)

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.