Custom Macro Throwing an error

Basic Information:

Printer Model: RatRig V-Core 3.1
MCU / Printerboard: Raspberry Pi 4/Octopus v1.1 (F446)
klippy.log:
klippy.zip (2.1 MB)

Describe your issue:

Let me preface by saying I don’t know a lot about coding in Python (or whatever language Klipper macros are written in) and have basically learned what I know based on the existing macros in the config file. Using this knowledge, I am trying to create a custom macro for bed mesh calibration that uses the Marlin and RRF G29 command with a few parameters. The problem is that I get an error message when trying to parse the second parameter of the command and I need assistance. I’ve tried passing the parameter with “=”, double quotes, and single quotes, but none of them seem to work. The latest revision of the macro definition is listed below, so any help will be greatly appreciated:

[gcode_macro G29]
variable_mesh_state: -10
variable_mesh_profile: "none"

# Command formats:
# G29: Calibrates bed mesh and saves it under profile name ratos
# G29 S-1: Clears bed mesh
# G29 S0: Same as G29
# G29 S1 P'Profile Name': Calibrates bed mesh and saves it under chosen profile name
# G29 S2 P'Profile Name': Loads Bed mesh profile
# G29 S3 P'Profile Name': Removes specified bed mesh profile

gcode:

  {% set x_homed = 'x' in printer.toolhead.homed_axes %}
  {% set y_homed = 'y' in printer.toolhead.homed_axes %}
  {% set z_homed = 'z' in printer.toolhead.homed_axes %}

  {% if params.S is defined %}
      {% set mesh_state = params.S|default(-10)|float %}
  {% endif %}

  {% if params.P is defined %}
      {% set mesh_profile = params.P|default('none')|replace("'", "") %}
      {% set decoded_msg = "Mesh Profile Name: " ~ mesh_profile %}
      RESPOND MSG={decoded_msg}
  {% endif %}

  {% if mesh_state == 3 %}
      {% if mesh_profile != 'none' %}
          RESPOND MSG={mesh_profile}
          BED_MESH_PROFILE REMOVE={mesh_profile}
      {% else %}
          RESPOND MSG="Missing parameter for mesh profile name!"
      {% endif %}
  {% else %}      
      {% if x_homed == False or y_homed == False or z_homed == False %}
          RESPOND MSG="Axes not homed! Home axes to perform bed mesh operations."
      {% else %}
          {% if printer["gcode_macro RatOS"].tilt_adjust_status == False %}
              RESPOND MSG="Bed tilt not adjusted! Adjust bed tilt prior to bed mesh operations."
          {% else %}
              {% if mesh_state == -10 or mesh_state == 0 %}
                  BED_MESH_CALIBRATE PROFILE=ratos
              {% else %}
                  {% if mesh_state == -1 %}
                      BED_MESH_CLEAR
                  {% elif mesh_state == 1 %}
                      {% if mesh_profile != 'none' %}
                          BED_MESH_CALIBRATE PROFILE={mesh_profile}
                      {% else %}
                          RESPOND MSG="Missing parameter for mesh profile name!"
                      {% endif %}
                  {% elif mesh_state == 2 %}
                      {% if mesh_profile != 'none' %}
                          BED_MESH_PROFILE LOAD={mesh_profile}
                      {% else %}
                          RESPOND MSG="Missing parameter for mesh profile name!"
                      {% endif %}
                  {% endif %}
              {% endif %}
          {% endif %}
        {% endif %}
    {% endif %}

Edit - Formatted Post to improve readability

Please use the Preformatted Text tag for such code snippets.
image

This makes your posts better readable.

If you use nested if-clauses did you indent the inner blocks? Might get lost due to just posting the code here without the proper tags.

I’m not such a programmer either but I think None is sometimes a bit special to use.
Maybe somebody can add some helpful tips here.

1 Like

Thank you, @LifeOfBrian . I’ve formatted the text to reflect the indentations.

It’s not clear how you’re trying to call this macro. The comments at the beginning of the macro about command formats aren’t correct as macro parameters aren’t passed like S1, it would have to be S=1.

I was able to work around the error by renaming the macro to CALIBRATE_MESH instead of G29 and using full names for the parameter variables (STATE and NAME) instead of single letters like S and P. For some reason, using single letter parameters only captures a single character when that parameter is provided (so if I provide parameter P as P’Hot’, it only captures the first single quote as the parameter value. When I try P=Hot, it captures the = as the value). Also, using G29 as the macro name does not seem to work no matter what the parameter variables are called, even though Klipper natively does not have G29 implemented.

My new macro now also includes adaptive mesh leveling, so this one macro handles all the bed mesh leveling requirements when I call it in my rather complex START_PRINT and END_PRINT macros, based on how I slice my print.

The new macro is listed below:

[gcode_macro CALIBRATE_MESH]
description: Macro for multiple bed mesh operations grouped under a single command
variable_mesh_state: -10
variable_mesh_profile: "default"
variable_x0: -1.0
variable_y0: -1.0
variable_x1: -1.0
variable_y1: -1.0

