diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 7b7ae9c22fcd..026f69c9e44b 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1612,6 +1612,12 @@ #define TOOLCHANGE_ZRAISE 2 // (mm) //#define TOOLCHANGE_NO_RETURN // Never return to the previous position on tool-change + /** + * Limit the hotend offset values that may be applied. + * DUAL_X_CARRIAGE uses the X limit as a maximum offset from X2_MAX_POS. + */ + #define HOTEND_OFFSET_LIMIT { 50.0, 50.0, 3.0 } + // Retract and prime filament on tool-change //#define TOOLCHANGE_FILAMENT_SWAP #if ENABLED(TOOLCHANGE_FILAMENT_SWAP) diff --git a/Marlin/src/gcode/config/M218.cpp b/Marlin/src/gcode/config/M218.cpp index 790d7714a370..2b28ac2c6e9e 100644 --- a/Marlin/src/gcode/config/M218.cpp +++ b/Marlin/src/gcode/config/M218.cpp @@ -44,9 +44,9 @@ void GcodeSuite::M218() { const int8_t target_extruder = get_target_extruder_from_command(); if (target_extruder < 0) return; - if (parser.seenval('X')) hotend_offset[target_extruder].x = parser.value_linear_units(); - if (parser.seenval('Y')) hotend_offset[target_extruder].y = parser.value_linear_units(); - if (parser.seenval('Z')) hotend_offset[target_extruder].z = parser.value_linear_units(); + if (parser.seenval('X')) hotend_offset[target_extruder].x = constrain(parser.value_linear_units(), hotend_offset_min_x, hotend_offset_max_x); + if (parser.seenval('Y')) hotend_offset[target_extruder].y = constrain(parser.value_linear_units(), -hotend_offset_limit.y, hotend_offset_limit.y); + if (parser.seenval('Z')) hotend_offset[target_extruder].z = constrain(parser.value_linear_units(), -hotend_offset_limit.z, hotend_offset_limit.z); if (!parser.seen("XYZ")) { SERIAL_ECHO_START(); diff --git a/Marlin/src/gcode/motion/M290.cpp b/Marlin/src/gcode/motion/M290.cpp index 7bf274a18d54..577733c222f1 100644 --- a/Marlin/src/gcode/motion/M290.cpp +++ b/Marlin/src/gcode/motion/M290.cpp @@ -40,7 +40,44 @@ #if ENABLED(BABYSTEP_ZPROBE_OFFSET) - FORCE_INLINE void mod_probe_offset(const float &offs) { + FORCE_INLINE void apply_offset_steps(const uint8_t axis, const float &offs) { + if (axis == Z_AXIS && parser.boolval('P', true)) { + #if ENABLED(BABYSTEP_ZPROBE_OFFSET) + if (true + #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET) + && active_extruder == 0 + #endif + ) { + NOLESS(offs, Z_PROBE_OFFSET_RANGE_MIN - zprobe_zoffset); + NOMORE(offs, Z_PROBE_OFFSET_RANGE_MAX - zprobe_zoffset); + } + #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET) + else if (offs > hotend_offset[active_extruder].z + hotend_offset_limit.z) + offs = -hotend_offset_limit.z - zprobe_zoffset; + else if (offs < hotend_offset[active_extruder].z - hotend_offset_limit.z) + offs = hotend_offset_limit.z - hotend_offset[active_extruder].z; + #endif + mod_zprobe_zoffset(offs); + #endif + } + #if ENABLED(BABYSTEP_XY) && EXTRUDERS > 1 + else if (axis == X_AXIS) { + if (offs > hotend_offset[active_extruder].x + hotend_offset_limit.x) + offs = -hotend_offset_limit.x - zprobe_zoffset; + else if (offs < hotend_offset[active_extruder].x - hotend_offset_limit.x) + offs = hotend_offset_limit.x - hotend_offset[active_extruder].x; + } + else if (axis == Y_AXIS) { + if (offs > hotend_offset[active_extruder].y + hotend_offset_limit.y) + offs = -hotend_offset_limit.y - zprobe_zoffset; + else if (offs < hotend_offset[active_extruder].y - hotend_offset_limit.y) + offs = hotend_offset_limit.y - hotend_offset[active_extruder].y; + } + #endif + babystep.add_mm((AxisEnum)axis, offs); + } + + FORCE_INLINE void mod_zprobe_zoffset(const float &offs) { if (true #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET) && active_extruder == 0 @@ -79,17 +116,17 @@ void GcodeSuite::M290() { for (uint8_t a = X_AXIS; a <= Z_AXIS; a++) if (parser.seenval(axis_codes[a]) || (a == Z_AXIS && parser.seenval('S'))) { const float offs = constrain(parser.value_axis_units((AxisEnum)a), -2, 2); - babystep.add_mm((AxisEnum)a, offs); + apply_offset_steps(a, offs); #if ENABLED(BABYSTEP_ZPROBE_OFFSET) - if (a == Z_AXIS && (!parser.seen('P') || parser.value_bool())) mod_probe_offset(offs); + if (a == Z_AXIS && parser.boolval('P', true)) mod_zprobe_zoffset(offs); #endif } #else if (parser.seenval('Z') || parser.seenval('S')) { const float offs = constrain(parser.value_axis_units(Z_AXIS), -2, 2); - babystep.add_mm(Z_AXIS, offs); + apply_offset_steps(Z_AXIS, offs); #if ENABLED(BABYSTEP_ZPROBE_OFFSET) - if (!parser.seen('P') || parser.value_bool()) mod_probe_offset(offs); + if (parser.boolval('P', true)) mod_zprobe_zoffset(offs); #endif } #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index fcc361ad4bc5..7454c39d1e36 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -1360,6 +1360,13 @@ #undef NOZZLE_TO_PROBE_OFFSET #endif +#if ENABLED(PRUSA_MMU2) + #define E_STEPPERS 1 + #ifndef TOOLCHANGE_ZRAISE + #define TOOLCHANGE_ZRAISE 0 + #endif +#endif + /** * XYZ Bed Skew Correction */ diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index 62f6f45ce5d0..c917899a0b04 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -140,10 +140,10 @@ void menu_advanced_settings(); #if ENABLED(DUAL_X_CARRIAGE) EDIT_ITEM_FAST(float51, MSG_X_OFFSET, &hotend_offset[1].x, float(X2_HOME_POS - 25), float(X2_HOME_POS + 25), _recalc_offsets); #else - EDIT_ITEM_FAST(float52sign, MSG_X_OFFSET, &hotend_offset[1].x, -99.0, 99.0, _recalc_offsets); + EDIT_ITEM_FAST(float52sign, MSG_X_OFFSET, &hotend_offset[1].x, hotend_offset_min_x, hotend_offset_max_x, _recalc_offsets); #endif - EDIT_ITEM_FAST(float52sign, MSG_Y_OFFSET, &hotend_offset[1].y, -99.0, 99.0, _recalc_offsets); - EDIT_ITEM_FAST(float52sign, MSG_Z_OFFSET, &hotend_offset[1].z, Z_PROBE_LOW_POINT, 10.0, _recalc_offsets); + EDIT_ITEM_FAST(float52sign, MSG_Y_OFFSET, &hotend_offset[1].y, -hotend_offset_limit.y, hotend_offset_limit.y, _recalc_offsets); + EDIT_ITEM_FAST(float52sign, MSG_Z_OFFSET, &hotend_offset[1].z, MIN(Z_PROBE_LOW_POINT, -hotend_offset_limit.z), hotend_offset_limit.z, _recalc_offsets); #if ENABLED(EEPROM_SETTINGS) ACTION_ITEM(MSG_STORE_EEPROM, lcd_store_settings); #endif diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 8182f23ae04e..c07b9a4be381 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -621,11 +621,20 @@ void restore_feedrate_and_scaling() { #endif - #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z) - NOLESS(target.z, soft_endstop.min.z); - #endif - #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z) - NOMORE(target.z, soft_endstop.max.z); + #if HAS_HOTEND_OFFSET + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z) + NOLESS(target.z, soft_endstop.min.z); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z) + NOMORE(target.z, soft_endstop.max.z); + #endif + #else + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z) + NOLESS(target.z, soft_endstop.min.z); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z) + NOMORE(target.z, soft_endstop.max.z); + #endif #endif } diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 8b9775ce9830..8cf4fce2462b 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -406,3 +406,16 @@ FORCE_INLINE bool position_is_reachable_by_probe(const xy_pos_t &pos) { return p #if HAS_M206_COMMAND void set_home_offset(const AxisEnum axis, const float v); #endif + +#if HAS_HOTEND_OFFSET + constexpr xyz_float_t hotend_offset_limit = HOTEND_OFFSET_LIMIT; + constexpr ab_float_t minmax_base = { + #if ENABLED(DUAL_X_CARRIAGE) + MIN(X2_HOME_POS, X2_MAX_POS), MAX(X2_HOME_POS, X2_MAX_POS) + #else + 0, 0 + #endif + }; + constexpr float hotend_offset_min_x = minmax_base.a - hotend_offset_limit.x, + hotend_offset_max_x = minmax_base.b + hotend_offset_limit.x; +#endif