Newer
Older
jeltz-klipper-config / config / macros.cfg
# gcode to run on printer start
[delayed_gcode STARTUP]
gcode:
    # grab saved variables
    {% set svv = printer.save_variables.variables %}
    {% set bed_leeway_temp = 10 %}
    {% set extruder_leeway_temp = 20 %}
    {% set hotend_filament = svv.hotend_filament %}
    
    # check if stored variables make sense, and set them to default values if not
    {% if not(svv.heater_mode == "auto" or svv.heater_mode == "manual" or svv.heater_mode == "slicer")%}
      { action_respond_info("setting heater_mode to AUTO, before: %s" % (svv.heater_mode)) }
      SAVE_VARIABLE VARIABLE=heater_mode VALUE='"auto"'

    {% endif %}
    
    # set temp variables - call variables macro
    VARIABLES

    # kickstart fan control macro
    UPDATE_DELAYED_GCODE ID=FAN_CONTROL_LOOP DURATION=2

    
    # check the current heater states and re enable heaters if able
    {% if svv.extruder_state == 'hot' %}
        {% if printer.extruder.temperature - extruder_leeway_temp <= svv.extruder_temperature %}
            { action_respond_info("re-enabling extruder after printer shutoff") }
        {% else %}
            { action_respond_info("extruder was enabled before last shutoff. State updated to cold.") }
            SAVE_VARIABLE VARIABLE=extruder_state VALUE='"cold"'
        {% endif %}
    {% endif %}
    
    {% if svv.bed_state == 'hot' %}
        {action_respond_info(printer.heater_bed.temperature|string)}
        {action_respond_info(bed_leeway_temp|string)}
        {action_respond_info(svv.bed_temperature|string)}

        {% if printer.heater_bed.temperature - bed_leeway_temp <= svv.bed_temperature %}
            { action_respond_info("re-enabling bed after printer shutoff") }
        {% else %}
            { action_respond_info("bed was enabled before last shutoff. State updated to cold.") }
            SAVE_VARIABLE VARIABLE=bed_state VALUE='"cold"'
        {% endif %}
    {% endif %}

    # check the filament load state:
    # exit-entry-bowden
    # 000  unloaded
    # 001  unloaded
    # 010  invalid
    # 011  unloaded
    # 100  runout
    # 101  invalid
    # 110  near_runout
    # 111  loaded

    # store button vals
    {% set exit_sense = (printer["gcode_button extruder_exit"].state == "PRESSED") %}
    {% set entry_sense = (printer["gcode_button extruder_entry"].state == "PRESSED") %}
    {% set bowden_sense = (printer["gcode_button bowden_sensor"].state == "PRESSED") %}

    # detect unloaded
    {% if not(entry_sense and exit_sense) or (not(entry_sense) and bowden_sense) %}
        {% if svv.filament_load_state != "unloaded" %}
            { action_respond_info("Current filament state does not match filament state on last boot. Was " ~ (svv.filament_load_state|string) ~ ", currently unloaded.") }
        {% endif %}
        SET_FILAMENT_LOAD_STATE STATE="unloaded"
        SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=0

    # loaded
    {% elif entry_sense and exit_sense and bowden_sense %}
        {% if svv.filament_load_state != "loaded" %}
            { action_respond_info("Current filament state does not match filament state on last boot. Was " ~ (svv.filament_load_state|string) ~ ", currently loaded. Double check filament path.") }
        {% endif %}
        # SAVE_VARIABLE VARIABLE=loaded_filament VALUE=none
        SET_FILAMENT_LOAD_STATE STATE="loaded"
        SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=1

    # runout
    {% elif entry_sense and not(exit_sense) and not(bowden_sense) %}
        { action_respond_info("Current filament state is runout. Unable to print.") }
        SET_FILAMENT_LOAD_STATE STATE="runout"
        SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=0

    # near_runout
    {% elif entry_sense and exit_sense and not(bowden_sense) %}
        { action_respond_info("Current filament state is runout. Unable to print.") }
        SET_FILAMENT_LOAD_STATE STATE="near_runout"
        SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=0

    {% endif %}

    # set the currently loaded filament
    SET_FILAMENT NAME={loaded_filament['name']}

initial_duration: 2

[gcode_macro TEST]
gcode:
  {% set svv = printer.save_variables.variables %}
  {break}
  {action_respond_info(svv.filaments|selectattr("name", "in", [svv.filament_hotend, 
  svv.filament_extruder])|map(attribute="extruder",default='None')|max|string)}

