What is the trick to using gcode_buttons in a macro?

Gday Guys,

I’m trying to measure nozzle offsets (x+,x-,y+,y-,z) using a series of microswitches attached to the bed. I thought that this would be simple task but I have run into the issue of the variables being evaluated at the beginning of the macro execution. I have tried having multiple macros one for querying the switches and another for preforming the step logic but no luck, i have also tried writing to a variable using press_gcode: but this hasn’t worked either.

Other people seem to be able to do nozzle probing with macros. so what is the trick ?

for info I have a EBB42 board on my heat bed setup as a canbus [MCU] and all the microswitches all query correctly from the console.

regards
Bryden Quirk

I have run into the issue of the variables being evaluated at the beginning of the macro execution.

I recommend using DynamicMacros. It fixes this problem.

I gave it a try it installed and setup ok but i still seem to have the same problem.

This is the code im testing it with in my dynamic.cfg file

[gcode_macro SWITCH_TEST]
gcode:
  {% for step in range(10) %}
  QUERY_BUTTON BUTTON=zswitch
  G4 P2000
      {% if printer["gcode_button zswitch"].state == 'PRESSED' %}
          M118 PRE SSED !!
      {% else %}
          M118 NOT PRES SED !!
    {% endif %}
   {% endfor %}

If you want a printer object to be updated in a Dynamic Macro, you need to have three empty lines before it. See Receiving Variable Updates - Klipper Dynamic Macros.

Please use the Preformatted Text feature of the forum editor for your code snippets.

Format

ok I finally found the correct combination of spaces, tabs and carriage returns to get kipper to start without an error with this code

[gcode_macro SWITCH_TEST]
gcode:
  {% for step in range(10) %}
   QUERY_BUTTON BUTTON=zswitch
   G4 P2000     
      {% if printer["gcode_button zswitch"].state == 'PRESSED' %}
      M118 PRE SSED !!
      {% else %}
          M118 NOT PRES SED !!
      {% endif %}
      {% endfor %}

except that it seems to have stopped my loop from working correctly
I assume that this is because the whitespaces are resetting the step variable somehow

I retried using the example loop structure from the recursion section of the dynamic macros documentation Using Dynamic Macros Features - Klipper Dynamic Macros

[gcode_macro COUNT]
gcode:
    {% set num = params.NUM|default(1)|int %}
    {% if num <= 10 %}
    QUERY_BUTTON BUTTON=zswitch
    G4 P2000
          {% if printer["gcode_button zswitch"].state == 'PRESSED' %}
        M118 PRE SSED !!
        {% else %}
        M118 NOT PRES SED !!
        {% endif %}
        COUNT NUM={num+1} # Count up 1
    {% else %}
       RESPOND MSG="Done Counting"
    {% endif %}

This however had the odd effect of only ever rehoming the printer and doing nothing more ?.

DynamicMacros wouldn’t home the printer unless the GCode in a macro says to do that. Maybe your zswitch button thinks its being pressed?

Oh my its gotten even weirder.

the example code itself without modification causes the printer to home
code from Example Macros - Klipper Dynamic Macros

Blockquote

[gcode_macro COUNT]
gcode:
    {% set num = params.NUM|default(1)|int %}
    {% if num <= 10 %}
        RESPOND MSG={num}
        COUNT NUM={num+1} # Count up 1
    {% else %}
        RESPOND MSG="Done Counting"
    {% endif %}

it seems the three whitespaces kills internal variables somehow
and the recursive loop breaks klipper somehow.

Sadly the trick to using buttons inside macros remains elusive.

it seems the three whitespaces kills internal variables somehow

This is a known issue and is solved by using the special update() function, described at the botton of Receiving Variable Updates - Klipper Dynamic Macros.

and the recursive loop breaks klipper somehow.

This is really strange. I’ve looked through the DynamicMacros code and all I can say is that DynamicMacros won’t home the printer unless there’s a G28 command in a macro it’s instructed to call.

SUCESS!!!

I discovered that the behavior of the macro would vary depending on where in the dynamic.cfg the macro was pasted.

It turns out I had another example macro with a g28 command in it.
this macro had a space before the “[” so it was " [gcode_macro DYNAMIC_MOVE]" insted of “[gcode_macro DYNAMIC_MOVE]”
This was causing some weird behavior

The following code correctly choses its conditional statement depending on the switch’s physical state

Blockquote
[gcode_macro SWITCH_TEST]
gcode:
{% set num = params.NUM|default(1)|int %}
{% if num <= 10 %}
QUERY_BUTTON BUTTON=zswitch
G4 P2000
{% if printer[“gcode_button zswitch”].state == ‘PRESSED’ %}
M118 PRE SSED !!
{% else %}
M118 NOT PRES SED !!
{% endif %}
SWITCH_TEST NUM={num+1} # Count up 1
{% else %}
RESPOND MSG=“Done Counting”
{% endif %}

Im still getting used to the whitespace syntax. and getting the formatting in a suitable state to run without errors.

Ill come back and update this post with a more polished working example for the benefit of future googlers.

Thankyou for your help kind sir !

1 Like

Blockquote

is not

Preformatted Text.

OK So i can sucessfully decend to the z limit switch and stop using the dynamic macro

Blockquote
[gcode_macro Z_DEC]
gcode:
G91
{% set num = params.NUM|default(1)|int %}
{% if num <= 100 %}
G4 P100
QUERY_BUTTON BUTTON=zswitch
{% if printer[“gcode_button zswitch”].state == ‘PRESSED’ %}
{% set num = 100 %}
{% else %}
G1 Z-0.05
#M118 {printer.toolhead.position.z}
Z_DEC NUM={num+1} # Count u
{% endif %}
{% else %}
RESPOND MSG=“Done Decrementing Z”
{% endif %}
G90

And that stops the Z axis at the correct location but im still having a heck of a time trying to get that Zposition back up to the macro that called it

Blockquote
[gcode_macro LOOP_TEST]
gcode:
{% for step in range(4) %}
Z_DEC
M118 {printer.toolhead.position.z}
G91
G1 Z+3.0
G90
G4 P3000
{% endfor %}

This loop functions but unsupprisingly reports back the z position at the start.
if i put three carriage returns in like this

Blockquote
[gcode_macro LOOP_TEST]
gcode:
{% for step in range(4) %}
Z_DEC

M118 {printer.toolhead.position.z}
G91
G1 Z+3.0
G90
G4 P3000
{% endfor %}

I get
Error loading template ‘LOOP_TEST’: jinja2.exceptions.TemplateSyntaxError: Unexpected end of template. Jinja was looking for the following tags: ‘endfor’ or ‘else’. The innermost block that needs to be closed is ‘for’.

it seams that any time i put the three (ive allso tried adding just two incase the existing newline counts) inside a macro that has any jinja expressions it throws that error

I tried using get_macro_variables() and SET_DYNAMIC_VARIABLE but they allways seem to return blank data as dose update()

PLEASE!

Use Preformatted Text for code snippets, not Blockquote:

grafik

what are you talking about ?

image

How did you manage to format that?

ive got no idea i just pushed the " button and pasted the code in… thats not the whole code snippit either theres suposed to be three caragige returns that form part of the code, honestly i have no idea what the deal is with jinja formatting.

You should have the marked icon somewhere when posting. This is essential as otherwise important formatting like indents etc get lost

this is what ive got

This is strange. Is it hidden behind the grafik?