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

Physical build complete, glides like it’s on rails!
No play, and think I have the tension of the bearings pretty good.

Now for the klipper config…

8 Likes

That looks good!

3 Likes

Making progress!
I have unmodified Klipper running gcode generated by Fusion 360 and post processed by flyfisher, with a small amount of removing gcode that doesn’t yet work.
I’ve made short attempts to leverage klippy-cnc, but not yet worked out how to deal with the errors I get about not setting G28.1. Will walk through the macros to try and understand what it’s doing and how to use them. For now I’m getting use to the CAM process using Fusion, for instance how to set the origin to the bottom left of the model rather than in the center so you don’t get gcode three quarters full of negative numbers.

While I’m obviously not up and running yet, here’s the Klipper config I used to set up the steppers on my Big Tree Tech Manta 8 board. These settings are right for my wiring layout, so use at your own risk if you plan to blind copy them into a setup of your own.

I suspect the journey so far has been the easy leg of the journey, turning this into a simple workflow like I currently have with my 3D printers will be the challenge. I don’t plan to get “dirty” until I have this working the way I want.

[endstop_phase]

# Motor 1
[stepper_x]
step_pin: PE2
dir_pin: !PB4
enable_pin: !PC11
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PF3
position_endstop: 0
position_max: 620
homing_speed: 40
homing_positive_dir: false

# Motor 2
[stepper_x1]
step_pin: PF12
dir_pin: PF11
enable_pin: !PB3
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PF4

# Motor 4
[stepper_y]
step_pin: PD3
dir_pin: PD2
enable_pin: !PD5
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PC0
position_endstop: 0
position_max: 345
homing_speed: 40
homing_positive_dir: false

# Motor 5
[stepper_y1]
step_pin: PC9
dir_pin: !PC8
enable_pin: !PD1
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PC1

# Motor 6
[stepper_z]
step_pin: PA10
dir_pin: PD15
enable_pin: !PA15
microsteps: 16
rotation_distance: 8
endstop_pin: ^!PC2
position_endstop: 1.40
position_max: 90 # 90 when legs are in first wooden board
position_min: -5.0
homing_speed: 3
second_homing_speed: 3
homing_retract_dist: 3


########################################
# TMC2209 configuration
########################################

[tmc2209 stepper_x]
uart_pin: PC10
run_current: 0.800
stealthchop_threshold: 999999

[tmc2209 stepper_x1]
uart_pin: PF13
run_current: 0.800
stealthchop_threshold: 999999

[tmc2209 stepper_y]
uart_pin: PD4
run_current: 0.800
stealthchop_threshold: 999999

[tmc2209 stepper_y1]
uart_pin: PD0
run_current: 0.800
stealthchop_threshold: 999999

[tmc2209 stepper_z]
uart_pin: PF8
run_current: 0.650
stealthchop_threshold: 999999
6 Likes

Looks really good. That silver filament is sweet looking! Keep us posted on your motor currents. I found at 0.5 my z was skipping even with a pen. Seems ok at 0.75 for now.

2 Likes

Thanks, I really like how the silver has turned out, I wanted the only contrasting colour to be the teal of the Makita router.

I haven’t done any kind of tuning yet and haven’t noticed any skipping on the test draws so far. Motors are warm after a minute of movement, but not hot.
I played around with the velocity, and while obviously not practical I had it upto 12500 before I heard any unpleasant sounds, currently have any pen activity at 2000 and expect to be cutting even slower.

The workflow I’m currently going with is

  1. Create a 3D model in Fusion 360
  2. Switch from “Design” to “Manufacture”
  3. Choosing the Trace option from 2D milling
  4. Select the simple “pen” tool I created already (it’s just a ball end mill)
  5. Choose the curves I want to follow and “OK”
  6. Double click on Setup in the browser side menu
  7. Choose Stock Box Point as the origin and click on the bottom left corner of the model and “OK”.
  8. Then select Post Process from the the Actions menu
  9. With MPCNC selected (I previously installed flyfisher604), I enable G92 and turn off probe on start and “Post”.
  10. I edit the gcode, removing M84 and upload through Mainsail.
  11. Use the Mainsail interface to home X,Y & Z (using the V1 Eng metal touch plate for Z)
  12. Again with Mainsail controls, I position the pen to the bottom left corner of the paper.
  13. Then print the file, since it performs a G92, it sets the corner of the paper to 0,0,0.

I’ve listed the above for others to comment on a better process, as I’m new to CNC’ing I’ve got plenty to learn but this is working for me at the moment. I walked some of the macros from klippy-cnc, and couldn’t wrap my head around how to make it work without modifying to take advantage of the endstops, so I removed references to it for now and may revisit once I have a better understanding of how to CNC.

In addition I commented out 2 sections in mainsail.cfg which reference an extruder, this now allows me to pause, resume and stop without errors. This parks the head by raising then moving to the rear corner, however when resuming it starts to return to Z at the same time a X & Y which will be a problem when I start cutting so I’ll have to make further modifications.

Next steps will be to install the stepper fans (again, possible overkill), then a drag chain solution.

1 Like