####### Calibration
[gcode_macro calibrate_full]
gcode:
  G28
  QUAD_GANTRY_LEVEL
  BED_MESH_CALIBRATE METHOD=rapid_scan
  G0 X239 Y210 F{700*60}
  SET_GCODE_VARIABLE MACRO=VARIABLES VARIABLE=calibrate VALUE='"full"'
  
[gcode_macro calibrate]
gcode:
  {% set calibrate = printer["gcode_macro VARIABLES"].calibrate %}
  
  {% if calibrate == "none" %}
    G28
    QUAD_GANTRY_LEVEL
    BED_MESH_CALIBRATE METHOD=rapid_scan
    
  {% elif calibrate == "home" %}
    QUAD_GANTRY_LEVEL
    BED_MESH_CALIBRATE METHOD=rapid_scan

  {% elif calibrate == "QGL" %}
    G0 X15 Y22 F{700*60}
    BED_MESH_CALIBRATE METHOD=rapid_scan
  {% endif %}
  
  G0 X239 Y210 F{700*60}
  SET_GCODE_VARIABLE MACRO=VARIABLES VARIABLE=calibrate VALUE='"full"'
  
[gcode_macro calibrate_override]
gcode:
  SET_GCODE_VARIABLE MACRO=VARIABLES VARIABLE=calibrate VALUE='"full"'

[gcode_macro calibrate_query]
gcode:
  {% set val = printer["gcode_macro VARIABLES"].calibrate %}
  { action_respond_info("a" + val|string) }

####### PRINT START AND STOP ETC
[gcode_macro START_PRINT]
description: Runs before the start of a print. Checks print readyness, corrects if nessesary, and primes the nozzle.
gcode:
  {% set svv = printer.save_variables.variables %}
  # first, check calibration
  CALIBRATE

  # enable the encoder filament sensor
  SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=1

  # check the state of the loaded filament
  {% if svv.filament_state in ["loaded", "primed"] and svv.filament_runout_state != "runout" %}
    # if in auto, only bother to set bed to loaded filament parameters. The others will be set when we purge/prime.
    {% if svv.heater_mode == "auto" %}
      #SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={svv.filaments|selectattr("name", "equalto", svv.filament_extruder)|map(attribute="bed",default='None')|first|string} MODE=auto; set extruder temp    
    # if in slicer or manual mode, quickly sanity check the set temperatures:
    {% else %}
      {% if printer['extruder'].target != 0 %}
        {action_raise_error("Extruder temperature is set to at or below zero")}
      {% endif %}
    {% endif %}
      
    {% if svv.filament_extruder == svv.filament_hotend %}
      PRIME_FILAMENT
    {% else %}
      PURGE_FILAMENT
    {% endif %}
    
  {% elif svv.filament_runout_state == "runout" %}
    {action_raise_error("Error, filament in runout state")}

  {% else %}
    {action_raise_error("Error, filament not loaded. Filament is %s" %(svv.filament_state))}
  {% endif %}

  # final enable of heaters and wait for temperature to be reached
  SET_HEATERS_TO_FILAMENT_AND_WAIT
  

[gcode_macro stop_print]
gcode:
    {% set z = params.Z|default(50)|int %}                                                   ; z hop amount

  SET_FILAMENT_SENSOR SENSOR=bowden_encoder_sensor ENABLE=0

  # reduce temperature of extruder by 10c to reduce oozing
  SET_HEATER_TEMPERATURE HEATER=extruder TARGET={printer['extruder'].target - 10} MODE=auto
  
  {% if (printer.gcode_move.position.z + z) < printer.toolhead.axis_maximum.z %}       ; check that zhop doesn't exceed z max
        G91                                                                              ; relative positioning
        G1 Z{z} F900                                                                     ; raise Z up by z hop amount
  {% else %}
        G0 Z{printer.toolhead.axis_maximum.z}
        { action_respond_info("Pause zhop exceeds maximum Z height.") }                 
  {% endif %}
  G90                                                                                  ; absolute positioning
  G1 Y{258} F6000   ; park toolhead


