New MPCNC build: Primo + Manta MP8 + Klipper in BC, Canada

Here’s the latest version of the mainsail config I have for klipper which allow me to use Pause and Resume.
NOTE: This should be used with caution, it is not complete AND not yet been tested on a CNC with an actual spindle connected
I haven’t yet worked out how to persist the speed the spindle was running at before pausing, so it’s hardcoded to resume at 5000.
I didn’t get much time to work on it yesterday and won’t tomorrow so wanted to share where I’m at.

This is my current complete mainsail.cfg

## Mainsail klipper macro definitions
##
## Copyright (C) 2022 Alex Zellner <alexander.zellner@googlemail.com>
##
## This file may be distributed under the terms of the GNU GPLv3 license

## Version 2.0

## add [include mainsail.cfg] to your printer.cfg

## Customization:
## copy the following macro to your printer.cfg (outside of mainsail.cfg)

#[gcode_macro _CLIENT_VARIABLE]
#variable_use_custom_pos  : True ; use custom park coordinates for x,y [True/False] 
#variable_custom_park_x   : 100.0   ; custom x position; value must be within your defined min and max of X
#variable_custom_park_y   : 100.0   ; custom y position; value must be within your defined min and max of Y
#variable_custom_park_dz  : 2.0   ; custom dz value; the value in mm to lift the nozzle when move to park position 
#variable_speed_hop       : 200.0  ; z move speed in mm/s
#variable_speed_move      : 200.0 ; move speed in mm/s
#variable_park_at_cancel  : False ; allow to move the toolhead to park while execute CANCEL_PRINT [True,False]
#gcode:

## After you uncomment it add your custom values

## You now can use your PAUSE macro direct in your M600 here a short example:

#[gcode_macro M600]
#description: Tool change
#gcode: PAUSE X=10 Y=10 Z_MIN=50

## That will park your head front left with a minimum hight of 50mm above the bed. If your head
## is already above 50mm it will use only the z_hop specified with dz.

[virtual_sdcard]
path: ~/printer_data/gcodes
on_error_gcode: CANCEL_PRINT

[pause_resume]

[display_status]

[gcode_macro CANCEL_PRINT]
description: Cancel the actual running print
rename_existing: CANCEL_PRINT_BASE
gcode:
  ##### get user parameters or use default #####
  {% set allow_park = False if printer['gcode_macro _CLIENT_VARIABLE'] is not defined
                 else False if printer['gcode_macro _CLIENT_VARIABLE'].park_at_cancel is not defined
                 else True  if printer['gcode_macro _CLIENT_VARIABLE'].park_at_cancel|lower == 'true' 
                 else False %}
  ##### end of definitions #####
  {% if not printer.pause_resume.is_paused and allow_park %} _TOOLHEAD_PARK_PAUSE_CANCEL {% endif %}

  CANCEL_PRINT_BASE

[gcode_macro PAUSE]

variable_restore: {'pos': {'x': 0, 'y':0, 'z':0}}
description: Pause the actual running print
rename_existing: PAUSE_BASE
gcode:
  PAUSE_BASE
  {% set restore = {'pos': 
    {'x': printer.gcode_move.gcode_position.x, 'y': printer.gcode_move.gcode_position.y, 'z': printer.gcode_move.gcode_position.z },
    'rpm': 5000} %}
  SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=restore VALUE="{restore}"
  M117 Paused at X{restore.pos.x|int} Y{restore.pos.y|int} Z{restore.pos.z} spinning at {restore.rpm}rpm
  _TOOLHEAD_PARK_PAUSE_CANCEL {rawparams}