This is where i got stuck with Klipper. Your workflow seems good. Since I went back to Marlin, I have a good workflow that works for me now. I’m still willing to switchback :grin:

1 Like

Looks great!

1 Like

I didn’t spot an immediate fix for this, but feel it shouldn’t be too difficult, expecting it to be another modification to mainsail.cfg… but will see.

Agreed, If I knew anything about programming I would help but yes looks like you somehow just need to have the resume go to X and Y and then Z. Shouldn’t be that difficult but way over my head! I’ll ask in the voron nad mainsail discord. Some sharp folks there.

So I looked at it a bit and definitly not just something in moonraker config straight away. Someone pointed me to this which shows more the details of the resume. I think the trick will be figuring out how to parse absolute coordinates into X,Y,Z into seperate references rather than just all three called but you’ve pretty much hit my coding knowledge limit :slight_smile: Here is something just to get you thinking it at least shows how restore works in klipper. moonraker-timelapse/timelapse.cfg at main · mainsail-crew/moonraker-timelapse · GitHub

1 Like

Thanks for the link, that makes sense and should be able to work with that when I put time into reading the code later in the week.

I have the stepper fans wired up so next I’m looking at cable chain solutions. I’ve had a look at what others have done, but want to keep all the drag chains clear of the workspace. So I’m thinking of using the inside of the tube ends as a mounting point.

Like you, i know enough to get myself into trouble so I’ll leave the coding to someone with better skills :laughing:.
I think the pseudo macro code would be something like this:
Change tool time

  • Move Z up to safe location to avoid work piece
  • store current X, Y location
  • execute Klipper PAUSE command (to move to the desired X and Y park location)
  • perform manual tools change (don’t forget to turn off rotation of router/spindle)
  • restore and move back to X and Y location (when the PAUSE command was executed)
  • turn router/spindle back on
  • execute Klipper RESUME command (at this point it should just lower Z to continue the cut job since X, Y is at the ‘resume’ location already)

We’re here to support you Neil. I can try to test this weekend if need be (I’ll have to put my Klipper setup back in but shouldn’t be a problem). Let us know if you need any aid with this. We’ll help were we can.

1 Like

Thanks Matt appreciate your support and agree on the pseudo steps. No need for you to switch back to klipper yet, I’ll take a stab first. I’m switching back and forth between klipper setup and designing 3D parts for drag chains. I’ve got some prototypes printing so I’ll try working on the resume code before work this morning.

Update: I’m close, I see how it works and am able to store the position at the point the process is paused. I just need to get the syntax right for retrieving them in the resume macro when saved in the pause macro.
I see how other functions do it and so expect to crack it tonight when I take another look.

Wasn’t too difficult and not finished yet as I want to put in some more safety coverage and not stopping the starting the spindle, but I do have it returning to X,Y before Z. I’ll paste the code here for anyone looking, and I’ll repost a more complete version later.

[gcode_macro PAUSE]
variable_restore: {'absolute': {'coordinates': True}, 'speed': 1500}
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 }
    , 'speed': printer.gcode_move.speed} %}
  SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=restore VALUE="{restore}"
  M117 Paused
  _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 pause_macro_found = True if printer['gcode_macro PAUSE'] is defined else False %}
  {% set paused_at = printer['gcode_macro PAUSE'] %}
  {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
  {% set use_fw_retract = False if not macro_found
                     else False if client.use_fw_retract is not defined
                     else True  if client.use_fw_retract|lower == 'true' and printer.firmware_retraction is defined
                     else False %} 
  {% set unretract      = 1.0  if not macro_found else client.unretract|default(1.0)|abs %}
  {% set sp_unretract   = 2100 if not macro_found else client.speed_unretract|default(35) * 60 %}
  {% set sp_move        = velocity if not macro_found else client.speed_move|default(velocity) %}
  ##### end of definitions #####

 #### move back to the saved position before resuming
   M117 Resume {paused_at.restore.pos.x},{paused_at.restore.pos.y},{paused_at.restore.pos.z}
   G90
   G1 X{paused_at.restore.pos.x} Y{paused_at.restore.pos.y} F2000
   G1 Z{paused_at.restore.pos.z} F200
  RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)}  
2 Likes

Wow. I’m not that into coding. I just tried this on my Voron Trident and it didn’t function as I expected, but like I said, I’m not that into coding to fully understand what it is supposed to do. It is funny that I was about to start playing around with figuring this out and you posted. I’m trying something a bit more simpler. It might not have a lot of safety built in like you are planning but it is simpler and I can follow along and understand it :wink:.
I just might have to reconnect my Pi (I only have a zero that will not work for cutting, but it worked for moving around) and re-test your macros. It wont be an issue since I still have the image on a SD card that I can re-insert into the Pi and I’m back to where I left it when I switched to Marlin.

EDITED: Well, I’m now running into whenever I PAUSE it moves the router/spindle to the MAX X,Y when it would be more helpful to move to the MIN X,Y (0,0) to be able to change the bit. Trying to figure out how to change the PARK location for the PAUSE.

3rd EDIT: I found my mistake - I had the PAUSE macro defined multiple times (I never looked into the mailsail.cfg file where it was original defined). Neil, your RESUME works nicely.