[gcode_macro PAUSE]
description: Pause the actual running print
rename_existing: PAUSE_MAINSAIL
gcode:
# Parameters
    {% set z = params.Z|default(10)|int %}                                                   ; z hop amount
    #{% set idle_timeout = client.idle_timeout|default({60*5}) %}
    {% set idle_timeout = 60*5 %}
    
    # if printer is not already paused...
    {% if printer['pause_resume'].is_paused|int == 0 %}
    # set variables for reference in resume macro
        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=posx VALUE={printer['gcode_move'].gcode_position.x}          
        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=posy VALUE={printer['gcode_move'].gcode_position.y}                              
        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=posz VALUE={printer['gcode_move'].gcode_position.z}                              

        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}    
        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=btemp VALUE={printer['heater_bed'].target}
        SAVE_GCODE_STATE NAME=PAUSE

        # set a new idle_timeout value
        SET_IDLE_TIMEOUT TIMEOUT={idle_timeout}
        
        # {client.user_pause_macro|default("")}

        # reduce temperature of extruder by 10c to reduce oozing
        SET_HEATER_TEMPERATURE HEATER=extruder TARGET={printer['extruder'].target - 10} MODE=auto
        
        {% if (printer.gcode_move.position.z + z) < printer.toolhead.axis_maximum.z %}       ; check that zhop doesn't exceed z max
            G91                                                                              ; relative positioning
            G1 Z{z} F900                                                                     ; raise Z up by z hop amount
        {% else %}
            G0 Z{printer.toolhead.axis_maximum.z}
            { action_respond_info("Pause zhop exceeds maximum Z height.") }                 
        {% endif %}
        G90                                                                                  ; absolute positioning
        G1 Y{258} F6000   ; park toolhead
        SAVE_GCODE_STATE NAME=PAUSEPARK                                                      ; save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)
    {% endif %}
  
[gcode_macro RESUME]
description: Resume the actual running print
rename_existing: RESUME_MAINSAIL
variable_posx: 0
variable_posy: 0
variable_posz: 0
variable_zhop: 0
variable_etemp: 0
variable_btemp: 0
gcode:
    # Parameters
    {% set e = params.E|default(2.5)|int %}                                          ; hotend prime amount (in mm)
    {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
    {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
    {% set sp_move = client.speed_move|default(velocity) %}
    {% set runout_resume = True if client.runout_sensor|default("") == ""     # no runout
                      else True if not printer[client.runout_sensor].enabled  # sensor is disabled
                      else printer[client.runout_sensor].filament_detected %} # sensor status
    {% set can_extrude = True if printer.toolhead.extruder == ''           # no extruder defined in config
                    else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder
    {% set do_resume = False %}
    {% set prompt_txt = [] %}

    # if printer is paused...
    {% if printer['pause_resume'].is_paused|int == 1 %}
        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}  ; set timeout back to configured value

        RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=200                     ; go back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)

        # reset temperatures
        {% if etemp > 0 %}
          SET_HEATER_TEMPERATURE HEATER=extruder TARGET={etemp} MODE=auto
        {% endif %}
        {% if btemp > 0 %}
          SET_HEATER_TEMPERATURE_AND_WAIT HEATER=heater_bed TARGET={btemp} MODE=auto
        {% endif %}
        {% if etemp > 0 %}
            SET_HEATER_TEMPERATURE_AND_WAIT HEATER=extruder TARGET={etemp} MODE=auto  ; Wait for hotend temp
        {% endif %}
        
        G91                                                                          ; relative positioning
        M83                                                                          ; relative extruder positioning
        {% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}
            G1 Z{zhop * -1} E{e} F900                                                ; prime nozzle by E, lower Z back down
        {% else %}
            G1 Z{zhop * -1} F900                                                     ; lower Z back down without priming (just in case we are testing the macro with cold hotend)
        {% endif %}
        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=60                          ; restore position
    {% endif %}

[gcode_macro CANCEL_PRINT]
rename_existing: CANCEL_PRINT_MAINSAIL
gcode:
    {% set z = params.Z|default(10)|int %}                                                   ; z hop amount

    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout} ; set timeout back to configured value
    CLEAR_PAUSE
    PRINT_END
    
    # reduce temperature of extruder by 10c to reduce oozing
    SET_HEATER_TEMPERATURE HEATER=extruder TARGET={printer['extruder'].target - 10} MODE=auto
    
    {% if (printer.gcode_move.position.z + z) < printer.toolhead.axis_maximum.z %}       ; check that zhop doesn't exceed z max
        G91                                                                              ; relative positioning
        G1 Z{z} F900                                                                     ; raise Z up by z hop amount
    {% else %}
        G0 Z{printer.toolhead.axis_maximum.z}
        { action_respond_info("Pause zhop exceeds maximum Z height.") }                 
    {% endif %}
    
    G90                                                                                  ; absolute positioning
    G1 Y{258} F6000   ; park toolhead
    # clear pause_next_layer and pause_at_layer as preparation for next print
    SET_PAUSE_NEXT_LAYER ENABLE=0
    SET_PAUSE_AT_LAYER ENABLE=0 LAYER=0

