diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index 8446235807..deb2a2fc81 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -143,18 +143,15 @@ inline void park_above_object(measurements_t &m, const float uncertainty) { } #if HOTENDS > 1 - inline void set_nozzle(measurements_t &m, const uint8_t extruder) { if (extruder != active_extruder) { park_above_object(m, CALIBRATION_MEASUREMENT_UNKNOWN); tool_change(extruder); } } +#endif - inline void reset_nozzle_offsets() { - constexpr float tmp[XYZ][HOTENDS] = { HOTEND_OFFSET_X, HOTEND_OFFSET_Y, HOTEND_OFFSET_Z }; - LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp[i][e]; - } +#if HAS_HOTEND_OFFSET inline void normalize_hotend_offsets() { for (uint8_t e = 1; e < HOTENDS; e++) { @@ -167,7 +164,7 @@ inline void park_above_object(measurements_t &m, const float uncertainty) { hotend_offset[Z_AXIS][0] = 0; } -#endif // HOTENDS > 1 +#endif inline bool read_calibration_pin() { #if HAS_CALIBRATION_PIN @@ -526,7 +523,7 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const probe_sides(m, uncertainty); // Adjust the hotend offset - #if HOTENDS > 1 + #if HAS_HOTEND_OFFSET #if HAS_X_CENTER hotend_offset[X_AXIS][extruder] += m.pos_error[X_AXIS]; #endif @@ -534,7 +531,6 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const hotend_offset[Y_AXIS][extruder] += m.pos_error[Y_AXIS]; #endif hotend_offset[Z_AXIS][extruder] += m.pos_error[Z_AXIS]; - normalize_hotend_offsets(); #endif @@ -565,8 +561,11 @@ inline void calibrate_all_toolheads(measurements_t &m, const float uncertainty) HOTEND_LOOP() calibrate_toolhead(m, uncertainty, e); - #if HOTENDS > 1 + #if HAS_HOTEND_OFFSET normalize_hotend_offsets(); + #endif + + #if HOTENDS > 1 set_nozzle(m, 0); #endif } @@ -585,8 +584,8 @@ inline void calibrate_all_toolheads(measurements_t &m, const float uncertainty) inline void calibrate_all() { measurements_t m; - #if HOTENDS > 1 - reset_nozzle_offsets(); + #if HAS_HOTEND_OFFSET + reset_hotend_offsets(); #endif TEMPORARY_BACKLASH_CORRECTION(1.0f); diff --git a/Marlin/src/gcode/feature/pause/M125.cpp b/Marlin/src/gcode/feature/pause/M125.cpp index 796bd79a1b..cc6fd0438d 100644 --- a/Marlin/src/gcode/feature/pause/M125.cpp +++ b/Marlin/src/gcode/feature/pause/M125.cpp @@ -68,8 +68,8 @@ void GcodeSuite::M125() { if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); #if HAS_HOTEND_OFFSET && DISABLED(DUAL_X_CARRIAGE) && DISABLED(DELTA) - park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0); - park_point.y += (active_extruder ? hotend_offset[Y_AXIS][active_extruder] : 0); + park_point.x += hotend_offset[X_AXIS][active_extruder]; + park_point.y += hotend_offset[Y_AXIS][active_extruder]; #endif #if ENABLED(SDSUPPORT) diff --git a/Marlin/src/gcode/feature/pause/M600.cpp b/Marlin/src/gcode/feature/pause/M600.cpp index d42df6f5ab..6ca278c10f 100644 --- a/Marlin/src/gcode/feature/pause/M600.cpp +++ b/Marlin/src/gcode/feature/pause/M600.cpp @@ -110,8 +110,8 @@ void GcodeSuite::M600() { if (parser.seenval('Y')) park_point.y = parser.linearval('Y'); #if HAS_HOTEND_OFFSET && DISABLED(DUAL_X_CARRIAGE) && DISABLED(DELTA) - park_point.x += (active_extruder ? hotend_offset[X_AXIS][active_extruder] : 0); - park_point.y += (active_extruder ? hotend_offset[Y_AXIS][active_extruder] : 0); + park_point.x += hotend_offset[X_AXIS][active_extruder]; + park_point.y += hotend_offset[Y_AXIS][active_extruder]; #endif #if ENABLED(MMU2_MENUS) diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 6995fa57d3..ab973e9e2c 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -397,20 +397,6 @@ bool MarlinUI::get_blink() { #endif #endif -#if HAS_PRINT_PROGRESS - uint8_t MarlinUI::get_progress() { - #if ENABLED(LCD_SET_PROGRESS_MANUALLY) - uint8_t &progress = progress_bar_percent; - #else - uint8_t progress = 0; - #endif - #if ENABLED(SDSUPPORT) - if (IS_SD_PRINTING()) progress = card.percentDone(); - #endif - return progress; - } -#endif - void MarlinUI::status_screen() { #if HAS_LCD_MENU @@ -1321,4 +1307,18 @@ void MarlinUI::update() { set_status_P(msg, -1); } + #if HAS_PRINT_PROGRESS + uint8_t MarlinUI::get_progress() { + #if ENABLED(LCD_SET_PROGRESS_MANUALLY) + uint8_t &progress = progress_bar_percent; + #else + uint8_t progress = 0; + #endif + #if ENABLED(SDSUPPORT) + if (IS_SD_PRINTING()) progress = card.percentDone(); + #endif + return progress; + } + #endif + #endif // HAS_SPI_LCD || EXTENSIBLE_UI diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp index e69df2f0df..13eacae04c 100644 --- a/Marlin/src/module/configuration_store.cpp +++ b/Marlin/src/module/configuration_store.cpp @@ -2028,15 +2028,7 @@ void MarlinSettings::reset() { #endif #if HAS_HOTEND_OFFSET - constexpr float tmp4[XYZ][HOTENDS] = { HOTEND_OFFSET_X, HOTEND_OFFSET_Y, HOTEND_OFFSET_Z }; - static_assert( - tmp4[X_AXIS][0] == 0 && tmp4[Y_AXIS][0] == 0 && tmp4[Z_AXIS][0] == 0, - "Offsets for the first hotend must be 0.0." - ); - LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp4[i][e]; - #if ENABLED(DUAL_X_CARRIAGE) - hotend_offset[X_AXIS][1] = MAX(X2_HOME_POS, X2_MAX_POS); - #endif + reset_hotend_offsets(); #endif #if EXTRUDERS > 1 diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index c9973816c4..44266e24b1 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -106,6 +106,17 @@ float destination[XYZE]; // = { 0 } // Extruder offsets #if HAS_HOTEND_OFFSET float hotend_offset[XYZ][HOTENDS]; // Initialized by settings.load() + void reset_hotend_offsets() { + constexpr float tmp[XYZ][HOTENDS] = { HOTEND_OFFSET_X, HOTEND_OFFSET_Y, HOTEND_OFFSET_Z }; + static_assert( + tmp[X_AXIS][0] == 0 && tmp[Y_AXIS][0] == 0 && tmp[Z_AXIS][0] == 0, + "Offsets for the first hotend must be 0.0." + ); + LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp[i][e]; + #if ENABLED(DUAL_X_CARRIAGE) + hotend_offset[X_AXIS][1] = MAX(X2_HOME_POS, X2_MAX_POS); + #endif + } #endif // The feedrate for the current move, often used as the default if @@ -130,11 +141,23 @@ const float homing_feedrate_mm_s[XYZ] PROGMEM = { float cartes[XYZ]; #if IS_KINEMATIC + float delta[ABC]; -#endif -#if HAS_SCARA_OFFSET - float scara_home_offset[ABC]; + #if HAS_SCARA_OFFSET + float scara_home_offset[ABC]; + #endif + + #if HAS_SOFTWARE_ENDSTOPS + float soft_endstop_radius, soft_endstop_radius_2; + #elif IS_SCARA + constexpr float soft_endstop_radius = SCARA_PRINTABLE_RADIUS, + soft_endstop_radius_2 = sq(SCARA_PRINTABLE_RADIUS); + #else // DELTA + constexpr float soft_endstop_radius = DELTA_PRINTABLE_RADIUS, + soft_endstop_radius_2 = sq(DELTA_PRINTABLE_RADIUS); + #endif + #endif /** @@ -440,47 +463,6 @@ void clean_up_after_endstop_or_probe_move() { float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS }, soft_endstop_max[XYZ] = { X_MAX_BED, Y_MAX_BED, Z_MAX_POS }; - #if IS_KINEMATIC - float soft_endstop_radius, soft_endstop_radius_2; - #endif - - /** - * Constrain the given coordinates to the software endstops. - * - * For DELTA/SCARA the XY constraint is based on the smallest - * radius within the set software endstops. - */ - void clamp_to_software_endstops(float target[XYZ]) { - if (!soft_endstops_enabled) return; - #if IS_KINEMATIC - const float dist_2 = HYPOT2(target[X_AXIS], target[Y_AXIS]); - if (dist_2 > soft_endstop_radius_2) { - const float ratio = soft_endstop_radius / SQRT(dist_2); // 200 / 300 = 0.66 - target[X_AXIS] *= ratio; - target[Y_AXIS] *= ratio; - } - #else - #if ENABLED(MIN_SOFTWARE_ENDSTOP_X) - NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]); - #endif - #if ENABLED(MIN_SOFTWARE_ENDSTOP_Y) - NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]); - #endif - #if ENABLED(MAX_SOFTWARE_ENDSTOP_X) - NOMORE(target[X_AXIS], soft_endstop_max[X_AXIS]); - #endif - #if ENABLED(MAX_SOFTWARE_ENDSTOP_Y) - NOMORE(target[Y_AXIS], soft_endstop_max[Y_AXIS]); - #endif - #endif - #if ENABLED(MIN_SOFTWARE_ENDSTOP_Z) - NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]); - #endif - #if ENABLED(MAX_SOFTWARE_ENDSTOP_Z) - NOMORE(target[Z_AXIS], soft_endstop_max[Z_AXIS]); - #endif - } - /** * Software endstops can be used to monitor the open end of * an axis that has a hardware endstop on the other end. Or @@ -490,7 +472,11 @@ void clean_up_after_endstop_or_probe_move() { * the software endstop positions must be refreshed to remain * at the same positions relative to the machine. */ - void update_software_endstops(const AxisEnum axis) { + void update_software_endstops(const AxisEnum axis + #if HAS_HOTEND_OFFSET + , const uint8_t old_tool_index/*=0*/, const uint8_t new_tool_index/*=0*/ + #endif + ) { #if ENABLED(DUAL_X_CARRIAGE) @@ -499,7 +485,7 @@ void clean_up_after_endstop_or_probe_move() { // In Dual X mode hotend_offset[X] is T1's home position const float dual_max_x = MAX(hotend_offset[X_AXIS][1], X2_MAX_POS); - if (active_extruder != 0) { + if (new_tool_index != 0) { // T1 can move from X2_MIN_POS to X2_MAX_POS or X2 home position (whichever is larger) soft_endstop_min[X_AXIS] = X2_MIN_POS; soft_endstop_max[X_AXIS] = dual_max_x; @@ -538,6 +524,22 @@ void clean_up_after_endstop_or_probe_move() { default: break; } + #elif HAS_HOTEND_OFFSET + + // Software endstops are relative to the tool 0 workspace, so + // the movement limits must be shifted by the tool offset to + // retain the same physical limit when other tools are selected. + if (old_tool_index != new_tool_index) { + const float offs = hotend_offset[axis][new_tool_index] - hotend_offset[axis][old_tool_index]; + soft_endstop_min[axis] += offs; + soft_endstop_max[axis] += offs; + } + else { + const float offs = hotend_offset[axis][active_extruder]; + soft_endstop_min[axis] = base_min_pos(axis) + offs; + soft_endstop_max[axis] = base_max_pos(axis) + offs; + } + #else soft_endstop_min[axis] = base_min_pos(axis); @@ -554,7 +556,59 @@ void clean_up_after_endstop_or_probe_move() { #endif } -#endif +#endif // HAS_SOFTWARE_ENDSTOPS + +/** + * Constrain the given coordinates to the software endstops. + * + * For DELTA/SCARA the XY constraint is based on the smallest + * radius within the set software endstops. + */ +void clamp_to_software_endstops(float target[XYZ]) { + + if (!soft_endstops_enabled) return; + + #if IS_KINEMATIC + + #if HAS_HOTEND_OFFSET && ENABLED(DELTA) + // The effector center position will be the target minus the hotend offset. + const float offx = hotend_offset[X_AXIS][active_extruder], offy = hotend_offset[Y_AXIS][active_extruder]; + #else + // SCARA needs to consider the angle of the arm through the entire move, so for now use no tool offset. + constexpr float offx = 0, offy = 0; + #endif + + const float dist_2 = HYPOT2(target[X_AXIS] - offx, target[Y_AXIS] - offy); + if (dist_2 > soft_endstop_radius_2) { + const float ratio = (soft_endstop_radius) / SQRT(dist_2); // 200 / 300 = 0.66 + target[X_AXIS] *= ratio; + target[Y_AXIS] *= ratio; + } + + #else + + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_X) + NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_X) + NOMORE(target[X_AXIS], soft_endstop_max[X_AXIS]); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Y) + NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Y) + NOMORE(target[Y_AXIS], soft_endstop_max[Y_AXIS]); + #endif + + #endif + + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z) + NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z) + NOMORE(target[Z_AXIS], soft_endstop_max[Z_AXIS]); + #endif +} #if !UBL_SEGMENTED #if IS_KINEMATIC diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 275fafe74e..e14892d738 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -90,10 +90,6 @@ extern int16_t feedrate_percentage; constexpr uint8_t active_extruder = 0; #endif -#if HAS_HOTEND_OFFSET - extern float hotend_offset[XYZ][HOTENDS]; -#endif - FORCE_INLINE float pgm_read_any(const float *p) { return pgm_read_float(p); } FORCE_INLINE signed char pgm_read_any(const signed char *p) { return pgm_read_byte(p); } @@ -115,19 +111,30 @@ XYZ_DEFS(signed char, home_dir, HOME_DIR); #define update_workspace_offset(x) NOOP #endif +#if HAS_HOTEND_OFFSET + extern float hotend_offset[XYZ][HOTENDS]; + void reset_hotend_offsets(); +#else + constexpr float hotend_offset[XYZ][HOTENDS] = { { 0 }, { 0 }, { 0 } }; +#endif + #if HAS_SOFTWARE_ENDSTOPS extern bool soft_endstops_enabled; extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ]; - void clamp_to_software_endstops(float target[XYZ]); - void update_software_endstops(const AxisEnum axis); + void update_software_endstops(const AxisEnum axis + #if HAS_HOTEND_OFFSET + , const uint8_t old_tool_index=0, const uint8_t new_tool_index=0 + #endif + ); #else - constexpr bool soft_endstops_enabled = false; - constexpr float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS }, - soft_endstop_max[XYZ] = { X_MAX_BED, Y_MAX_BED, Z_MAX_POS }; - #define clamp_to_software_endstops(x) NOOP - #define update_software_endstops(x) NOOP + constexpr bool soft_endstops_enabled = true; + constexpr float soft_endstop_min[XYZ] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS }, + soft_endstop_max[XYZ] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS }; + #define update_software_endstops(...) NOOP #endif +void clamp_to_software_endstops(float target[XYZ]); + void report_current_position(); inline void set_current_from_destination() { COPY(current_position, destination); } diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index dc7458a257..c383dae753 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1626,7 +1626,7 @@ void Planner::synchronize() { if (reversing == (error_correction < 0)) { if (segment_proportion == 0) segment_proportion = MIN(1.0f, block->millimeters / backlash_smoothing_mm); - error_correction *= segment_proportion; + error_correction = ceil(segment_proportion * error_correction); } else error_correction = 0; // Don't take up any backlash in this segment, as it would subtract steps diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 5094e5f5b1..5f1aced021 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -735,23 +735,8 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n const float old_feedrate_mm_s = fr_mm_s > 0.0 ? fr_mm_s : feedrate_mm_s; feedrate_mm_s = fr_mm_s > 0.0 ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S; - #if ENABLED(DUAL_X_CARRIAGE) - - #if HAS_SOFTWARE_ENDSTOPS - // Update the X software endstops early - active_extruder = tmp_extruder; - update_software_endstops(X_AXIS); - active_extruder = !tmp_extruder; - const float minx = soft_endstop_min[X_AXIS], maxx = soft_endstop_max[X_AXIS]; - #else - // No software endstops? Use the configured limits - const float minx = tmp_extruder ? X2_MIN_POS : X1_MIN_POS, - maxx = tmp_extruder ? X2_MAX_POS : X1_MAX_POS; - #endif - - // Don't move the new extruder out of bounds - if (!WITHIN(current_position[X_AXIS], minx, maxx)) no_move = true; - + #if HAS_SOFTWARE_ENDSTOPS && ENABLED(DUAL_X_CARRIAGE) + update_software_endstops(X_AXIS, active_extruder, tmp_extruder); #endif set_destination_from_current(); @@ -772,7 +757,7 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n planner.synchronize(); } - #if HOTENDS > 1 + #if HAS_HOTEND_OFFSET #if ENABLED(DUAL_X_CARRIAGE) constexpr float xdiff = 0; #else @@ -914,10 +899,6 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n enable_solenoid_on_active_extruder(); #endif - #if HAS_SOFTWARE_ENDSTOPS && ENABLED(DUAL_X_CARRIAGE) - update_software_endstops(X_AXIS); - #endif - #if ENABLED(MK2_MULTIPLEXER) if (tmp_extruder >= E_STEPPERS) return invalid_extruder_error(tmp_extruder); select_multiplexed_stepper(tmp_extruder); diff --git a/Marlin/src/pins/pins_EINSY_RETRO.h b/Marlin/src/pins/pins_EINSY_RETRO.h index f24235763d..40db378f43 100644 --- a/Marlin/src/pins/pins_EINSY_RETRO.h +++ b/Marlin/src/pins/pins_EINSY_RETRO.h @@ -176,8 +176,8 @@ #define BTN_EN2 19 #else #define LCD_PINS_RS 82 - #define LCD_PINS_ENABLE 18 - #define LCD_PINS_D4 19 + #define LCD_PINS_ENABLE 18 // On 0.6b, use 61 + #define LCD_PINS_D4 19 // On 0.6b, use 59 #define LCD_PINS_D5 70 #define LCD_PINS_D6 85 #define LCD_PINS_D7 71