1 Like

Hello,
Very nice project :grin:
I’m also on klipper on an octopus BTT for my MPCNC Primo.
For the resumption of the break, it’s quite complicated, what I do is that I make a gcode for each change of tools.
You have a risk of moving your motors by changing the tool.

Sorry my English is very bad, I am French speaking.

2 Likes

Cool!
I didn’t give instructions as I’ll do that once I have it working the way I want. I just shared the code in it’s current basic state as I’d solved the initial problem and so folks following along can benefit.

2 Likes

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



Here’s the drag chain mount I’ve been working on, doesn’t require any screws or modifications to existing parts, just slides into the end of my Stainless Steel 1" tubes.
Please excuse the quality of the print, I made some tweaks and haven’t spent the time to retune

4 Likes

Good Stuff! Can’t wait to see you get this one up and going. I plan to cut foam tomorrow on mine :slight_smile:

Could you post your printer.cfg just for my curiosity

1 Like

Good luck on cutting the foam!
I split up the config sections into different files to make maintenance easier.

printer.cfg

[include mainsail.cfg]
[include Hardware/MPCNC.cfg]
[include Hardware/mcu.cfg]
[include Hardware/steppers.cfg]
[include Hardware/homing.cfg]
[include Hardware/fans.cfg]
[include Hardware/leds.cfg]
[include Hardware/thermistors.cfg]

[include Macros/mainsail_variables.cfg]
[include Macros/neils_macros/m600.cfg]

MPCNC.cfg

[printer]
kinematics: cartesian
max_velocity: 12000
max_accel: 3000
max_z_velocity: 40 #45 if needed
max_z_accel: 100

[gcode_arcs]
resolution: 1.0

mcu.cfg

[mcu]
serial: /dev/serial/by-id/usb-Klipper_stm32g0b1xx_*******

[mcu cb1]
serial: /tmp/klipper_host_mcu

stepper.cfg

[endstop_phase]

# Motor 1
[stepper_x]
step_pin: PE2
dir_pin: !PB4
enable_pin: !PC11
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PF3
position_endstop: 0
position_max: 620
homing_speed: 40
homing_positive_dir: false

# Motor 2
[stepper_x1]
step_pin: PF12
dir_pin: PF11
enable_pin: !PB3
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PF4
#position_endstop: 0
#position_max: 235
#homing_speed: 40

# Motor 4
[stepper_y]
step_pin: PD3
dir_pin: PD2
enable_pin: !PD5
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PC0
position_endstop: 0
position_max: 345
homing_speed: 40
homing_positive_dir: false

# Motor 5
[stepper_y1]
step_pin: PC9
dir_pin: !PC8
enable_pin: !PD1
microsteps: 16
rotation_distance: 32
endstop_pin: ^!PC1
#position_endstop: 0
#position_max: 235
#homing_speed: 40

# Motor 6
[stepper_z]
step_pin: PA10
dir_pin: PD15
enable_pin: !PA15
microsteps: 16
rotation_distance: 8
endstop_pin: ^!PC2
position_endstop: 1.40
position_max: 70 # 90 when legs are in first wooden board
position_min: -5.0
homing_speed: 3
second_homing_speed: 3
homing_retract_dist: 3


########################################
# TMC2209 configuration
########################################

[tmc2209 stepper_x]
uart_pin: PC10
##diag_pin: PF3
run_current: 0.700
stealthchop_threshold: 999999

[tmc2209 stepper_x1]
uart_pin: PF13
##diag_pin: PF3
run_current: 0.700
stealthchop_threshold: 999999

[tmc2209 stepper_y]
uart_pin: PD4
##diag_pin: PF4
run_current: 0.700
stealthchop_threshold: 999999

[tmc2209 stepper_y1]
uart_pin: PD0
##diag_pin: PF4
run_current: 0.700
stealthchop_threshold: 999999

[tmc2209 stepper_z]
uart_pin: PF8
##diag_pin: PF5
run_current: 0.650
stealthchop_threshold: 999999

homing.cfg

[safe_z_home]
#home_xy_position: 320,172 Center of workspace
home_xy_position: 10,10
speed: 200 # up from 100
z_hop: 2                 # Move up 10mm
z_hop_speed: 10
#move_to_previous: True

[force_move]
enable_force_move: True

fans.cfg

[fan_generic X_fans]
pin: PE6
#stepper: stepper_x

[fan_generic Y_fans]
pin: PE0
#stepper: stepper_x1

[fan_generic Z_fan]
pin: PC12
#stepper: stepper_y

[fan_generic Laser]
pin: PE5
#stepper: stepper_y1

leds.cfg

#[neopixel my_neopixel_1]
#pin: PC6

#[neopixel my_neopixel_2]
#pin: PA9

thermistors.cfg

sensor_type: temperature_mcu
max_temp: 100

[temperature_sensor cb1]
sensor_type: temperature_host
max_temp: 70

mainsail_variables.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:

m600.cfg

[gcode_macro M600]
description: Tool change
gcode:
  M117 Pausing for tool change
  PAUSE X=10 Y=10 Z_MIN=50
4 Likes