###### HEATER AUTO HANDLING
[gcode_macro SET_HEATERS_TO_FILAMENT_AND_WAIT]
gcode:
  SET_HEATER_TEMPERATURE HEATER=extruder TARGET={svv.filaments|selectattr("name", "equalto", svv.filament_hotend)|map(attribute="extruder",default='None')|first|string} MODE=auto
  SET_HEATER_TEMPERATURE_AND_WAIT HEATER=heater_bed TARGET={svv.filaments|selectattr("name", "equalto", svv.filament_hotend)|map(attribute="bed",default='None')|first|string} MODE=auto
  SET_HEATER_TEMPERATURE_AND_WAIT HEATER=extruder TARGET={svv.filaments|selectattr("name", "equalto", svv.filament_hotend)|map(attribute="extruder",default='None')|first|string} MODE=auto


## MISC MACROS

[gcode_macro DUMP_VARIABLES]
gcode:
    {% set filter_name = params.NAME|default('')|string|lower %}
    {% set filter_value = params.VALUE|default('')|string|lower %}
    {% set show_cfg = params.SHOW_CFG|default(0)|int %}
    
    {% set out = [] %}

    {% for key1 in printer %}
        {% for key2 in printer[key1] %}
            {% if (show_cfg or not (key1|lower == 'configfile' and key2|lower in ['config', 'settings'])) and (filter_name in key1|lower or filter_name in key2|lower) and filter_value in printer[key1][key2]|string|lower %}
                {% set dummy = out.append("printer['%s'].%s = %s" % (key1, key2, printer[key1][key2])) %}
            {% endif %}
        {% else %}
            {% if filter_name in key1|lower and filter_value in printer[key1]|string|lower %}
                {% set dummy = out.append("printer['%s'] = %s" % (key1, printer[key1])) %}
            {% endif %}
        {% endfor %}
    {% endfor %}
    
    {action_respond_info(out|join("\n"))}

[gcode_macro TEST_SPEED]
# Home, get position, throw around toolhead, home again.
# If MCU stepper positions (first line in GET_POSITION) are greater than a full step different (your number of microsteps), then skipping occured.
# We only measure to a full step to accomodate for endstop variance.
# Example: TEST_SPEED SPEED=300 ACCEL=5000 ITERATIONS=10

description: Test for max speed and acceleration parameters for the printer. Procedure: Home -> ReadPositionFromMCU -> MovesToolhead@Vel&Accel -> Home -> ReadPositionfromMCU