# Command formats:
# CALIBRATE_MESH: Calibrates bed mesh and saves it under profile name default
# CALIBRATE_MESH STATE=-1: Clears bed mesh
# CALIBRATE_MESH STATE=0: Same as CALIBRATE_MESH
# CALIBRATE_MESH STATE=1 NAME=Profile Name: Calibrates bed mesh and saves it under chosen profile name
# CALIBRATE_MESH STATE=2 NAME=Profile Name: Loads Bed mesh profile
# CALIBRATE_MESH STATE=3 NAME=Profile Name: Removes specified bed mesh profile
# CALIBRATE_MESH STATE=4 NAME=Profile Name X0=x0 X1=x1 Y0=y0 Y1=y1: Performs adaptive bed mesh calibration and saves it under chosen profile name (default if no name provided)

gcode:

  {% set x_homed = 'x' in printer.toolhead.homed_axes %}
  {% set y_homed = 'y' in printer.toolhead.homed_axes %}
  {% set z_homed = 'z' in printer.toolhead.homed_axes %}

  {% set mesh_state = params.STATE|default(-10)|int %}
  
  {% set x0 = params.X0|default(-1)|float %}
  {% set y0 = params.Y0|default(-1)|float %}
  {% set x1 = params.X1|default(-1)|float %}
  {% set y1 = params.Y1|default(-1)|float %}

  {% if params.NAME %}
      {% set mesh_profile = params.NAME|string %}
      {% if mesh_state == -10 or mesh_state == 0 %}
          RESPOND MSG="Command State: {mesh_state} - Full Mesh Calibrate to Profile: default"
      {% elif mesh_state == 1 %}
          RESPOND MSG="Command State: {mesh_state} - Full Mesh Calibrate to Profile: {mesh_profile}"
      {% elif mesh_state == 2 %}
          RESPOND MSG="Command State: {mesh_state} - Load Calibration Profile: {mesh_profile}"
      {% elif mesh_state == 3 %}
          RESPOND MSG="Command State: {mesh_state} - Remove Calibration Profile: {mesh_profile}"
      {% elif mesh_state == 4 %}
          {% if not (x0 == -1.0 and y0 == -1.0 and x1 == -1.0 and y1 == -1.0) %}
              RESPOND MSG="Command State: {mesh_state} - Calibrate Adaptive Mesh between coordinates ({x0}, {y0}) and ({x1}, {y1}). Profile Name: {mesh_profile}"
          {% else %}
              {% set mesh_state = 1 %}
              RESPOND MSG="No coordinates provided for adaptive meshing. Reverting to Full mesh calibration. Command State: {mesh_state} - Full Mesh Calibrate to Profile: {mesh_profile}"
          {% endif %}
      {% endif %}
  {% else %}
      {% if mesh_state == 1 or mesh_state == 2 or mesh_state ==3 %}
          {% set mesh_profile = 'none' %}
          { action_raise_error("CALIBRATE_MESH Command State {} requires a profile name".format(mesh_state)) }
      {% elif mesh_state == 4 %}
          {% set mesh_profile = 'default' %}
          {% if not (x0 == -1.0 and y0 == -1.0 and x1 == -1.0 and y1 == -1.0) %}
              RESPOND MSG="Command State: {mesh_state} - Calibrate Adaptive Mesh between coordinates ({x0}, {y0}) and ({x1}, {y1}). Profile Name: {mesh_profile}"
          {% else %}
              {% set mesh_state = 0 %}
              RESPOND MSG="No coordinates provided for adaptive meshing. Reverting to Default Full mesh calibration. Command State: {mesh_state} - Full Mesh Calibrate to Profile: {mesh_profile}"
          {% endif %}
      {% endif %}
  {% endif %}

  {% if mesh_state == 3 %}
      {% if mesh_profile != 'none' %}
          BED_MESH_PROFILE REMOVE={mesh_profile}
      {% else %}
          RESPOND MSG="Missing mesh profile name!"
      {% endif %}
  {% else %}      
      {% if x_homed == False or y_homed == False or z_homed == False %}
          RESPOND MSG="Axes not homed! Home axes to perform bed mesh operations."
      {% else %}
          {% if printer.z_tilt.applied == False %}
              RESPOND MSG="Bed tilt not adjusted! Adjust bed tilt prior to bed mesh operations."
          {% else %}
              {% if mesh_state == -10 or mesh_state == 0 %}
                  BED_MESH_CALIBRATE PROFILE=default
              {% else %}
                  {% if mesh_state == -1 %}
                      BED_MESH_CLEAR
                  {% elif mesh_state == 1 %}
                      {% if mesh_profile != 'none' %}
                          BED_MESH_CALIBRATE PROFILE={mesh_profile}
                      {% else %}
                          RESPOND MSG="Missing mesh profile name!"
                      {% endif %}
                  {% elif mesh_state == 2 %}
                      {% if mesh_profile != 'none' %}
                          BED_MESH_PROFILE LOAD={mesh_profile}
                      {% else %}
                          RESPOND MSG="Missing mesh profile name!"
                      {% endif %}
                  {% elif mesh_state == 4 %}
                      {% if mesh_profile != 'none' %}
                          CALIBRATE_ADAPTIVE_MESH PROFILE={mesh_profile} X0={x0} Y0={y0} X1={x1} Y1={y1}
                      {% else %}
                          RESPOND MSG="Missing mesh profile name!"
                      {% endif %}
                  {% endif %}
              {% endif %}
          {% endif %}
        {% endif %}
    {% endif %}

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