[gcode_macro RESUME]
description: Resume the actual running print
rename_existing: RESUME_BASE
gcode:
  ##### get user parameters or use default #####
  {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %}
  {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %}
  {% set paused_at = printer['gcode_macro PAUSE'] %}
  {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
  {% set sp_move      = velocity * 60 if not macro_found else client.speed_move|default(velocity) * 60 %}
  {% set sp_hop       = 900  if not macro_found else client.speed_hop|default(15) * 60 %}

  ##### define resume position
  {% set x_resume = printer['gcode_macro PAUSE'].restore.pos.x %}
  {% set y_resume = printer['gcode_macro PAUSE'].restore.pos.y %}
  {% set z_resume = printer['gcode_macro PAUSE'].restore.pos.z %}
  {% set rpm_resume = printer['gcode_macro PAUSE'].restore.rpm %}

  ##### end of definitions #####


 #### move back to the saved position before resuming
   M117 Resume to X{x_resume|int} Y{y_resume|int} then Z{z_resume} spinning as {rpm_resume}rpm
   G90
   #### restarting spindle, need to 
   M3 S{rpm_resume}
   G1 X{x_resume} Y{y_resume} F{sp_move}
   G1 Z{z_resume} F{sp_hop}
  RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)}  

[gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL]
description: Helper: park toolhead used in PAUSE and CANCEL_PRINT
gcode:
  ##### get user parameters or use default #####
  {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %}
  {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %}
  {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
  {% set use_custom     = False if not macro_found
                     else False if client.use_custom_pos is not defined
                     else True  if client.use_custom_pos|lower == 'true' 
                     else False %}
  {% set custom_park_x  = 0.0 if not macro_found else client.custom_park_x|default(0.0) %}
  {% set custom_park_y  = 0.0 if not macro_found else client.custom_park_y|default(0.0) %}
  {% set park_dz        = 2.0 if not macro_found else client.custom_park_dz|default(2.0)|abs %}

  {% set sp_hop       = 900  if not macro_found else client.speed_hop|default(15) * 60 %}
  {% set sp_move      = velocity * 60 if not macro_found else client.speed_move|default(velocity) * 60 %}
  ##### get config and toolhead values #####
  {% set act = printer.toolhead.position %}
  {% set max = printer.toolhead.axis_maximum %}
  {% set cone = printer.toolhead.cone_start_z|default(max.z) %} ; hight as long the toolhead can reach max and min of an delta
  {% set round_bed = True if printer.configfile.settings.printer.kinematics is in ['delta','polar','rotary_delta','winch'] 
                else False %}
  ##### define park position #####
  {% set z_min = params.Z_MIN|default(0)|float %}
  {% set z_park = [[(act.z + park_dz), z_min]|max, max.z]|min %}
  {% set x_park = params.X       if params.X is defined
             else custom_park_x  if use_custom
             else 0.0            if round_bed 
             else (max.x - 5.0) %}
  {% set y_park = params.Y       if params.Y is defined
             else custom_park_y  if use_custom
             else (max.y - 5.0)  if round_bed and z_park < cone
             else 0.0            if round_bed
             else (max.y - 5.0) %}

  {% if "xyz" in printer.toolhead.homed_axes %}
    G90
    G1 Z{z_park} F{sp_hop}
    #### stopping spindle
    M5
    G1 X{x_park} Y{y_park} F{sp_move}
    {% if not printer.gcode_move.absolute_coordinates %} G91 {% endif %}
  {% else %}
    {action_respond_info("Printer not homed")}
  {% endif %}

I currently have these variables include via my printer.cfg;

## Customization:
## copy the following macro to your printer.cfg (outside of mainsail.cfg)

[gcode_macro _CLIENT_VARIABLE]
variable_use_custom_pos  : True ; use custom park coordinates for x,y [True/False] 
variable_custom_park_x   : 100.0   ; custom x position; value must be within your defined min and max of X
variable_custom_park_y   : 100.0   ; custom y position; value must be within your defined min and max of Y
variable_custom_park_dz  : 40.0   ; custom dz value; the value in mm to lift the nozzle when move to park position 
variable_speed_hop       : 5.0  ; z move speed in mm/s
variable_speed_move      : 80.0 ; move speed in mm/s
#variable_park_at_cancel  : False ; allow to move the toolhead to park while execute CANCEL_PRINT [True,False]
gcode:

I’ll be focusing on the drag chains and other modifications next, and still some time away from being ready for cutting. i.e. I need to build a table, speed control for the Makita etc.

1 Like