gcode:
    # Speed
    {% set speed  = params.SPEED|default(printer.configfile.settings.printer.max_velocity)|int %}
    # Iterations
    {% set iterations = params.ITERATIONS|default(5)|int %}
    # Acceleration
    {% set accel  = params.ACCEL|default(printer.configfile.settings.printer.max_accel)|int %}
    # Minimum Cruise Ratio
    {% set min_cruise_ratio = params.MIN_CRUISE_RATIO|default(0.5)|float %}
    # Bounding inset for large pattern (helps prevent slamming the toolhead into the sides after small skips, and helps to account for machines with imperfectly set dimensions)
    {% set bound = params.BOUND|default(20)|int %}
    # Size for small pattern box
    {% set smallpatternsize = SMALLPATTERNSIZE|default(20)|int %}
    
    # Large pattern
        # Max positions, inset by BOUND
        {% set x_min = printer.toolhead.axis_minimum.x %}
        {% if x_min < 0 %}
            {% set x_min = 0 %}
        {% endif %}
    
        {% set y_min = printer.toolhead.axis_minimum.y %}
        {% if y_min < 0 %}
            {% set y_min = 0 %}
        {% endif %}
    
        {% set x_min = x_min + bound %}
        {% set x_max = printer.toolhead.axis_maximum.x - bound %}
        {% set y_min = y_min + bound %}
        {% set y_max = printer.toolhead.axis_maximum.y - bound %}
    
    # Small pattern at center
        # Find X/Y center point
        {% set x_center = (printer.toolhead.axis_minimum.x|float + printer.toolhead.axis_maximum.x|float ) / 2 %}
        {% set y_center = (printer.toolhead.axis_minimum.y|float + printer.toolhead.axis_maximum.y|float ) / 2 %}
        
        # Set small pattern box around center point
        {% set x_center_min = x_center - (smallpatternsize/2) %}
        {% set x_center_max = x_center + (smallpatternsize/2) %}
        {% set y_center_min = y_center - (smallpatternsize/2) %}
        {% set y_center_max = y_center + (smallpatternsize/2) %}

    # Save current gcode state (absolute/relative, etc)
    SAVE_GCODE_STATE NAME=TEST_SPEED
    
    # Output parameters to g-code terminal
    { action_respond_info("TEST_SPEED: starting %d iterations at speed %d, accel %d" % (iterations, speed, accel)) }
    
    # Home and get position for comparison later:
        M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
        # QGL if not already QGLd (only if QGL section exists in config)
        {% if printer.configfile.settings.quad_gantry_level %}
            {% if printer.quad_gantry_level.applied == False %}
                G28
                QUAD_GANTRY_LEVEL
                G28 Z
            {% endif %}
        {% endif %} 
        # Move 50mm away from max position and home again (to help with hall effect endstop accuracy - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/24)
        G90
        G1 X{printer.toolhead.axis_maximum.x-50} Y{printer.toolhead.axis_maximum.y-50} F{100*60}
        M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
        G28 X Y
        G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{100*60}
        G4 P1000 
        GET_POSITION

    # Go to starting position
    G0 X{x_min} Y{y_min} Z{bound + 10} F{speed*60}

    # Set new limits
    {% if printer.configfile.settings.printer.minimum_cruise_ratio is defined %}
        SET_VELOCITY_LIMIT VELOCITY={speed} ACCEL={accel} MINIMUM_CRUISE_RATIO={min_cruise_ratio}
    {% else %}
        SET_VELOCITY_LIMIT VELOCITY={speed} ACCEL={accel} ACCEL_TO_DECEL={accel / 2}
    {% endif %}

    {% for i in range(iterations) %}
        # Large pattern diagonals
        G0 X{x_min} Y{y_min} F{speed*60}
        G0 X{x_max} Y{y_max} F{speed*60}
        G0 X{x_min} Y{y_min} F{speed*60}
        G0 X{x_max} Y{y_min} F{speed*60}
        G0 X{x_min} Y{y_max} F{speed*60}
        G0 X{x_max} Y{y_min} F{speed*60}
        
        # Large pattern box
        G0 X{x_min} Y{y_min} F{speed*60}
        G0 X{x_min} Y{y_max} F{speed*60}
        G0 X{x_max} Y{y_max} F{speed*60}
        G0 X{x_max} Y{y_min} F{speed*60}
    
        # Small pattern diagonals
        G0 X{x_center_min} Y{y_center_min} F{speed*60}
        G0 X{x_center_max} Y{y_center_max} F{speed*60}
        G0 X{x_center_min} Y{y_center_min} F{speed*60}
        G0 X{x_center_max} Y{y_center_min} F{speed*60}
        G0 X{x_center_min} Y{y_center_max} F{speed*60}
        G0 X{x_center_max} Y{y_center_min} F{speed*60}
        
        # Small pattern box
        G0 X{x_center_min} Y{y_center_min} F{speed*60}
        G0 X{x_center_min} Y{y_center_max} F{speed*60}
        G0 X{x_center_max} Y{y_center_max} F{speed*60}
        G0 X{x_center_max} Y{y_center_min} F{speed*60}
    {% endfor %}

    # Restore max speed/accel/accel_to_decel to their configured values
    {% if printer.configfile.settings.printer.minimum_cruise_ratio is defined %}
        SET_VELOCITY_LIMIT VELOCITY={printer.configfile.settings.printer.max_velocity} ACCEL={printer.configfile.settings.printer.max_accel} MINIMUM_CRUISE_RATIO={printer.configfile.settings.printer.minimum_cruise_ratio} 
    {% else %}
        SET_VELOCITY_LIMIT VELOCITY={printer.configfile.settings.printer.max_velocity} ACCEL={printer.configfile.settings.printer.max_accel} ACCEL_TO_DECEL={printer.configfile.settings.printer.max_accel_to_decel}
    {% endif %}

    # Re-home and get position again for comparison:
        M400 # Finish moves - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/66
        # G28 # This is a full G28 to fix an issue with CoreXZ - https://github.com/AndrewEllis93/Print-Tuning-Guide/issues/12
        # Go to XY home positions (in case your homing override leaves it elsewhere)
        G90motors
        G0 X{printer.toolhead.axis_maximum.x-1} Y{printer.toolhead.axis_maximum.y-1} F{100*60}
        G4 P1000 
        GET_POSITION

    # Restore previous gcode state (absolute/relative, etc)
    RESTORE_GCODE_STATE NAME=TEST_SPEED